Question

Say I have the following code which initializes an NSDateComponents:

NSCalendar *calendar = [NSCalendar currentCalendar];

NSDateComponents *components = [[NSDateComponents alloc] init];
[components setYear:1987];
[components setMonth:3];
[components setDay:17];
[components setHour:14];
[components setMinute:20];
[components setSecond:0];

And now I want to convert the components to an NSDate. It seems like there are two ways:

Method 1:

NSDate *date = [calendar dateFromComponents:components];

Method 2:

NSDate *date = [components date];

Is there a difference between these two methods? If so, which one should be used and why?

Was it helpful?

Solution

NSDate *date = [components date];

is identical to

NSDate *date = [[components calendar] dateFromComponents:comps];

and it returns nil if you don't have assigned a calendar to the date components. You can verify that by setting the environment variable NSObjCMessageLoggingEnabled=YES in the projects scheme, and observe in the generated message trace (/tmp/msgSends-NNNN) that exactly the same methods are called.

That means that you can call

NSDate *date = [calendar dateFromComponents:components];

or

[components setCalendar:calendar];
NSDate *date = [components date];

and there is no difference between the two methods.

OTHER TIPS

I believe it is that the NSDateComponents does not have a calendar set by default. Thus questions related to a specific calendar (like the Gregorian) are undefined.

According to Apple's documentation here:

An instance of NSDateComponents is not responsible for answering questions about a date beyond the information with which it was initialized. For example, if you initialize one with May 6, 2004, its weekday is NSUndefinedDateComponent, not Thursday. To get the correct day of the week, you must create a suitable instance of NSCalendar, create an NSDate object using dateFromComponents: and then use components:fromDate: to retrieve the weekday—as illustrated in the following example.

NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:6];
[comps setMonth:5];
[comps setYear:2004];
NSCalendar *gregorian = [[NSCalendar alloc]
    initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:comps];
[comps release];
NSDateComponents *weekdayComponents =
    [gregorian components:NSWeekdayCalendarUnit fromDate:date];
int weekday = [weekdayComponents weekday];

But I believe you can set the NSDateComponent's Calendar property to fix that.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top