Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Number of seconds between two dates including leap seconds

I'm fiddling around with time representation in C++.

I would like to have a strictly monotonic representation of time, that handles leap seconds well. The utc_clock in C++20 should be able to do that, and since my compiler doesn't support this version yet, I'm using HowardHinnant/date.

To understand the library better I have started making small test cases, but got stuck on one. I take two dates, before and after insertion of a leap second and check that duration between those two dates actually has the extra second.

This is the test case:

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);
}

but it fails for me:

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

It seems that the conversion between sys_clock and utc_clock doesn't add the leap second.

Suspecting that the problem is the resolution of sys_days, I've also tried doing a time_point_cast<seconds>(...) before the clock_cast<utc_clock>, but the result didn't change. I've also tried using 2017-01-02 as the second date, in case there was an issue with distinction between 2016-12-31 23:59:60 and 2017-01-01 00:00 -- the leap second also didn't appear there.

like image 630
cube Avatar asked Jan 24 '23 15:01

cube


1 Answers

It looks like you're using the OS supplied timezone database (USE_OS_TZDB=1), and that the leapseconds aren't being read. This can be confirmed with:

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

This should output 27 (currently), but for you I imagine it is outputting 0. This means leapsecond data is missing.

With a recent (2020-09-11) commit: https://github.com/HowardHinnant/date/commit/ba99134b8a7c4a6e7d28d738a0234a85dc6bd827, the leapsecond data is read from either one of these files:

zoneinfo/leapseconds
zoneinfo/leap-seconds.list

Both of these files are IANA-supplied, but have slightly different formats. Either file will do as they have duplicate information in them. tz.cpp will search for both. If your platform doesn't ship either one of these files, you can download it from the IANA data download and copy it into place manually.

like image 76
Howard Hinnant Avatar answered Mar 08 '23 15:03

Howard Hinnant