I would like to convert string data to struct tm
(c) or std::chrono::time_point
. The problem is I wanna working solution for both standard libc (glibc and musl). I have tree standard formats that I wanna parse.
RFC-1123
Sun, 06 Nov 1994 08:49:37 GMT
RFC-850
"Sunday, 06-Nov-94 08:49:37 GMT"
ANSI C's asctime format
Sun Nov 6 08:49:37 1994"
Is there any way to make it work? std::get_time
has a bug
strptime
work fine (and quick) on glibc but fail against musl.
Any idea? I don't wanna use stream like in get_time
. But If it would be necessary that fine. (It's ok to use GCC5> and c++11 standard)
Howard Hinnant's free, open source, header-only, date/time library can parse these formats into a std::chrono::time_point
, even in the context of faulty get_time
and strptime
facilities. It does require the use of std::istringstream
though. Here is what it looks like:
#include "date.h"
#include <sstream>
std::chrono::system_clock::time_point
parse_RFC_1123(const std::string& s)
{
std::istringstream in{s};
std::chrono::system_clock::time_point tp;
in >> date::parse("%a, %d %b %Y %T %Z", tp);
return tp;
}
std::chrono::system_clock::time_point
parse_RFC_850(const std::string& s)
{
std::istringstream in{s};
std::chrono::system_clock::time_point tp;
in >> date::parse("%a, %d-%b-%y %T %Z", tp);
return tp;
}
std::chrono::system_clock::time_point
parse_asctime(const std::string& s)
{
std::istringstream in{s};
std::chrono::system_clock::time_point tp;
in >> date::parse("%a %b %d %T %Y", tp);
return tp;
}
This can be exercised like this:
#include <iostream>
int
main()
{
auto tp = parse_RFC_1123("Sun, 06 Nov 1994 08:49:37 GMT");
using namespace date;
std::cout << tp << '\n';
tp = parse_RFC_850("Sunday, 06-Nov-94 08:49:37 GMT");
std::cout << tp << '\n';
tp = parse_asctime("Sun Nov 6 08:49:37 1994");
std::cout << tp << '\n';
}
and outputs:
1994-11-06 08:49:37.000000
1994-11-06 08:49:37.000000
1994-11-06 08:49:37.000000
The parse flags %a
and %b
are normally locale-dependent. However if you compile this library with -DONLY_C_LOCALE=1
it becomes locale independent. It should give the same result either way. But from a practical standpoint, if you compile without -DONLY_C_LOCALE=1
and you don't get the results above, you have to submit a bug report to your std::lib vendor.
If you compile with -DONLY_C_LOCALE=1
and you don't get the results above, rattle my cage, and I will have it fixed within days, if not hours.