有没有办法在逻辑上(不是绝对)将时间段添加到本地时间并在未来获得有效的本地时间?
例如,在第 1 天的上午 11 点添加一天会变成第 2 天的上午 11 点,即使同时有夏令时更改(+/- 1 小时)?如果时间不存在,它可能会返回错误或下一个有效时间。
C++ 标准机制、Windows API 函数、STL 和/或 Boost 类都可以。
这有点取决于你的语义。
如果您对半天后的本地时间感兴趣,那么可以:您转换为 UTC,加上半天,然后转换回本地时间。
另一方面,如果您主要在当地时间进行操作(例如,我们在电力负荷预测中这样做),您可能会采取相反的方式,即“我们的半天未来事件还有多少小时?”:您对待本地时间就好像它是 UTC,加上半天,然后将其视为本地时间并转换回 UTC 以进行完整性检查 - 您必须知道某些本地时间不存在,而某些本地时间是模糊的。
如果您从当地时间开始,例如2013-07-02 18:30:00
您只想同时前往下一个日历日,那么尽管有其他人的建议 - 您真的不想涉及 UTC。
您正在按照日历时间工作。UTC 用于测量瞬时时间。日历时间可以有 DST 更改的不连续性,但瞬时时间不会。
当您将一天添加到瞬时时间时,您总是添加正好 24 小时。但是,当您将一天添加到日历时间时,您会将日历提前一天的位置。这是微妙的,但明显不同。一个日历日可能有 23、24 或 25 个实际小时。
当涉及不连续性时,您将需要处理“弹簧向前”过渡,即时钟跳过一个小时。如果您添加一天并最终出现在此间隙中,您将指的是日历上不存在的时间。你需要决定在这种情况下你想要发生什么。它应该提前到下一个可能的时间吗?还是应该出错?或者,在这种情况下,您可能会再增加一小时。由你决定。
另一个不连续性是“回退”过渡,即时钟回退一个小时。这个单一的日历位置可能有两个实际时刻可以参考 - 但由于您只对日历时间感兴趣,所以这不应该直接影响您。如果您确实想知道它映射到哪个时刻,那么您将再次需要做出决定——可能涉及一些业务逻辑或通过 UI 询问用户。
为了知道不连续性在哪里,您需要一个时区数据库。IANA数据库是事实上的标准。
对于 C++,您应该考虑使用Boost 的日期和时间支持。他们确实使用标准数据库(又名“ZoneInfo”),并在此处讨论使用它。您可能想要使用local_time
.
如果可能的话,请远离 POSIX 时区设置,比如PST8DST
Boost,虽然 Boost 支持它们,但它们很神秘,通常难以在国际上使用。IANA 时区具有由区域和位置组成的查找键,例如America/New_York
或Europe/London
。
还要在 Boost 中查看local_time::ambiguous_result
和local_time::time_label_invalid
。这些会告诉你你是否处于不连续状态。
我还要说(恕我直言),在 C++ 中使用本地日期时间、时区、DST 等要比在任何其他语言中复杂得多。PHP、Python、.Net、Ruby 等都有很好的解决方案。 Boost 可能具有 C++ 最全面的日期/时间实现,但它远不如Noda Time for .Net 之类的库那么简单
更新
我开始意识到 Boost 对 IANA/Olson 时区的支持是有缺陷的。他们的时区数据文件剥离了 IANA/Olson 时区数据库的丰富历史——它基本上重现了我在时区标签 wiki中描述的所有 POSIX 时区问题。因此,我不再推荐使用 Boost 进行时区转换。