Calendars encapsulate information about systems of reckoning time in which the beginning, length, and divisions of a year are defined. They provide information about the calendar and support for calendrical computations such as determining the range of a given calendrical unit and adding units to a given absolute time. This article describes the basic features of the NSCalendar
class.
In Mac OS X version 10.4 and later, the NSCalendar
class provides an Objective-C implementation of calendars for Cocoa. NSCalendar
is closely associated with the NSDateComponents
class, instances of which describe the components required for calendrical computations.
In a calendar, day, week, weekday, month, and year numbers are generally 1-based, but there may be calendar-specific exceptions. Ordinal numbers, where they occur, are 1-based. Some calendars represented by this API may have to map their basic unit concepts into year/month/week/day/… nomenclature. For example, a calendar composed of 4 quarters in a year instead of 12 months uses the “month” unit to represent quarters. The particular values of the unit are defined by each calendar, and are not necessarily “consistent with” or have a “correspondence with,” values for that unit in another calendar.
Creating a Calendar
Calendrical Calculations
You create a calendar object by specifying an identifier for the calendar you want. Mac OS X provides data for several different calendars—Buddhist, Chinese, Gregorian, Hebrew, Islamic, and Japanese—specified by constants in NSLocale
. You can get the calendar for the user's preferred locale (or in general from any NSLocale
object) using the key NSLocaleCalendar
, or most easily using the NSCalendar
method currentCalendar
. The following code fragment shows how to create a calendar object for the Japanese calendar, and for the current user:
NSCalendar *japaneseCalendar = [[NSCalendar alloc] |
initWithCalendarIdentifier:NSJapaneseCalendar]; |
NSCalendar *usersCalendar = [[NSCalendar alloc] initWithCalendarIdentifier: |
[[NSLocale currentLocale] objectForKey:NSLocaleCalendar]]; |
NSCalendar *currentCalendar = [NSCalendar currentCalendar]; |
Here, usersCalendar
and currentCalendar
are equal, although they are different objects.
To do calendar arithmetic, you use NSDate
objects in conjunction with a calendar. For example, to convert between a decomposed date in one calendar and another calendar, you must first convert the decomposed elements to a date using the first calendar, then decompose it using the second. NSDate
provides the absolute scale and epoch for dates and times, which can then be rendered into a particular calendar, for calendrical computations or user display.
Two NSCalendar
methods—dateFromComponents:
and dateByAddingComponents:toDate:options:
—take as a parameter an NSDateComponents
object that describes the calendrical components required for the computation. You can provide as many components as you need (or choose to). When there is incomplete information to compute an absolute time, default values similar to 0
and 1
are usually chosen by a calendar, but this is a calendar-specific choice. If you provide inconsistent information, calendar-specific disambiguation is performed (which may involve ignoring one or more of the parameters).
The methods (components:fromDate:
and components:fromDate:toDate:options:
) take a bit mask parameter that specifies which components to calculate when returning an NSDateComponents
object. The bit mask is composed of NSCalendarUnit
constants. You can use components:fromDate:toDate:options:
to conveniently determine the temporal difference between two dates in units other than seconds (which you could calculate with the NSDate
method, timeIntervalSinceDate:
). The following code fragment shows how to get the approximate number of months and days between two dates using a Gregorian calendar:
NSDate *startDate = ...; |
NSDate *endDate = ...; |
NSCalendar *gregorian = [[NSCalendar alloc] |
initWithCalendarIdentifier:NSGregorianCalendar]; |
unsigned int unitFlags = NSMonthCalendarUnit | NSDayCalendarUnit; |
NSDateComponents *components = [gregorian components:unitFlags |
fromDate:startDate |
toDate:endDate options:0]; |
int months = [components month]; |
int days = [components day]; |
It is important to note that an instance of NSDateComponents
is meaningless in itself; you need to know what calendar it is interpreted against, and you need to know whether the values are absolute values of the units, or quantities of the units. Note also that there are differences in the way that NSCalendar
’s Gregorian calendar (NSGregorianCalendar
) and NSCalendarDate
interpret components—for example, NSCalendar
’s Gregorian calendar’s week (interpreted using NSDateComponents
’s weekday
) starts with Sunday = 1, whereas NSCalendarDate
’s week (see dayOfWeek
) starts with Sunday = 0.
© 2002, 2007 Apple Inc. All Rights Reserved. (Last updated: 2007-09-04)