0

I have a few lines of code that takes the system clock on my Windows machine and converts it to a double.

std::chrono::time_point<std::chrono::system_clock> currentNow = 
std::chrono::system_clock::now();
auto duration = currentNow.time_since_epoch();
double millis = static_cast<double>(std::chrono::duration_cast<std::chrono::milliseconds>(duration).count());
double origin_time = millis / 1000;

I would like to reverse this later on and convert the double to a string being the format YYYY-mm-dd HH:MM:SS.ffffffff

The first step I have right now is taking the double and passing it as a parameter to chrono::duration.

auto rep = std::chrono::duration<double>(origin_time);

How would I go about using the chrono library to achieve the string specified above, thanks!

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
Kyle
  • 793
  • 6
  • 24
  • 1
    Handy reading: [Documentation for Howard Hinnant's Date Library](https://howardhinnant.github.io/date/date.html) – user4581301 Jan 10 '20 at 18:17
  • I'm avoiding using date.h though it's a possibility if a viable solution for chrono isn't reached. – Kyle Jan 10 '20 at 18:23
  • 1
    `chrono` is almost entirely concerned with the timekeeping. To format the `chrono` time as a string, you're doomed to dropping out of chrono and using the old C time formatting routines or writing something similar to `date`. This is addressed in C++20, pretty much by assimilating `date` into the collective. – user4581301 Jan 10 '20 at 18:32
  • 1
    [date.h](https://howardhinnant.github.io/date/date.html) _is_ a `chrono` solution. It is also a preview of (currently draft) C++20 `` that works with C++11/14/17. The C++11 `` has no built-in formatting capability whatsoever. In C++20 it is just `cout << system_clock::now()`. – Howard Hinnant Jan 10 '20 at 18:33
  • @HowardHinnant If I were to tackle this problem using date.h, how would I go about it. I tested it using https://stackoverflow.com/questions/46516471/how-to-convert-in-modern-c-a-double-into-a-datetime but it ended up with 31127-09-13 02:48:05.4775809 – Kyle Jan 10 '20 at 19:06
  • 2
    Hard to tell without seeing your code. But my first guess is that you converted your `double` into `days` instead of `seconds`. Do you have to convert to `double` in the first place? If you don't escape the `` type-system, that kind of error can't happen. – Howard Hinnant Jan 10 '20 at 19:16
  • It's indeed in seconds and I am unfortunately forced to stay within the chrono domain. The link was the method I tried but as you said, it is indeed in days. – Kyle Jan 10 '20 at 19:28
  • 1
    What happens when you simply change `days` to `seconds` in the definition of `ddays`? – Howard Hinnant Jan 10 '20 at 19:30
  • I ended up going to 1950-01-08 19:35:47.9000000, following this I adjusted the date from December 31st 1899 to January 1st 1970 which fixed it. Looks like I have two solutions, thanks Howard. – Kyle Jan 10 '20 at 19:38
  • 2
    Excellent! Now you know how to use date.h! :-) You could also replace `sys_days{January/1/1970}` with `system_clock::time_point{}`. The only difference is readability, pick whichever you like best. They both mean "system clock epoch". And they are both compile-time constants. – Howard Hinnant Jan 10 '20 at 19:41

1 Answers1

4

Construct a new time_point containing the current epoch:

auto epoch = std::chrono::time_point<std::chrono::system_clock>();

Add your converted duration to this time_point:

auto oldNow = epoch + std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::duration<double>(origin_time));

Convert it into a std::time_t:

auto t_c = std::chrono::system_clock::to_time_t(oldNow);

Print it using formatting facilities for time_t:

std::cout << std::put_time(std::localtime(&t_c), "%F %T");

Example output:

2020-01-10 18:45:48

See it live!

You'll notice it is missing the .ffffffff part. That's because std::put_time has no formatting option for it. You can easily calculate the value yourself and put it at the end of the string, if that's important for you.

Also note that this is much better accomplished using C++20 chrono or Howard's Date library (which is basically the same thing, except for a few bits here and there) as noted in the comments by the man himself. For an overview on it, you may be interested in this answer.

Not a real meerkat
  • 5,604
  • 1
  • 24
  • 55