52
votes

All I want is to get the time since epoch in milliseconds and store it in an unsigned long.

I found this related question. But honestly, this can't be the easiest way to perform such a simple task, is it? I am hoping for something much simpler, but can't find anything in the std::chrono reference. Any advice is most welcome. I don't necessarily have to use std::chrono, but I want it to be platform independent.

1
auto ms_since_epoch = duration_cast<milliseconds>(since_epoch); already seems pretty simple. Perhaps the problem is the basic mindset of chrono where it's hoped that you'll stick with type safety and a richer type system than just unsigned long.bames53
since_epoch is just a stand-in variable for system_clock::now().time_since_epoch() or whatever duration you want to convert. Using auto does not mean that code is not typesafe. In this case we explicitly state the type and we just use auto so we don't have to repeat it.bames53
But the basic mindset of chrono durations is that types keep track of units for you, like a full physical units library would do, and you don't have to worry about it except at boundaries into and out of chrono's type system. For example consider std::this_thread::sleep_for(microseconds(1000)); vs. std::this_thread::sleep_for(milliseconds(1));. The library doesn't care what units the input is in. Both durations represent the same amount of time and that's all that matters here.bames53
@bames53, yes, in principal your right about the type safty issu. However I really dislike using auto, especialy if I don't know what type it would be. And I did't say the chrono library is useless, I would fully agree that it offers quite a lot of nice features. What is bugging me is, that in my opinion trivial task (like this one) are awfull complicated.Haatschii
@Haatschii Perhaps part of that is that this sort of thing is supposed to be a rare operation, done only on the boundaries. Ideally all the work is done without having to move data outside the type system. That way not only is there no need to use count() to get a unit-less value, you don't even need to use duration_cast; simply use since_epoch in your calculations directly.bames53

1 Answers

88
votes
unsigned long milliseconds_since_epoch =
    std::chrono::system_clock::now().time_since_epoch() / 
    std::chrono::milliseconds(1);

although, especially since you want platform independence, it might be better to replace unsigned long with a type that's more likely to be large enough:

  • (unsigned) long long
  • std::(u)int64_t
  • std::chrono::milliseconds::rep
  • auto

To me, this clearly states both that you're risking loss of precision (by analogy with integer division) and that you're leaving the safety of the type system (by dividing by a typed time to give a unitless number). However, as demonstrated in the comments, some people would say that any attempt to move away from type-safety should be accompanied by a deliberate attempt to make the code look dangerous. If you need to deal with people who hold that belief, it might be simpler to use duration_cast rather than enter into an argument about irrelevant stylistic choices:

unsigned long milliseconds_since_epoch = 
    std::chrono::duration_cast<std::chrono::milliseconds>
        (std::chrono::system_clock::now().time_since_epoch()).count();