---
layout: default
title: Calendar Services
nav_order: 1
parent: Date/Time
---
<!--
© 2020 and later: Unicode, Inc. and others.
License & terms of use: http://www.unicode.org/copyright.html
-->

# Calendar Classes
{: .no_toc }

## Contents
{: .no_toc .text-delta }

1. TOC
{:toc}

---

## Overview

ICU has two main calendar classes used for parsing and formatting Calendar
information correctly:

1.  `Calendar`

    An abstract base class that defines the calendar API. This API supports
    UDate to fields conversion and field arithmetic.

2.  `GregorianCalendar`

    A concrete subclass of `Calendar` that implements the standard calendar used
    today internationally.

In addition to these, ICU has other `Calendar` subclasses to support
non-gregorian calendars including:

*   Buddhist

*   Chinese

*   Coptic

*   Ethiopic

*   Hebrew

*   Indian

*   Islamic

*   Japanese

*   Persian

The `Calendar` class is designed to support additional calendar systems in the future.

> :point_right: **Note**: *`Calendar` classes are related to `UDate`, the `TimeZone` classes, and the `DateFormat`
classes.*

### Calendar locale and keyword handling

When a calendar object is created, via either `Calendar::create()`, or
`ucal_open()`, or indirectly within a date formatter, ICU looks up the 'default'
calendar type for that locale. At present, all locales default to a Gregorian
calendar. If the "calendar" keyword is supplied, this value will
override the default for that locale.

For instance, `Calendar::createInstance("fr_FR", status)` will create a Gregorian calendar,
but `Calendar::createInstance("fr_FR@calendar=buddhist")` will create a Buddhist calendar.

It is an error to use an invalid calendar type. It will produce a missing resource error.

> :point_right: **Note**: *As of ICU 2.8, the above description applies to ICU4J only. ICU4J will have
this behavior in 3.0*

## Usage

This section discusses how to use the `Calendar` class and the `GregorianCalendar` subclass.

### Calendar

`Calendar` is an abstract base class. It defines common protocols for a hierarchy
of classes. Concrete subclasses of `Calendar`, for example the `GregorianCalendar`
class, define specific operations that correspond to a real-world calendar
system. `Calendar` objects (instantiations of concrete subclasses of `Calendar`),
embody state that represents a specific context. They correspond to a real-world
locale. They also contain state that specifies a moment in time.

The API defined by `Calendar` encompasses multiple functions:

1.  Representation of a specific time as a `UDate`

2.  Representation of a specific time as a set of integer fields, such as `YEAR`,
    `MONTH`, `HOUR`, etc.

3.  Conversion from `UDate` to fields

4.  Conversion from fields to `UDate`

5.  Field arithmetic, including adding, rolling, and field difference

6.  Context management

7.  Factory methods

8.  Miscellaneous: field meta-information, time comparison

#### Representation and Conversion

The basic function of the `Calendar` class is to convert between a `UDate` value and
a set of integer fields. A `UDate` value is stored as UTC time in milliseconds,
which means it is calendar and time zone independent. `UDate` is the most compact
and portable way to store and transmit a date and time. `Integer` field values, on
the other hand, depend on the calendar system (that is, the concrete subclass of
`Calendar`) and the calendar object's context state.

> :point_right: **Note**: *`Integer` field values are needed when implementing a human interface that must
display or input a date and/or time.*

At any given time, a calendar object uses (when `DateFormat` is not sufficient)
either its internal `UDate` or its integer fields (depending on which has been set
most recently via `setTime()` or `set()`), to represent a specific date and time.
Whatever the current internal representation, when the caller requests a `UDate`
or an integer field it is computed if necessary. The caller need never trigger
the conversion explicitly. The caller must perform a conversion to set either
the `UDate` or the integer fields, and then retrieve the desired data. This also
applies in situations where the caller has some integer fields and wants to
obtain others.

#### Field Arithmetic

Arithmetic with `UDate` values is straightforward. Since the values are
millisecond scalar values, direct addition and subtraction is all that is
required. Arithmetic with integer fields is more complicated. For example, what
is the date June 4, 1999 plus 300 days? `Calendar` defines three basic methods (in
several variants) that perform field arithmetic: `add()`, `roll()`, and
`fieldDifference()`.

The `add()` method adds positive or negative values to a specified field. For
example, calling `add(Calendar::MONTH, 2)` on a `GregorianCalendar` object set to
March 15, 1999 sets the calendar to May 15, 1999. The `roll()` method is similar,
but does not modify fields that are larger. For example, calling
`roll(Calendar::HOUR, n)` changes the hour that a calendar is set to without
changing the day. Calling `roll(Calendar::MONTH, n)` changes the month without
changing the year.

