2

I have timers where the start and stop times get stored in a SQLite Database.

I want to pull these out and create std::chrono::high_resolution_clock::time_point so I can compare them to now and see how much time is left.

an example stored time: 14903312

typedef std::chrono::high_resolution_clock::time_point TP;

double _estimatedGrowFinish = o.getPlantTimeEstimatedGrowingStopped(); // `14903312`

TP _now = std::chrono::high_resolution_clock::now();

TP _end = ??

I just dont see how one can convert the double value that I have stored to a time_point where I can run some math and decide how much time is left or it the time has past...

The times are being put in the database like:

std::chrono::high_resolution_clock::now() + std::chrono::seconds(20)

Edit: SQLite says this about Dates and Times

TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS").

REAL as Julian day numbers, the number of days since noon in Greenwich on November 24, 4714 B.C. according to the proleptic Gregorian calendar.

INTEGER as Unix Time, the number of seconds since 1970-01-01 00:00:00 UTC.
Jasmine
  • 15,375
  • 10
  • 30
  • 48

1 Answers1

4

You won't be able to use high_resolution_clock for this because the epoch for the high_resolution_clock varies from platform to platform. For example on my platform (OS X), the epoch of high_resolution_clock is whenever I booted up my computer. This clock just counts nanoseconds since then.

system_clock also has an unspecified epoch. However, all 3 implementations I'm aware of use Unix Time as their definition. So if you are willing to assume this observation as fact, you can easily transform time_points between the Julian epoch and the Unix Time epoch by subtracting off the difference between these two epochs.

I.e. to convert a Julian time_point to a Unix Time time_point subtract the time duration from noon in Greenwich on November 24, 4714 B.C. to 1970-01-01 00:00:00 UTC.

To help do this, here are some handy and efficient date algorithms:

http://howardhinnant.github.io/date_algorithms.html

For example to get the number of days between these two epochs as a double:

double const JulianEpoch = days_from_civil(-4714+1, 11, 24) - 0.5;

Note the +1 to convert B.C. years to proleptic Gregorian years (1 B.C. is the year 0, 2 B.C. is the year -1, etc.). I've also subtracted half a day to account for one epoch being at noon, and the other being at midnight.

If estimatedGrowFinishJulian is a time_point representing the number of days since the Julian epoch:

double estimatedGrowFinishJulian = getPlantTimeEstimatedGrowingStopped(); // `14903312`

Then you can get the estimate in days with respect to the Unix Time epoch:

double estimatedGrowFinishCivil = estimatedGrowFinishJulian + JulianEpoch;

Note that this is a time_point. And it is a time_point with epoch consistent with the de-facto epoch of std::system_clock. You can create such a time_point. To do so, first it is handy to create a days duration based on double:

using days = std::chrono::duration
    <
        double,
        std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>
    >;

Now you can say:

days estimatedGrowFinish(estimatedGrowFinishJulian + JulianEpoch);

Recall that this is still a duration, but it represents the number of days since the system_clock epoch. Thus it is really a time_point. You can create the type of such a time_point with:

using DTP = std::chrono::time_point
    <
        std::chrono::system_clock,
        days
    >;

This is a time_point with the same epoch as system_clock, and it ticks once per day, and stores the tick count as a double. Now you can:

DTP end(days(estimatedGrowFinishJulian + JulianEpoch));

This time_point can be compared with std::chrono::system_clock::now() and subtracted from std::chrono::system_clock::now(). If you subtract them, you will get a duration with the same precision as std::chrono::system_clock::period, but stored as a double. On my system this is a duration<double, micro>. And so:

std::cout << (end - now).count() << '\n';

outputs the number of microseconds (as a double) between 14903312 days past the Julian epoch and now (which is quite far into the future).

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • if Howard Hinnant answers your question you know it is right! – Jasmine May 18 '14 at 19:05
  • Can I ask if you have any insight on what we should store in the SQLite db then? Currently we store: `std::chrono::high_resolution_clock::now() + std::chrono::seconds(20)` as `std::chrono::high_resolution_clock::time_point`. That is currently putting something like `14903312` in the database. So first order is to switch from `high_resolution_clock` to `standard_clock. – Jasmine May 18 '14 at 19:34
  • @Jason: I don't know what platform you're on. But I do know that the epoch for `high_resolution_clock` varies from platform to platform, and that on my platform, that epoch changes every time the computer is rebooted. If the database does not need to remain meaningful between computer boots, then you're fine, else you aren't. If these time_points need to be related to an external epoch such as 1970-01-01 or 4714-11-24 B.C. then you are hosed with `high_resolution_clock`. But `system_clock` solves both problems. The solution is not guaranteed by the standard, but I think it is safe. – Howard Hinnant May 18 '14 at 20:50
  • @Jason: I think you need to decide what you want to store in the database, and then convert from what you have to what you want, and store that. If you store what you have, without knowing what you have, then you're on very shaky ground. Examples of things you might reasonably decide to store: seconds since the Unix epoch. milliseconds since the Unix epoch. microseconds since 2000-03-01T00:00:00 UTC. etc. You should also decide if you want to bother with leap seconds or not. Unix Time ignores the existence of leap seconds. – Howard Hinnant May 18 '14 at 21:03
  • I edited the question to reflect what SQLite has. We are storing it as a `std::chrono::high_resolution_clock::time_point` but switching to `std::chrono::system_clock::time_point` – Jasmine May 18 '14 at 21:08