OverviewICU has two specific calendar classes used for parsing and formatting Calendar information correctly:
The Calendar class is designed to support other calendar systems in the future, such as the Islamic, Persian, Hebrew, Chinese, and Japanese calendars. If these calendar systems are introduced, the current code automatically accepts them (where appropriate), so long as the factory methods (§) are used.
Calendar locale and keyword handlingWhen 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, except for the compatibility locales th_TH_TRADITIONAL and ja_JP_TRADITIONAL. 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.
UsageThis section discusses how to use the Calendar class and the GregorianCalendar subclass. CalendarCalendar 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:
Representation and ConversionThe 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.
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 ArithmeticArithmetic 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 UDates 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:
Context ManagementA 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:
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 MethodsLike 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().
Gregorian CalendarThe 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 can not 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:
DisambiguationWhen computing a UDate from fields, two 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), or there might be inconsistent information (such as "Tuesday, July 15, 1996" -— July 15, 1996, is actually a Monday).
Programming ExamplesProgramming for calendar examples in C++, C, and Java . |