问题
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?
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/22108932/nscalendar-datefromcomponents-vs-nsdatecomponents-date