2
votes

Am trying to replace some boost::gregorian code using c++20 std::chrono, hoping to remove the boost build depedency. Code is reading and writing to json (using nlohmann) so ability to convert dates to and from std::string is critical.

Using g++ 9.3.0 on Ubuntu 20.04. 2 compile-time erorrs, one on std::chrono::parse() and the second on std::put_time()

For error A on std::chrono::parse(), I see here that calendar support (P0355R7), that includes chrono::parse, is not yet available in gcc libstdc++. Anyone know if this is correct or have a link to an ETA for this? or is there something wrong with how I'm calling parse()?

For error B for std::put_time(): since std:put_time() is documented as c++11 feel like I'm missing something silly here. Also find it strange needing to covert through c's time_t and tm. Is there a better way to convert std::chrono::time_point directly to std::string without resorting to c?

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

int main(int argc, char *argv[]) {
    std::chrono::system_clock::time_point myDate;

    //Create time point from string
    //Ref: https://en.cppreference.com/w/cpp/chrono/parse
    std::stringstream ss;
    ss << "2020-05-24";
    ss >> std::chrono::parse("%Y-%m-%e", myDate);   //error A: ‘parse’ is not a member of ‘std::chrono’

    //Write time point to string
    //https://en.cppreference.com/w/cpp/io/manip/put_time
    //http://cgi.cse.unsw.edu.au/~cs6771/cppreference/en/cpp/chrono/time_point.html
    std::string dateString;
    std::time_t dateTime = std::chrono::system_clock::to_time_t(myDate);
    std::tm tm = *std::localtime(&dateTime);
    dateString = std::put_time(&tm, "%Y-%m-%e");    //error B: ‘put_time’ is not a member of ‘std’

    //Write out
    std::cout << "date: " << dateString << "\n";

    return 0;
}
1

1 Answers

3
votes

C++20 <chrono> is still under construction for gcc. I've seen no public ETA's for it.

Your syntax for std::chrono::parse looks correct. If you're willing to use a free, open-source, header-only preview of C++20 <chrono> then you can get it to work by adding #include "date/date.h" and using date::parse instead.

Note that the resulting myDate will be 2020-05-24 00:00:00 UTC.

std::put_time lives in the header <iomanip> and is a manipulator. After adding that header and <iostream> you would use it like this:

std::cout << "date: " << std::put_time(&tm, "%Y-%m-%e") << '\n';

If you need the output in a std::string, you will have to stream the manipulator to a std::stringstream first.

C++20 <chrono> will provide an alternative to the C API for formatting:

std::cout << "date: " << std::format("{%Y-%m-%e}", myDate) << '\n';

The preview library also provides this with a slightly altered format string:

std::cout << "date: " << date::format("%Y-%m-%e", myDate) << '\n';