根据夏令时逻辑操作时间

Posted

技术标签:

【中文标题】根据夏令时逻辑操作时间【英文标题】:Manipulating times logically with respects to daylight savings time 【发布时间】:2013-06-29 05:41:54 【问题描述】:

有没有办法在逻辑上(不是绝对)将时间段添加到本地时间并在未来获得有效的本地时间?

例如,在第 1 天的上午 11 点添加一天会变成第 2 天的上午 11 点,即使同时有夏令时更改(+/- 1 小时)?如果时间不存在,它可能会返回错误或下一个有效时间。

C++ 标准机制、Windows API 函数、STL 和/或 Boost 类都可以。

【问题讨论】:

你想要完成什么? 除了I'd start with this list,我什么都不知道 @TimoGeusch 我正在尝试将一天添加到一个时间,即某一天的上午 11 点,并在第二天获得相同的时间(上午 11 点),即使有夏令时更改-在此期间结束。 “将时间转换为 UTC,加上时间,然后再转换回来”看起来不错。如果是凌晨 1 点 30 分,而第二天,由于“跃进”而没有凌晨 1 点 30 分,你想要什么? 感谢 cmets - 我已尝试将问题简化并澄清为更具体的术语。我希望这会有所帮助。 【参考方案1】:

这有点取决于你的语义。

如果您对本地时间可能正好是半天时间感兴趣,那么可以:转换为 UTC,加上半天,然后再转换回本地时间。

另一方面,如果您主要在当地时间进行操作(例如,我们在电力负荷预测中这样做),您可能会采用另一种方式,ie半天未来事件?':您将本地时间视为 UTC,添加半天,然后将其视为本地时间并转换回 UTC 以进行完整性检查 - 您必须注意某些本地时间不存在,而且有些当地时间是模棱两可的。

【讨论】:

除了您可能想使用 TAI。 UTC 有闰秒 :(【参考方案2】:

如果您从2013-07-02 18:30:00 等当地时间开始,而您只想同时前往下一个日历日,那么尽管有其他人的建议 - 您真的 不想涉及UTC。

您正在按照日历时间工作。 UTC 用于测量瞬时时间。日历时间可能会因 DST 更改而不连续,但瞬时时间不会。

当您将 添加到瞬时时间时,您始终会添加 24 小时。但是,当您将一天添加到日历时间时,您会将日历提前一天的位置。这是微妙的,但明显不同。一个日历日可能有 23、24 或 25 个实际小时。

当涉及到不连续性时,您将需要处理“弹簧向前”过渡,即时钟跳过一个小时。如果您添加一天并最终出现在此间隙中,您将指的是日历上不存在的时间。你需要决定在这种情况下你想要发生什么。它应该提前到下一个可能的时间吗?还是应该出错?或者,在这种情况下,您可能会再增加一小时。这取决于你。

另一个不连续性是“回退”转换,即时钟回退一个小时。这个单一的日历位置可能有 两个 实际时刻可以参考 - 但由于您只对日历时间感兴趣,因此这不应该直接影响您。如果您确实想知道它映射到哪个瞬间,那么您将再次需要做出决定 - 可能涉及一些业务逻辑或通过 UI 询问用户。

为了知道不连续的位置,您需要一个时区数据库。 IANA 数据库是事实上的标准。

对于 C++,您应该考虑使用 Boost's Date and Time 支持。他们确实使用标准数据库(又名“ZoneInfo”),并讨论使用它here。您可能想使用local_time

如果可能,请远离诸如PST8DST 之类的 POSIX 时区设置,虽然 Boost 支持它们,但它们是神秘的,通常难以在国际上使用。 IANA 时区具有由区域和位置组成的查找键,例如 America/New_YorkEurope/London

在 Boost 中也可以查看 local_time::ambiguous_resultlocal_time::time_label_invalid。如果您处于不连续状态,这些会告诉您。

我还要说(恕我直言),使用本地日期时间、时区、DST 等在 C++ 中比在任何其他语言中要复杂得多php、Python、.Net、Ruby 等都有很好的解决方案。 Boost 可能拥有最全面的 C++ 日期/时间实现, 但它远没有像 Noda Time for .Net 这样的库那么简单

更新

我开始意识到 Boost 对 IANA/Olson 时区的支持存在缺陷。他们的time zone data file 剥离了 IANA/Olson 时区数据库的丰富历史——它基本上重现了我在the timezone tag wiki 中描述的所有 POSIX 时区问题。因此,我不再推荐使用 Boost 进行时区转换。

请考虑 ICU 或 GNU C library (as described here) 的时区函数 - 两者都使用完整的 IANA/Olson 时区数据。

【讨论】:

以上是关于根据夏令时逻辑操作时间的主要内容,如果未能解决你的问题,请参考以下文章

各种时间格式(UTC、GMT等)及夏令时和冬令时

夏令时计算

程序里的国际时区和夏令时

夏令时 plusHours 和 plusDays 之间的时间差

夏令时问题[重复]

CTimeSpan.GetDays() 和夏令时