5

A program like this

int
main()
{
    using namespace date;
    std::cout << std::chrono::system_clock::now() << '\n';
}

prints something like 2017-09-15 13:11:34.356648.

Assume I have a string literal "2017-09-15 13:11:34.356648" in my code.

What is the right way to create std::chrono::time_point from it in C++20?

Alexey Starinsky
  • 3,699
  • 3
  • 21
  • 57
  • 2
    FYI: [std::chrono::parse](https://en.cppreference.com/w/cpp/chrono/parse) (since C++20) – Scheff's Cat Feb 19 '22 at 08:12
  • The (currently most voted answer) of the suggested duplicate refers to a pre-C++20 solution. Actually, it would be nice to add a C++20 answer here or there. What makes me uncertain: While `date::from_stream(str, "%Y-%m-%d %H:%M:%S")` might work for the current sample, it will break for other locales. And, finally a stupid idea: If you used `operator<<()` for output... Did you try `operator>>()` for input? – Scheff's Cat Feb 19 '22 at 08:24
  • @Scheff'sCat can it parse nanoseconds? – Alexey Starinsky Feb 19 '22 at 08:28
  • With a bit luck, Howard E. Hinnant may answer this. He's the author of that C++20 formatting stuff and usually reacts on questions concerning time related I/O. I must admit that I don't know but I would suspect that the formatted I/O is capable for all what can be internally represented. – Scheff's Cat Feb 19 '22 at 09:29

1 Answers1

3

Just to be clear, there is no namespace date in C++20. So the code in the question should look like:

#include <chrono>
#include <iostream>

int
main()
{
    std::cout << std::chrono::system_clock::now() << '\n';
}

The inverse of this is std::chrono::parse which operates on streams. You can also use std::chrono::from_stream if desired. parse is a stream manipulator that makes the syntax a little nicer.

istringstream in{"2017-09-15 13:11:34.356648"};
system_clock::time_point tp;
in >> parse("%F %T", tp);

(I've dropped the namespaces just to keep the verbosity down)

The locale used is the global locale in effect at the time the istringstream is constructed. If you prefer another locale use the imbue member function to set the desired locale. The locale will only impact the decimal point character in this example.

The %T will read up to whatever precision the input time_point has (which varies with platform from microseconds to nanoseconds). If you want to be sure you can parse nanoseconds even if system_clock::time_point is coarser than that, then you can parse into a sys_time<nanoseconds> which is a type alias for time_point<system_clock, nanoseconds>.

sys_time<nanoseconds> tp;
in >> parse("%F %T", tp);

If the input stream has precision less than the input time_point, there is no problem. What the stream has will be read, and no more. If the input stream has precision finer than the input time_point, then the parse stops at the precision of the time_point, and the remaining digits are left unparsed in the stream.

Other strptime-like parsing flags are supported.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577