【问题标题】:Number of seconds between two dates including leap seconds两个日期之间的秒数,包括闰秒
【发布时间】:2021-02-13 18:21:44
【问题描述】:

我正在摆弄 C++ 中的时间表示。

我希望有一个严格单调的时间表示,可以很好地处理闰秒。 C++20 中的utc_clock 应该可以做到这一点,而且由于我的编译器还不支持这个版本,所以我使用的是HowardHinnant/date

为了更好地理解这个库,我开始制作小型测试用例,但被困在一个上面。 我在插入闰秒之前和之后取两个日期,并检查这两个日期之间的持续时间是否实际上有额外的秒数。

这是测试用例:

TEST(DateTime, TimeLeap)
{
  using namespace std::chrono;
  using namespace date;

  // Two dates with a leap second in between
  // https://en.wikipedia.org/wiki/Leap_second
  auto t1 = clock_cast<utc_clock>(static_cast<sys_days>(2016_y/December/31));
  auto t2 = clock_cast<utc_clock>(static_cast<sys_days>(2017_y/January/1));

  EXPECT_EQ(duration_cast<seconds>(t2 - t1).count(), 24 * 3600 + 1);
}

但对我来说失败了:

common/tests/datetime.cpp:39: Failure
      Expected: duration_cast<seconds>(t2 - t1).count()
      Which is: 86400
To be equal to: 24 * 3600 + 1
      Which is: 86401

sys_clockutc_clock 之间的转换似乎没有添加闰秒。

怀疑是sys_days的分辨率问题,我也试过在clock_cast&lt;utc_clock&gt;之前做一个time_point_cast&lt;seconds&gt;(...),但结果没有改变。 我还尝试使用 2017-01-02 作为第二个日期,以防 2016-12-31 23:59:60 和 2017-01-01 00:00 之间存在区别问题 - 闰秒也是没有出现在那里。

【问题讨论】:

  • 在这里工作正常。您如何配置 HowardHinnant/date 的安装?
  • 我强烈怀疑你get_tzdb().leap_seconds.size() == 0。它应该是 27。这意味着您依赖操作系统来提供闰秒信息 (USE_OS_TZDB=1),但它没有这样做。尽管在这方面 tz.cpp 最近有一些补丁:github.com/HowardHinnant/date/commit/…
  • @HowardHinnant 谢谢,就是这样!您能否将其转换为答案,以便我可以将其标记为已解决?并感谢很棒的图书馆。

标签: c++ c++20 chrono


【解决方案1】:

看起来您正在使用操作系统提供的时区数据库 (USE_OS_TZDB=1),并且没有读取闰秒。这可以通过以下方式确认:

cout << get_tzdb().leap_seconds.size() << '\n';

这应该输出 27(当前),但对你来说,我想它输出 0。这意味着闰秒数据丢失。

通过最近 (2020-09-11) 提交:https://github.com/HowardHinnant/date/commit/ba99134b8a7c4a6e7d28d738a0234a85dc6bd827,从以下任一文件中读取闰秒数据:

zoneinfo/leapseconds
zoneinfo/leap-seconds.list

这两个文件均由 IANA 提供,但格式略有不同。任何一个文件都可以,因为它们中有重复的信息。 tz.cpp 将搜索两者。如果您的平台没有提供这些文件中的任何一个,您可以从the IANA data download 下载并手动将其复制到位。

【讨论】:

  • 问题是闰秒没有从我的系统 tzdata 加载。你提到的提交完美地解决了这个问题。
猜你喜欢
  • 2022-09-26
  • 2019-05-11
  • 2014-10-30
  • 2015-09-13
  • 2023-03-07
  • 2021-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多