Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set epoch for std::chrono::steady_clock in C++?

Tags:

c++

datetime

I would like to get current time in milliseconds since a specific epoch e.g. Jan 1, 2016.

The reason to do this is to avoid using 8 bytes for std::chrono::milliseconds.
I would like to store the result in a 4byte data type instead.

std::chrono::steady_clock() uses default epoch which is unspecified.

like image 248
Aman Jain Avatar asked Sep 06 '25 03:09

Aman Jain


1 Answers

Here is how you can create your own clock as suggested in the comments by David.

#include "date.h"
#include <cstdint>
#include <iostream>

struct myclock
{
    using rep        = std::int32_t;
    using period     = std::milli;
    using duration   = std::chrono::duration<rep, period>;
    using time_point = std::chrono::time_point<myclock>;
    static constexpr bool is_steady = false;

    static time_point now() noexcept
    {
        using namespace std::chrono;
        using namespace date;
        return time_point{duration_cast<duration>(system_clock::now()
                                                - sys_days{jan/1/2016})};
    }
};

static_assert(sizeof(myclock::time_point) == 4, "");
static_assert(sizeof(myclock::duration) == 4, "");

int
main()
{
    auto tp = myclock::now();
    std::cout << tp.time_since_epoch().count() << '\n';
}

The representation is specified to be int32_t as you specified, and the precision is milliseconds, as you specified.

To get the epoch you specified I got an assist from this date library which makes it very easy to interoperate dates and system_clock::time_point. I simply subtract off your desired epoch from system_clock::now(), and cast that duration to myclock::duration (32 bit milliseconds).

Running this program just now output for me:

1207186990

which is 13.97 days.

You can compute the range of your clock with this code:

using namespace date;
using namespace std::chrono;
auto min = milliseconds{myclock::duration::min()} + sys_days{jan/1/2016};
auto max = milliseconds{myclock::duration::max()} + sys_days{jan/1/2016};
std::cout << min << '\n';
std::cout << max << '\n';

The explicit conversion to std::chrono::milliseconds is necessary to avoid overflow. This will output:

2015-12-07 03:28:36.352
2016-01-25 20:31:23.647

So better hurry. myclock will overflow in another 10 days. :-)

like image 110
Howard Hinnant Avatar answered Sep 07 '25 22:09

Howard Hinnant