< Previous PageNext Page > Hide TOC

Calendars

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.

Contents:

Creating a Calendar
Calendrical Calculations


Creating a Calendar

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.

Calendrical Calculations

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.



< Previous PageNext Page > Hide TOC


© 2002, 2007 Apple Inc. All Rights Reserved. (Last updated: 2007-09-04)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.