Why would NSDate be inconsistent across devices?
The following method attempts to calculate the number of days in a year of an NSHebrew calendar object, given a hebrew year. For some reason, I'm getting inconsistent results across devices. The test case was the date of May 25, 1996. One device was returning one day longer (the correct value) than another device, which was one day short.
- (NSInteger) lengthOfYearForYear:(NSInteger)year{
//
// Then get the first day of the current hebrew year
//
NSCalendar *hebrewCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSHebrewCalendar];
NSDateComponents *roshHashanaComponents开发者_Python百科 = [[[NSDateComponents alloc] init ]autorelease];
[roshHashanaComponents setDay:1];
[roshHashanaComponents setMonth:1];
[roshHashanaComponents setYear:year];
[roshHashanaComponents setHour:12];
[roshHashanaComponents setMinute:0];
[roshHashanaComponents setSecond:0];
NSDate *roshHashanaDate = [hebrewCalendar dateFromComponents:roshHashanaComponents];
//
// Then convert that to gregorian
//
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *gregorianDayComponentsForRoshHashana = [gregorianCalendar components:NSWeekdayCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:roshHashanaDate];
//Determine the day of the week of the first day of the current hebrew year
NSDate *oneTishreiAsGregorian = [gregorianCalendar dateFromComponents:gregorianDayComponentsForRoshHashana];
//
// Then get the first day of the next hebrew year
//
NSDateComponents *roshHashanaOfNextYearComponents = [[NSDateComponents alloc] init ];
NSInteger tempYear = year+1;
[roshHashanaOfNextYearComponents setDay:1];
[roshHashanaOfNextYearComponents setMonth:1];
[roshHashanaOfNextYearComponents setYear:tempYear];
[roshHashanaOfNextYearComponents setHour:12];
[roshHashanaOfNextYearComponents setMinute:0];
[roshHashanaOfNextYearComponents setSecond:0];
NSDate *roshHashanaOfNextYearAsDate = [hebrewCalendar dateFromComponents:roshHashanaOfNextYearComponents];
[roshHashanaOfNextYearComponents release];
[hebrewCalendar release];
//
// Then convert that to gregorian
//
NSDateComponents *gregorianDayComponentsForRoshHashanaOfNextYear = [gregorianCalendar components:NSWeekdayCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:roshHashanaOfNextYearAsDate];
//Determine the first day of the week of the next hebrew year
NSDate *oneTishreiOfNextYearAsGregorian = [gregorianCalendar dateFromComponents:gregorianDayComponentsForRoshHashanaOfNextYear];
// Length of this year in days
NSTimeInterval totalDaysInTheYear = [oneTishreiOfNextYearAsGregorian timeIntervalSinceReferenceDate] - [oneTishreiAsGregorian timeIntervalSinceReferenceDate];
//
// We round here because of slight offsets in the Gregorian calendar.
//
totalDaysInTheYear = round(totalDaysInTheYear/86400);
if(totalDaysInTheYear == 353 || totalDaysInTheYear == 383){
totalDaysInTheYear = 0;
}else if(totalDaysInTheYear == 354 || totalDaysInTheYear == 384){
totalDaysInTheYear = 1;
}else if(totalDaysInTheYear == 355 || totalDaysInTheYear == 385){
totalDaysInTheYear = 2;
}
return totalDaysInTheYear;
}
I think that it could be because I'm not using NSHourCalendarUnit
and smaller, but I'm not sure. Would that do it? Is there anything else that's blatantly incorrect?
Had the same observation between devices across my beta testers. Different cellular network means different time signal. Silly, but they use their time for billing, so they provide their own signal in the cellular network.
iPods are set by the host machines who are usually set by a NTP server. Those should be pretty in sync.
The problem with this code is the fact that I left out the identifiers for the NSDateComponents. The NSDateComponents, without required identifiers, messes up the hours, minutes and seconds, thus producing a varying year length across devices.
精彩评论