The `fieldDifference()` method is the inverse of the `add()` method. It computes the
difference between a calendar's currently set time and a specified `UDate` in
terms of a specified field. Repeated calls to `fieldDifference()` compute the
difference between two `UDate` objects in terms of whatever fields the caller specifies
(for example, years, months, days, and hours). If the `add()` method is called
with the results of `fieldDifference(when, n)`, then the calendar is moved toward
field by field.

This is demonstrated in the following example:

```c++
Calendar cal = Calendar.getInstance();
cal.set(2000, Calendar.MARCH, 15);
Date date = new Date(2000-1900, Calendar.JULY, 4);
int yearDiff = cal.fieldDifference(date, Calendar.YEAR); // yearDiff <= 0
int monthDiff = cal.fieldDifference(date, Calendar.MONTH); // monthDiff ;<= 3
// At this point cal has been advanced 3 months to June 15, 2000.
int dayDiff = cal.fieldDifference(date, Calendar.DAY_OF_MONTH); // dayDiff ;<=19
// At this point cal has been advanced 19 days to July 4, 2000.
```

#### Context Management

A `Calendar` object performs its computations within a specific context. The
context affects the results of conversions and arithmetic computations. When a
`Calendar` object is created, it establishes its context using either default
values or values specified by the caller:

1.  Locale-specific week data, including the first day of the week and the
    minimal days in the first week. Initially, this is retrieved from the locale
    resource data for the specified locale, or if none is specified, for the
    default locale.

2.  A `TimeZone` object. Initially, this is set to the specified zone object, or
    if none is specified, the default `TimeZone`.

The context of a `Calendar` object can be queried after the calendar is created
using calls such as `getMinimalDaysInFirstWeek()`, `getFirstDayOfWeek()`, and
`getTimeZone()`. The context can be changed using calls such as
`setMinimalDaysInFirstWeek()`, `setFirstDayOfWeek()`, and `setTimeZone()`.

#### Factory Methods

Like other format classes, the best way to create a calendar object is by using
one of the factory methods. These are static methods on the `Calendar` class that
create and return an instance of a concrete subclass. Factory methods should be
used to enable the code to obtain the correct calendar for a locale without
having to know specific details. The factory methods on `Calendar` are named
`createInstance()`.

***`MONTH` field***
> :point_right: **Note**: *Calendar numbers months starting from zero, so calling `cal.set(1998, 3, 5)`
sets cal to April 15, 1998, not March 15, 1998. This follows the Java
convention. To avoid mistakes, use the constants defined in the `Calendar` class
for the months and days of the week. For example, `cal.set(1998, Calendar::APRIL, 15)`.*

#### Ambiguous Wall Clock Time Resolution

When the time offset from UTC has changed, it produces an ambiguous time slot
around the transition. For example, many US locations observe daylight saving
time. On the date of transition to daylight saving time in US, wall clock time
jumps from 12:59 AM (standard) to 2:00 AM (daylight). Therefore, wall clock
times from 1:00 AM to 1:59 AM do not exist on the date. When the input wall time
falls into this missing time slot, the ICU Calendar resolves the time using the
UTC offset before the transition by default. In this example, 1:30 AM is
interpreted as 1:30 AM standard time (non-exist), so the final result will be
2:30 AM daylight time.
On the date of transition back to standard time, wall clock time is moved back
one hour at 2:00 AM. So wall clock times from 1:00 AM to 1:59 AM occur twice. In
this case, the ICU Calendar resolves the time using the UTC offset after the
transition by default. For example, 1:30 AM on the date is resolved as 1:30 AM
standard time.
Ambiguous wall clock time resolution behaviors can be customized by Calendar
APIs `setRepeatedWallTimeOption()` and `setSkippedWallTimeOption()`. These APIs are
available in ICU 49 or later versions.

### `GregorianCalendar`

The `GregorianCalendar` class implements two calendar systems, the Gregorian
calendar and the Julian calendar. These calendar systems are closely related,
differing mainly in their definition of the leap year. The Julian calendar has
leap years every four years; the Gregorian calendar refines this by excluding
century years that are not divisible by 400. `GregorianCalendar` defines two eras,
BC (B.C.E.) and AD (C.E.).

