【问题标题】:How to determine if specific date is daylight savings time or not?如何确定特定日期是否为夏令时?
【发布时间】:2013-05-25 10:36:41
【问题描述】:

我正在处理一个编程错误的第 3 方 API,它迫使我在目标 C 中处理一些日期/时间数据。

它不是将日期作为 UTC 中的绝对 UNIX 时间戳返回,而是将日期作为没有时区信息的格式化字符串返回。 (实际上,在与他们的一位开发人员交谈后,他们实际上将日期/时间存储在他们的数据库中作为没有时区信息的字符串,而不是时间戳!)服务器是在美国中部的某个地方,所以它目前在 CDT 上,所以理论上我可以将“CDT”添加到格式化日期并使用 NSDateFormatter (yyyy-MM-dd HH:mm:ss zzz) 来构造 NSDate。但是,根据相关日期的来源,它可能是 CST 或 CDT。

如何确定夏令时在该特定日期是否有效,以便我可以附加正确的时区并计算正确的 UTC 日期?

【问题讨论】:

    标签: ios timezone nsdate nsdateformatter


    【解决方案1】:

    嗯,我不认为有 一个正确的方法来做到这一点。有用于此的 API,例如:

    [NSTimeZone isDaylightSavingTimeForDate:][NSTimeZone daylightSavingTimeOffsetForDate:]

    但是 在从 CDT 到 CST 的过渡过程中,将重复一小时,因此无法知道是 CDT 还是 CST。除了假设 CST 和检查夏令时的一小时之外应该工作。我的建议是让编写此 API 的人着火。

    【讨论】:

    • 对——最好的选择是更改 API。不幸的是,我没有权力这样做。有没有办法从 NSDate 获取 NSTimeZone?这样我就可以使用 isDaylightSavingsTimeForDate: 方法。
    • @Jason 要非常小心。 NSDate 与 NSTimeZone 无关(unix 标记是否有时区?不,原因相同)。时区在日期 formatter 上,而不是日期本身。因此,正如我上面所说,只需假设 CST(使用该缩写创建一个时区),在格式化程序上设置该时区,并使用格式化程序创建一个 NSDate 对象。除了重复的一小时外,它将起作用。如果夏令时生效,则适当调整 NSDate。
    • 我同意在 DST 后备过渡期间重复一小时。如果没有来自 API 的其他信息,您只能猜测它可能是两者中的哪一个,并且您可能错了。
    • 我也想找到那个人。
    【解决方案2】:

    我认为我有一个解决方案:

        NSString *originalDateString = <ORIGINAL DATE FROM API>;
    
        NSDateFormatter *dateStringFormatter = [[NSDateFormatter alloc] init];
        dateStringFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss zzz";
    
        NSString *tempDateString = [originalDateString stringByAppendingFormat:@" CST"];
    
        // create a temporary NSDate object
        NSDate *tempDate = [dateStringFormatter dateFromString:tempDateString];
    
        // get the time zone for this NSDate (it may be incorrect but it is an NSTimeZone object)
        NSDateComponents *components = [[NSCalendar currentCalendar]
                                        components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit | NSTimeZoneCalendarUnit
                                        fromDate:tempDate];
        NSTimeZone *tempTimeZone = [components timeZone];
    
        // Find out if the time zone of the temporary date
        // (in CST or CDT depending on the local time zone of the iOS device)
        // **would** use daylight savings time for the date in question, and
        // select the proper time zone
        NSString *timeZone;
        if ([tempTimeZone isDaylightSavingTimeForDate:tempDate]) {
            timeZone = @"CDT";
        } else {
            timeZone = @"CST";
        }
    
        NSString *finalDateString = [originalDateString stringByAppendingFormat:@" %@", timeZone];
    

    【讨论】:

    • 注意时区缩写。我不太确定 iOS 是如何处理它的,但是有许多区域具有相同的缩写。你可以看到一个列表here。例如,CST 可能表示“中国标准时间”...
    • 我想知道你是否可以只传递区域 ID America/Chicago 来代替?如果是这样,您可能不必亲自检查isDaylightSavingsTimeForDate。它可能会在内部完成。 (我只是猜测 - 我不是 iOS/ObjectiveC 开发人员)
    • @MattJohnson 这对这个 API 没有意义,因为“美国/芝加哥”将取决于日期,而时区则不是。此外,此 API 的更快方法是无需制作其他格式化程序,只需将 daylightSavingTimeOffsetForDate: 添加到您在 tempDate 中创建的日期即可。如果夏令时无效,它将为零。
    • @MattJohnson 不幸的是,iOS 不会从日期格式化程序自动确定夏令时。如果我在应该是 CDT 的时候放 CST,它会延迟一个小时。
    • @Jason 他的意思是通过“美国/芝加哥”而不是“CST”让系统确定实际时区:)。另外,您可以考虑按名称而不是缩写来构建时区,以避免他上面提到的问题。
    猜你喜欢
    • 2015-09-17
    • 1970-01-01
    • 2020-04-29
    • 2010-09-07
    • 2019-08-31
    • 2013-11-16
    • 2010-09-09
    • 2018-12-23
    • 1970-01-01
    相关资源
    最近更新 更多