NSDate 和 TimeZone 问题

Posted

技术标签:

【中文标题】NSDate 和 TimeZone 问题【英文标题】:NSDate and TimeZone Issues 【发布时间】:2014-02-11 04:34:45 【问题描述】:

我正在尝试让我的应用根据预定事件触发通知。给出的日期来自将在 EST 进行的时间表。给出的时间是 2014 年 2 月 21 日星期五 12:00:00 -0500(美国东部标准时间中午)。

当按下安排通知的按钮时,它会运行以下代码:

NSString *message = [@"15 minutes until " stringByAppendingString:self.thetitle];
                NSLog(@"original%@", self.thedate);
        NSDate *newDate = [self.thedate dateByAddingTimeInterval:-60*15];
        NSDateFormatter *formatter3 = [[NSDateFormatter alloc] init];

        // [formatter3 setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
        [formatter3 setTimeStyle:NSDateFormatterShortStyle];
        [formatter3 setDateStyle:NSDateFormatterShortStyle];
        NSString *detailstext = [formatter3 stringFromDate:newDate];
        NSDate *othernewdate = [formatter3 dateFromString:detailstext];
        NSLog(@"other%@", othernewdate);
        UILocalNotification *notification = [[UILocalNotification alloc] init];
    notification.timeZone = [NSTimeZone systemTimeZone];
        notification.fireDate = othernewdate;
        notification.alertBody = message;
        notification.soundName = UILocalNotificationDefaultSoundName;
        notification.hasAction = YES;
        notification.alertAction = NSLocalizedString(@"View", @"View notification button");

        [[UIApplication sharedApplication] scheduleLocalNotification:notification];

由于通知 fireDate 上设置的时间是 othernewdate,因此我在控制台中运行了一个 NSLog 以查看它显示的内容。它回来了:

2014-02-21 16:45:00 +0000

这似乎很完美,因为美国东部标准时间的那个时间是上午 11:45,或者中午前 15 分钟,这正是我想要的。

问题是这样的: 我正在 CST 中对此进行测试。我运行该应用程序,告诉它为此事件安排通知,然后将我的手机时钟更改为 EST,它最终在 10:45 触发通知。

会有人从不同的时区使用这个应用程序,然后在这个应用程序的会议开始时前往美国东部标准时间。我不希望他们在不同的时区安排大量通知并在错误的时间触发。有什么建议吗?

【问题讨论】:

在字符串和日期之间转换时使用NSDateFormatter。还要在格式化程序中设置时区。 NSDateNSLog 可能没有提供您想要/期望的字符串,请在 NSLog 中使用 NSDateFormatterNSDate 内部基于 GMT,时区只影响字符串到日期、日期到字符串和日期组件的操作。 @Zaph 好的,我试过在一行中添加 ~[formatter3 setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"EST"]];~ 但它保持不变。 【参考方案1】:

如果您希望在独立于时区的绝对日期/时间触发通知,则必须设置notification.timezone = nil

来自文档:

"fireDate中指定的日期根据该属性的值进行解释。如果指定nil(默认),则触发日期解释为绝对GMT时间,适用于倒数计时器等情况。如果如果您为此属性分配一个有效的 NSTimeZone 对象,则触发日期被解释为挂钟时间,当时区发生变化时会自动调整;适合这种情况的示例是闹钟。"

【讨论】:

仍然没有区别。 您能在更改设备时区前后显示NSLog(@"timezone=%@, notification=%@", [NSTimeZone localTimeZone], notification) 的输出吗?

以上是关于NSDate 和 TimeZone 问题的主要内容,如果未能解决你的问题,请参考以下文章

Android 6.0 修改默认时区

Symfony2 和 date_default_timezone_get() - 依赖系统的时区设置是不安全的

关于date()

一篇文章吃透iOSJS的时间日期(Date, Calendar, Locale, TimeZone)

将 UTC 日期格式转换为本地 nsdate

NSDate 比较,找出特定(本地)时区的“午夜数”