60

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.

Community
  • 1
  • 1
Haatschii
  • 9,021
  • 10
  • 58
  • 95
  • 11
    `auto ms_since_epoch = duration_cast(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 Apr 23 '13 at 19:51
  • @bames53 Please post your solution as an answer with code snippet. If it works, I will upvote it. – Ali Apr 23 '13 at 19:54
  • @bames53: What is `since_epoch`in your code? If it would work it would definitly be pretty simple. And I really like type safety, which is exactly why I dislike `chrono` because all examples I can find (including yours) simply use `auto` and no one seems to care what the actual type of all those chrono objects is (In most cases some ugly long template expression...). – Haatschii Apr 23 '13 at 20:08
  • 5
    `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 Apr 23 '13 at 20:35
  • 5
    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 Apr 23 '13 at 20:36
  • 1
    @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 Apr 23 '13 at 21:54
  • 2
    @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 Apr 24 '13 at 15:12
  • `cout << chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count() << endl;` – Paul Jun 25 '21 at 18:10

2 Answers2

97
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();
Mikhail
  • 7,749
  • 11
  • 62
  • 136
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Yea, this is much nicer. Thanks you very much. Still I am not really warming up with `std::chrono`, but thats probably only me not understanding the library. ;) – Haatschii Apr 23 '13 at 19:21
  • @Haatschii How exactly is this simpler than just casting a duration to an appropriate type? – bames53 Apr 23 '13 at 19:34
  • @bames53 What do you mean with `casting a duration to an appropriate type`? Like the question I linked? – Haatschii Apr 23 '13 at 20:10
  • 1
    @bames53: It depends what you mean by "simple". And what you mean by "is". But, by my aesthetics, it feels more expressive than `duration_cast<...>(...).count()`, so I present it as an alternative. – Mike Seymour Apr 23 '13 at 21:33
  • @bames53: I second Mike. When I read this statement I can directly guess what it does, even if I am not deep into `chrono`, which, at least for me, is completly different in the other example. – Haatschii Apr 23 '13 at 21:56
  • 4
    @MikeSeymour What I see with this method is dividing one duration of time by another duration of time and the result being a unitless value. This seems to me less expressive than alternatives which preserve the dimension. – bames53 Apr 24 '13 at 15:06
  • @bames53: Indeed; the question specifically asked for a unitless value: "store it in an usinged(sic) long". Such a thing is useful in some circumstances; perhaps for interoperability with an API that doesn't use `std::chrono` types. I'm answering the question that was asked, not trying to guess whether the OP really wants he's asking for. If you think a lecture about whether or not to use unitless types would make a better answer, then feel free to post one. – Mike Seymour Apr 24 '13 at 17:45
  • Not an answer, but I think my lecture makes good comments. ;) – bames53 Apr 24 '13 at 21:29
  • Alright, so in purely in terms of what to do on the boundary to break out of the type system, IMO this method looks too benign. Normally durations are safe in the sense that if you try to do something like `milliseconds ms = nanoseconds{100};` you get a compile error (important because in generic programing the types vary). `duration_cast` is used when you specifically want to get around such things and plays on the same skepticism C++ programmers have about the built-in casts to express the risks. Using division instead like this has the same risks as a cast but doesn't look like it. @Haatsch – bames53 Apr 24 '13 at 21:30
  • @bames53: We'll just have to disagree then. To me (and hopefully most C++ programmers), division clearly signals the potential rounding issue, which is exactly analogous to that of integer division. A cast merely says "there's something dodgy going on, and the type system won't help you". One could certainly argue for a stronger type system, requiring a cast from the (theoretically rational) division result to an integer; but we don't have that and, in my opinion, moving the cast elsewhere only serves to replace knowledge with fear and doubt. – Mike Seymour Apr 24 '13 at 22:03
  • 1
    @MikeSeymour "division clearly signals the potential rounding issue, which is exactly analogous to that of integer division" That's true, but at the same time it appears like you're dividing by '1' and you need to know what's going on in order to know that dividing by '1' isn't safe in this case. IMO this is definitely a case that deserves the label of 'something dodgy going on' more than just any old integer division. Breaking out of the type system deserves to _look_ like breaking out of the type system. – bames53 Apr 24 '13 at 23:49
  • 2
    Unfortunately, C++11 does not specify what the epoch is for `system_clock`, or for any other clock. :-( But see http://stackoverflow.com/questions/29799293/when-is-stdchrono-epoch. – Kristian Spangsege Jun 16 '15 at 20:39
  • 5
    This answer is incorrect, although working for most implementations. The standard does not specify what the epoch of a clock is. And indeed, my mingw build of GCC 5.3 uses the system boot time as an epoch which has no relation whatsoever with the unix epoch. – Stefan Jun 05 '16 at 20:27
  • although late to the party, I would suggest that the cast is much more explicit, in that it asserts the desired resolution (milliseconds) and the call to `count()` explicitly retrieves the number of (millisecond) "ticks". This is precisely what was asked for. Note that an operator (such as division) does not explicitly assert a type, so without resorting to the header or documentation, it's not a given that the result is an integral value. It might be floating point, or some other type. – jwm Feb 23 '18 at 20:33
  • also note that `duration_cast` is only required for lossy conversions, so it clearly communicates the danger implicit in leaving the type system. – jwm Feb 23 '18 at 20:35
-2

count() returns long long and AFAIK you have to manually cast long long to unsigned long long by your self.

  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/31986141) – SiggiSv Jun 14 '22 at 11:18