Search code examples
c++c++-chrono

C++ std::chrono::high_resolution_clock time_since_epoch returns too small numbers. How can I get the correct time since 1970 in microseconds?


I am trying to write a function, which will return the current time in microseconds since 1970. While a debugging I noticed, that the returned numbers are too small. For example: 269104616249. I also added static_assert to check the returned value type is int64_t, which i big enough to hold 292471 years in microseconds. So integer overflow should not be a case here. What am I doing wrong? Here is my code:

int64_t NowInMicroseconds() {
    static_assert(std::is_same<decltype(duration_cast<microseconds>(high_resolution_clock::now().time_since_epoch()).count()), int64_t>::value);
    return duration_cast<microseconds>(high_resolution_clock::now().time_since_epoch()).count();
}

int64_t result = NowInMicroseconds();

Solution

  • There are three chrono-supplied clocks in C++11/14/17 (more in C++20):

    1. system_clock: This measures Unix Time (time since 1970 excluding leap seconds).1

    2. steady_clock: Like a stop-watch. Great for timing, but it can not tell you the time of day.

    3. high_resolution_clock: This has the disadvantages of system_clock and steady_clock, and the advantages of neither. Typically it is a type alias to either system_clock or steady_clock, and which one differs with platform.

    You have to use system_clock for measuring time since 1970. Note that this is measured in UTC, not your local time zone. In C++11/14/17 to get the local time since 1970, you will have to either manually take your time zone into account, or use this C++20 chrono preview library.

    std::int64_t
    NowInMicroseconds()
    {
        using namespace std::chrono;
        return duration_cast<microseconds>(system_clock_clock::now().time_since_epoch()).count();
    }
    

    Consider returning a strong type which means "microseconds since 1970" instead of an integral type. Strong type safety helps you find your logic errors at compile time:

    std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds>
    NowInMicroseconds()
    {
        using namespace std::chrono;
        return time_point_cast<microseconds>(system_clock.now());
    }
    

    1 This is unspecified in C++11/14/17, but is true on all implementations. C++20 finally nails this epoch down in the spec.