7

I have a double containing seconds. I would like to convert this into a time_t.

I can't find a standard function which accomplishes this. Do I have to fill out the time_t by hand?

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • 4
    _I have a `double` containing seconds_ - seconds since when? – Maxim Egorushkin Jun 23 '15 at 10:36
  • 2
    `time_t` is not usually a `struct` - it's almost universally an integral type. – Sergey Kalinichenko Jun 23 '15 at 10:39
  • @dasblinkenlight Ugh I meant to ask this: http://stackoverflow.com/q/31000677/2642059 – Jonathan Mee Jun 23 '15 at 10:48
  • Whenever someone starts a paragraph with _"I have a double containing [some unit of time]"_ I wish to shout. Please don't ever use floats or doubles for time, at no point in your code. If your collegue tells you to, punch him in the face. This is a really bad idea. (N.B.: the same goes for currency). – Damon Jun 23 '15 at 10:51
  • 1
    @Damon This comes out of a velocity equation, so it will be in `double` at some point. But to prevent "face punchings" I can cast it to a `long`, however it seems the simplest answer is cast directly to a `time_t`. – Jonathan Mee Jun 23 '15 at 10:53
  • 1
    @Damon: I strongly suspect that you're advocating integral types instead. But consider this: What type would be appropriate for the age of the universe? An integral type would be misleading; there are real time durations known only within 3 significant figures. Even `float` is a thousand times more precise. Currency, OTOH, is countable. – MSalters Jun 23 '15 at 12:51
  • @MSalters: Examples where only 3 significant digits are known are of course another thing. I'm referring to the usual stuff that happens when time is used with floating point, such as adding a millisecond, and surprise, it's the same time. Or sometimes time goes backwards, and nobody can explain it. Or the whole numeric integration explodes. It's surely OK to convert time _to_ double for use e.g. within a "velocity calculation" as by the OP (hardly possible otherwise!), but I would only ever keep track of it with integral values and never convert back _from_ double. – Damon Jun 23 '15 at 13:22
  • @Damon: Sometimes the "add one millisecond and it's still the same time" is **precisely** what should happen. The big bang was 10 billion years, and tomorrow it will **still** be 10 billion years ago. If your numerical integration explodes, it probably wouldn't have given you a correct result using integral math. – MSalters Jun 23 '15 at 13:29
  • @MSalters: not really. Saying that 10bn years is still 10bn years tomorrow isn't correct. Of course it makes no _practical_ difference whether you add one day. And that's just where floating point math is useful. However, adding a day a hundred billion times makes a difference of 273 million years. You might say _"still the same"_, as that's still less than 3% of your 10 billion, but it's not. If you were running a simulation of the universe and adding a tiny amount of time (let's say a year to be a little more realistic) would give the same time, nothing would never move. – Damon Jun 23 '15 at 13:50
  • Staying with the universe, you could also argue that (neglecting relativistic effects) a kilometer is a kilometer, everywhere in the universe, and moving at 150km/h is the same speed everywhere. In an universe that measures the distance from its center with floating point math, that is not the case because floating point numbers are unevenly distributed. – Damon Jun 23 '15 at 13:55
  • @Damon: Guess what? For a big bang simulation, that's even a correct outcome. Galaxies don't change at that timescale. In numerical integration, you can't pick an arbitrary step size. And for time, you can't pick an arbitrary time step. An integral number of seconds is choosing an arbitrary step size of 9192631770 periods of Cesium atom ground state radiation. – MSalters Jun 23 '15 at 13:56
  • `double` is a good unit for representing time IMO – M.M May 24 '18 at 04:12
  • @M.M As mentioned here: https://stackoverflow.com/questions/31000399/convert-double-to-time-t?noredirect=1#comment50029501_31000399 for time calculated from a velocity function it's really all that makes sense. Getting it into some standardized duration is the trick. But as I suggest in my answer, `chrono::duration` does seem to be the best solution. – Jonathan Mee May 24 '18 at 12:45

2 Answers2

6

The type of std::time_t is unspecified.

Although not defined, this is almost always an integral value holding the number of seconds (not counting leap seconds) since 00:00, Jan 1 1970 UTC, corresponding to POSIX time.

So, just a safe casting between them could be fine. Also be carefull about portability (because it's type is not specified in the standard) and consider about the values than can not fit while casting from double to integrals.

masoud
  • 55,379
  • 16
  • 141
  • 208
  • It should be pointed out that although there is an implicit cast to convert the values the pointers are not compatible. So if you have `double foo` you can do this: `const time_t bar = foo` You cannot do this: `const time_t* bar = (time_t*)&foo;` – Jonathan Mee Jul 02 '15 at 11:29
4

Chrono Library

As pointed out in deepmax's answer the type of time_t is implementation defined. Therefore a cast is not guaranteed to succeed. Thankfully the chrono library has significantly improved the capabilities of time operations.

Code Example

To demonstrate how this can be done, I have put a Live Example on ideone.

Explanation

As an example of the improved capabilities provided by the chrono library, a double containing seconds can be used to directly construct a chrono::duration<double>.
From there, to_time_t can be used on a chrono::system_clock::time_point so it's just a matter of constructing our chrono::system_clock::time_point with our chrono::duration<double>.
So given a number of seconds in double input we can accomplish an implementation independent conversion like this:

chrono::system_clock::to_time_t(chrono::system_clock::time_point(chrono::duration_cast<chrono::seconds>(chrono::duration<double>(input))))

Simplification

Although we can get this time_t (or a chrono::system_clock::time_point), this is traditionally considered the number of seconds since 00:00:00 in Coordinated Universal Time. Thus, storing the result of "a velocity equation" in a time_t may be confusing for a traditionalist.

The readability of your code would be improved if rather than converting to a time_t you simply stopped at converting to a chrono::duration<double> therefore I suggest you go no further than:

chrono::duration<double>(input)
Hermann Döppes
  • 1,373
  • 1
  • 18
  • 26
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288