Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can std::chrono::from_stream convert string to time_point with microseconds accuracy?

TLDR:

std::chrono::sys_time<std::chrono::microseconds> tTimePoint;
std::istringstream stream("2020-09-16 22:00:00.123456");

std::chrono::from_stream(stream, "%Y-%m-%d %H:%M:%S", tTimePoint);

I expected the code above to parse the .123456 as microseconds. However, when running this tTimePoint only contains the date and time excluding subseconds.

Longer:

I am using Visual Studio 2019 with the \cpplatest flag on Windows 10. I have a simple input where users can define their datetime format for the input.

Strings can look like 2020-09-16T22:00:00.123456 or 16.09.2020 22:00:00.123456 or any other valid datetime format as long as there's a way of describing it using the qualifiers listed in the cppreference for std::chrono::from_stream.

Based on the reference and my previous experience with std::format()(which uses the same formatting) I would assume that %S also parses subseconds.

I have also tried std::chrono::parse but this does not state that %S would parse subseconds after the decimal. I have tried various different formats and datetime formats to ensure that this issue does not only occur due to some irregular datetime format.

Is this an error in the cppreference documentation, is this a not fully implemented feature in the Visual Studio implementation or (most likely) am I just simply missing something obvious about this?

Thank you for any help that I can get!

like image 222
Valentin Sagl Avatar asked Jul 28 '21 07:07

Valentin Sagl


1 Answers

As far as I can see, VS2019 has a flaw when using from_stream and a time_point where subseconds are supposed to be used. There is a place in the VS2019 library where it is supposed to deal with it - but it never enters that case.

Fortunately, it works if you use a duration instead of a time_point, so you can work around the problem:

#include <chrono>
#include <sstream>
#include <iostream>

int main() {
    std::istringstream stream("2020-09-16 22:00:00.123456");

    std::chrono::sys_time<std::chrono::microseconds> tTimePoint;

    // extract all but the second:  
    std::chrono::from_stream(stream, "%Y-%m-%d %H:%M:", tTimePoint);

    std::chrono::microseconds micros;

    // extract the second:
    std::chrono::from_stream(stream, "%S", micros);

    // add the duration to the time_point
    tTimePoint += micros;

    std::cout << tTimePoint << '\n';
}

Bugreport - Current state: Fixed In: Visual Studio 2022 version 17.0 Preview 3

like image 68
Ted Lyngmo Avatar answered Sep 22 '22 06:09

Ted Lyngmo