Historically, most western countries used the Julian calendar until the 16th to
20th century, depending on the country. They then switched to the Gregorian
calendar. The `GregorianCalendar` class mirrors this behavior by defining a
cut-over date. Before this date, the Julian calendar algorithms are used. After
it, the Gregorian calendar algorithms are used. By default, the cut-over date is
set to October 4, 1582 C.E., which reflects the time when countries first began
adopting the Gregorian calendar. The `GregorianCalendar` class does not attempt
historical accuracy beyond this behavior, and does not vary its cut-over date by
locale. However, users can modify the cut-over date by using the
`setGregorianChange()` method.

Code that is written correctly instantiates calendar objects using the Calendar
factory methods, and therefore holds a `Calendar*` pointer. Such code cannot
directly access the GregorianCalendar-specific methods not present in `Calendar`.
The correct way to handle this is to perform a dynamic cast, after testing the
type of the object using `getDynamicClassID()`. For example:

```c++
void setCutover(Calendar *cal, UDate myCutover) {
    if (cal->getDynamicClassID() == GregorianCalendar::getStaticClassID()) {
        GregorianCalendar *gc = (GregorianCalendar*)cal;
        gc->setGregorianChange(myCutover, status);
    }
}
```

> :point_right: **Note**: *This is a general technique that should be used throughout ICU in conjunction
with the factory methods.*

### Disambiguation

When computing a `UDate` from fields, some special circumstances can arise. There
might be insufficient information to compute the `UDate` (such as only year and
month but no day in the month), there might be inconsistent information (such as
"Tuesday, July 15, 1996" -— July 15, 1996, is actually a Monday), or the input
time might be ambiguous because of time zone transition.

1.  **Insufficient Information**
    ICU Calendar uses the default field values to specify missing fields. The
    default for a field is the same as that of the start of the epoch (that is,
    `YEAR = 1970`, `MONTH = JANUARY`, `DAY_OF_MONTH = 1`).

2.  **Inconsistent Information**
    If fields conflict, the calendar gives preference to fields set more
    recently. For example, when determining the day, the calendar looks for one
    of the following combinations of fields:
    `MONTH + DAY_OF_MONTH`
    `MONTH + WEEK_OF_MONTH + DAY_OF_WEEK`
    `MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK`
    `DAY_OF_YEAR`
    `DAY_OF_WEEK + WEEK_OF_YEAR`
    For the time of day, the calendar looks for one of the following
    combinations of fields:
    `HOUR_OF_DAY`
    `AM_PM + HOUR`

3.  **Ambiguous Wall Clock Time**
    When time offset from UTC has changed, it produces ambiguous time slot
    around the transition. For example, many US locations observe daylight
    saving time. On the date switching to daylight saving time in US, wall clock
    time jumps from 1:00 AM (standard) to 2:00 AM (daylight). Therefore, wall
    clock time from 1:00 AM to 1:59 AM do not exist on the date. When the input
    wall time fall into this missing time slot, the ICU Calendar resolves the
    time using the UTC offset before the transition by default. In this example,
    1:30 AM is interpreted as 1:30 AM standard time (non-exist), so the final
    result will be 2:30 AM daylight time.
    On the date switching back to standard time, wall clock time is moved back
    one hour at 2:00 AM. So wall clock time from 1:00 AM to 1:59 AM occur twice.
    In this case, the ICU Calendar resolves the time using the UTC offset after
    the transition by default. For example, 1:30 AM on the date is resolved as
    1:30 AM standard time.

***Options for Ambiguous Time Resolution***
> :point_right: **Note**: *Ambiguous wall clock time resolution behaviors can be customized by Calendar APIs `setRepeatedTimeOption()` and `setSkippedTimeOption()`. These methods are available in ICU 49 or later versions.*

***`WEEK_OF_YEAR` field***
> :point_right: **Note**: *Values calculated for the `WEEK_OF_YEAR` field range from 1 to 53. Week 1 for a year is the first week that contains at least `getMinimalDaysInFirstWeek()` days from that year. It depends on the values of `getMinimalDaysInFirstWeek()`, `getFirstDayOfWeek()`, and the day of the week of January 1. Weeks between week 1 of one year and week 1 of the following year are numbered sequentially from 2 to 52 or 53 (if needed).
For example, January 1, 1998 was a Thursday. If `getFirstDayOfWeek()` is `MONDAY`
and `getMinimalDaysInFirstWeek()` is `4` (these are the values reflecting ISO 8601
and many national standards), then week 1 of 1998 starts on December 29, 1997,
and ends on January 4, 1998. However, if `getFirstDayOfWeek()` is `SUNDAY`, then
week 1 of 1998 starts on January 4, 1998, and ends on January 10, 1998. The
first three days of 1998 are then part of week 53 of 1997.*

## Programming Examples

Programming for calendar [examples in C++, C, and Java](examples.md) .
