22SAS
22SAS

Reputation: 21

Can the value of std::chrono::system_clock::time_point change based on the timezone?

I have been writing unit tests for a class in our codebase that basically converts date, time values from std::string to std::chrono::time_point and vice versa, for different kinds of timestamps (yyyy-mm-dd , hh:mm:ss.ms etc).

One way I tried to test whether a std::chrono::system_clock::time_point returned by a function in our codebase as the same as one created in the unit tests was to do something like this -

std::chrono::system_clock::time_point m_TimePoint{}; // == Clock's epoch
auto foo = convertToString(n_TimePoint); //foo is std::string
auto bar = getTimePoint(foo);
ASSERT_EQ(m_TimePoint, bar);

This was on Ubuntu , now the constructor should return a time point as UTC Jan 1 00:00:00 1970. Now when I used ctime() to see the textual representation of the epoch it returned Dec 31 19:00:00 1969. I was puzzled and checked that EST(my system timezone) is equal to UTC-5.

Once I created the object as -

std::chrono::duration d{0};
d += std::chrono::hours(5);
std::chrono::system_clock::time_point m_TimePoint{d}; //== clock epoch + 5 hours

All worked fine.

My question is it possible for the system clock epoch to be adjusted based on the system timezone?

Upvotes: 2

Views: 1663

Answers (1)

Howard Hinnant
Howard Hinnant

Reputation: 218780

There's two answers to this question, and I'll try to hit both of them.

system_clock was introduced in C++11, and its epoch was left unspecified. So the technical answer to your question is: yes, it is possible for the system_clock epoch to be adjusted based on the system timezone.

But that's not the end of the story.

There's only a few implementations of system_clock, and all of them model Unix Time. Unix Time is a measure of time duration since 1970-01-01 00:00:00 UTC, excluding leap seconds. It is not dependent on the system timezone.

The C++20 spec standardizes this existing practice.

So from a practical standpoint, the answer to your question is: no, it is not possible for the system_clock epoch to be adjusted based on the system timezone.

One thing that could be tripping you up is that system_clock typically counts time in units finer than milliseconds. It varies from platform to platform, and you can inspect what it is with system_clock::duration::period::num and system_clock::duration::period::den. These are two compile-time integral constants that form a fraction, n/d which describes the length of time in seconds that system_clock is measuring. For Ubuntu my guess would be this forms the fraction 1/1'000'000'000, or nanoseconds.

You can get milliseconds (or whatever unit you want) out of system_clock::time_point with:

auto tp = time_point_cast<milliseconds>(system_clock::now());

Upvotes: 5

Related Questions