我在Xcode中编写一个类别,它将扩展当前的NSDate类。我想添加两个我经常使用的方法,不知怎的,我不能让它们正常工作。
目前我有这段代码:
+ (NSDate*) today
{
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *todayComponents = [gregorian components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:[NSDate date]];
NSInteger theDay = [todayComponents day];
NSInteger theMonth = [todayComponents month];
NSInteger theYear = [todayComponents year];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:theDay];
[components setMonth:theMonth];
[components setYear:theYear];
NSDate* todayDate = [gregorian dateFromComponents:components];
[components release];
[gregorian release];
return todayDate;
}
我希望它返回这样的日期:“2010-11-03 00:00:00 +01”。但不知怎的,时区一直在冒险,因为这段代码返回“2010-11-02 23:00:00 +0000”。
有人能告诉我如何修复此代码以实际返回正确的日期吗?或者我可以使用此日期,我的应用程序将自行转换,因为机器设置的时区。
我必须将我的应用程序中的某些事件记录到数据库中,该数据库也只使用[NSDate date]方法。这是否意味着[NSDate date]方法也使用没有时区信息的时间?
编辑: 我认为这与夏令时错误有关。我看到的东西与Clock应用程序可能完全相同,但是这些错误让人们起得更晚。此外,TimeZone默认为您设备上当前设置的TimeZone,因此它应保持不变,直到您在设置屏幕中更改时区为止。
EDIT2: 好的,还有一些测试:
NSLog(@"CurrentDate: %@", [NSDate date]);
NSLog(@"TZ: %@", [NSTimeZone defaultTimeZone]);
给我以下结果:
2010-11-03 23:23:49.000 App[8578:207] CurrentDate: 2010-11-03 22:23:49 +0000
2010-11-03 23:23:49.001 App[8578:207] TZ: Europe/Amsterdam (GMT+01:00) offset 3600
答案 0 :(得分:6)
见Using Time Zones。在开始询问日期之前,您需要使用NSCalendar的-setTimeZone:方法设置日历的时区。
答案 1 :(得分:3)
这是一个有趣的问题,我在解决方案中工作了好几个小时。这些是我的发现:
NSLog(@"CurrentDate: %@", [NSDate date]);
上面显示的代码与下面显示的代码具有相同的结果:
NSLog(@"CurrentDate: %@", [[NSDate date] description]);
阅读NSDate Class Reference会在 NSDate的 description
方法上生成此文档。
不保证表示在操作系统的不同版本中保持不变。要格式化日期,您应该使用日期格式化程序对象(请参阅NSDateFormatter和数据格式指南)
我还浏览了descriptionWithLocale: (id) locale
的文档:
“使用给定的语言环境返回接收者的字符串表示形式。”
所以,改变你的代码
NSLog(@"CurrentDate: %@", [NSDate date]);
要:
NSLog(@"CurrentDate: %@", [[NSDate date] descriptionWithLocale:[NSLocale currentLocale]]);
哪个应该会产生你想要的东西。我还可以证明[NSDate date]
确实给出了正确的日期,但只是用错误的方法显示:
我们可以使用[today]
(Wim Haanstra)创建两个日期。
dateLastDay : 2010-11-02 23:59:00 +01
dateToday : 2010-11-03 24:01:00 +01
然后我们使用下面的代码显示两个日期:
NSLog(@"CurrentDate: %@", dateLastDay);
NSLog(@"CurrentDate: %@", dateToday);
或者:
NSLog(@"CurrentDate: %@", [dateLastDay description]);
NSLog(@"CurrentDate: %@", [dateToday description]);
这两组显示相同的结果,如:“2010-11- 02 22:59:00 +0000”和“2010-11- 02 23 :01:00 +0000“。看起来这两个日期有相同的“日期”,但是真的吗?
现在我们比较日期的日期:
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger unitFlags = NSDayCalendarUnit;
NSDateComponents *lastDayComponents = [gregorian components:unitFlags fromDate:dateLastDay];
NSDateComponents *todayComponents = [gregorian components:unitFlags fromDate:dateToday];
NSInteger lastDay = [lastDayComponents day];
NSInteger today = [todayComponents day];
return (lastDay == today) ? YES : NO;
我们会得到NO!虽然这两个日期似乎有相同的日,月和年,但他们不这样做。它只是出现这种方式,因为我们以错误的方式显示它们。
答案 2 :(得分:2)
你尝试过使用:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd"];
todayAtOO = [formatter dateFromString:[formatter stringFromDate:[NSDate date]]];
答案 3 :(得分:1)
我仍在努力弄清楚为什么会发生这个错误,但我确实知道一个解决方案。在发送日期之前将NSCalendar的时区设置为GMT dateFromComponents:将解决问题。
[gregorian setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
PS如果你根据Joshua的建议找到了不同的解决方案,你能告诉我们它是什么吗?你似乎已经解决了这个问题,因为你已经接受了他的答案,但你所做的并不是很清楚。谢谢!
答案 4 :(得分:0)
据我所知,如果您的时区是GMT + 1,它会给您正确答案。午夜时间是格林尼治标准时间前一天的23:00。
问题可能在于格式化输出的返回日期。它为您提供了GMT的字符串,而不是您当前的语言环境。