Search code examples
c++timec++17c++20c++-chrono

How to create a time point from milliseconds since Unix epoch?


To create a time point for the current time, you can use: std::chrono::system_clock::now().

I cannot figure out, however, how to create a time point given milliseconds since the UNIX epoch?

Also, is std::chrono::time_point even the recommended way to represent "instants" in time? Or should std::time_t be preferred?


Solution

  • This is easier/simpler:

    std::chrono::system_clock::time_point tp{std::chrono::milliseconds{m}};
    

    The above has a precision of system_clock::precision (microseconds on macOS, nanoseconds on Linux systems, and 1/10 microseconds on Windows). You could also create a time_point with a precision of milliseconds if desired:

    std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>
        tp{std::chrono::milliseconds{m}};
    

    In C++20 this can be simplified to:

    std::chrono::sys_time tp{std::chrono::milliseconds{m}};
    

    sys_time is just a template type alias for the system_clock family of time_points at any precision. I.e. the above is the exact same type as the milliseconds precision time_point created before.

    Also, is std::chrono::time_point even the recommended way to represent "instants" in time? Or should std::time_t be preferred?

    I recommend std::chrono::system_clock::time_point over std::time_t:

    • time_point's based on system_clock have a well-defined epoch (in C++20) which is also a de-facto standard in C++17: It counts time since 1970-01-01 00::00:00 UTC, excluding leap seconds. This is also known as Unix Time. In contrast no C or C++ standard specifies the epoch of time_t, though using Unix Time is common practice, and specified by POSIX.

    • Though unspecified, time_t typically has a precision of seconds. system_clock::time_point typically has a precision that is millions or billions finer than that. The exact precision is not specified, but it is documented within the API so you can discover it at compile-time or run-time. system_clock::period is the same std::ratio as system_clock::time_point::period and represents a compile-time fraction of a second from one tick to the next.

    • time_t is typically just a 32 or 64 bit signed integral. This has no type safety in generic code. For example you can add two time_t's and it compiles. However adding two points in time is not logical (while subtracting them is). The chrono library catches such logic bugs at compile-time. Adding two time_point's does not compile. But you can add a time_point and any duration. The logical algebra of time_points and durations is checked for you at compile-time.

    • If you need to cover leap seconds, it is unspecified but common that time_t does not (typically it is Unix Time). With system_clock, Unix Time is specified (you know you aren't counting leap seconds). However in C++20 there is another chrono clock that does include leap seconds in its count: std::chrono::utc_clock. Like all chrono clocks this clock has it's own type-safe family of time_points, with its own convenience template type alias called utc_time<Duration>. And you can convert between them using std::chrono::clock_cast.

    like this:

    auto tp_sys = clock_cast<system_clock>(tp_utc);