为什么 NSDate 在不同设备上会不一致?
以下方法尝试在给定希伯来年份的情况下计算 NSHebrew 日历对象一年中的天数。由于某种原因,我在不同设备上得到的结果不一致。测试用例的日期是 1996 年 5 月 25 日。一台设备返回的时间比另一台设备多一天(正确值),而另一台设备则少一天。
- (NSInteger) lengthOfYearForYear:(NSInteger)year{
//
// Then get the first day of the current hebrew year
//
NSCalendar *hebrewCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSHebrewCalendar];
NSDateComponents *roshHashanaComponents = [[[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;
}
我认为这可能是因为我没有使用 NSHourCalendarUnit 及更小的文件,但我不确定。这样做可以吗?还有什么明显不正确的地方吗?
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 = [[[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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在我的 Beta 测试人员的设备之间也有同样的观察结果。不同的蜂窝网络意味着不同的时间信号。愚蠢的是,他们利用自己的时间进行计费,因此他们在蜂窝网络中提供自己的信号。
iPod 由主机设置,而主机通常由 NTP 服务器设置。这些应该非常同步。
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.
这段代码的问题是我遗漏了 NSDateComponents 的标识符。 NSDateComponents 没有必需的标识符,会弄乱小时、分钟和秒,从而在不同设备上产生不同的年份长度。
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.