今天00:00:00获取NSDate作为时间

时间:2010-11-03 12:11:26

标签: iphone objective-c cocoa ios

我在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

5 个答案:

答案 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的字符串,而不是您当前的语言环境。

相关问题