【问题标题】:Getting NSDate for today with 00:00:00 as time以 00:00:00 为时间获取今天的 NSDate
【发布时间】:2010-11-03 12:11:25
【问题描述】:

我正在 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 应用程序所看到的完全一样,只是这个错误让人们起床晚了。此外,时区默认为您设备上当前设置的时区,因此它应该保持不变,直到您在设置屏幕中更改时区。

编辑2: 好的,再做一些测试:

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

【问题讨论】:

    标签: iphone objective-c cocoa ios


    【解决方案1】:

    Using Time Zones。在开始询问日期之前,您需要使用 NSCalendar 的 -setTimeZone: 方法设置日历的时区。

    【讨论】:

    • 诺齐……真的吗?你正在跟着我吗? :P。我认为这与夏令时错误有关。我看到的东西可能与 Clock 应用程序所看到的完全一样,只是有让人们起床晚的错误。
    • 我不认识你提到的这个@jnozzi Twitter 人。什么?你没提?该死!哦,对,是我。 ;-) 唔。我没听说过。在使用 Foundation 的东西时可能想要标记 iPhone,因为在这些情况下 Mac/iOS 并不清楚。 :-)
    • 穆哈哈,我知道到处都能找到你。又更新了我的帖子。当我调用 [NSDate date] 时,我真的需要添加该偏移量吗?我希望操作系统会自动执行此操作。
    • 我想你想要 +[NSCalendar currentCalendar] 而不是从头开始初始化一个。文档说这使用了用户的设置。
    • 但是问题不是“更早”吗?因为 [NSDate date] 已经错了?或者该方法是否返回某种 GMT 时区。
    【解决方案2】:

    这是一个有趣的问题,我为解决方案工作了好几个小时。以下是我的发现:

    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) 创建两个日期。

    dateLastDay2010-11-02 23:59:00 +01
    dateToday2010-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;
    

    我们会拒绝的!尽管这两个日期似乎具有相同的日、月和年,但它们并不相同。之所以出现这种情况,是因为我们以错误的方式显示它们。

    【讨论】:

      【解决方案3】:

      您是否尝试过使用:

      NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
      [formatter setDateFormat:@"yyyy-MM-dd"];
      todayAtOO = [formatter dateFromString:[formatter stringFromDate:[NSDate date]]];
      

      【讨论】:

        【解决方案4】:

        我仍在试图弄清楚为什么会发生此错误,但我确实知道解决方案。在发送 dateFromComponents: 之前将 NSCalendar 的时区设置为 GMT 将解决问题。

        [gregorian setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
        

        PS 如果您根据 Joshua 的建议找到了不同的解决方案,您能告诉我们是什么吗?自从您接受他的回答以来,您似乎已经解决了这个问题,但目前还不清楚您做了什么。谢谢!

        【讨论】:

          【解决方案5】:

          据我所知,如果您的时区是 GMT+1,它会给您正确的答案。您的时间是格林威治标准时间前一天的 23:00 午夜。

          问题可能在于格式化返回的输出日期。它为您提供了一个 GMT 字符串,而不是您当前的语言环境。

          【讨论】:

            猜你喜欢
            • 2021-04-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-03-26
            • 2013-03-17
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多