Closed ecorm closed 3 years ago
Just a note that hinnant/date pollutes the preprocessor namespace with short, unprefixed macros. See https://github.com/HowardHinnant/date/issues/135
That may be a showstopper in directly making use of that library to support chrono date formatting flags.
Thanks for the suggestion. Could you elaborate what specifically you are looking for, maybe with an example?
Here's a C++20 example that formats a std::chrono::timepoint into a ISO8601 date/time.
std::chrono::time_point t = std::chrono::system_clock::now();
std::format(std::locale::classic(), "{:%FT%TZ}", t); // Prints something like 2021-03-31T12:34:56.123456789Z
The chrono format specifiers are documented here: https://eel.is/c++draft/time.format
Those that are specific to the Gregorian calendar are (here summarized):
Specifier | Replacement |
---|---|
%a | The locale's abbreviated weekday name. |
%A | The locale's full weekday name. |
%b | The locale's abbreviated month name. |
%B | The locale's full month name. |
%c | The locale's date and time representation. |
%C | The year divided by 100 using floored division. |
%d | The day of month as a decimal number. %Od produces the locale's alternative representation. |
%D | Equivalent to %m/%d/%y. |
%e | The day of month as a decimal number. %Oe produces the locale's alternative representation. |
%F | Equivalent to %Y-%m-%d. |
%g | The last two decimal digits of the ISO week-based year. |
%G | The ISO week-based year as a decimal number. |
%j | Number of days (duration), or day of the year (time_point). |
%m | The month as a decimal number. %Om produces the locale's alternative representation. |
%u | The ISO weekday as a decimal number. Ou produces the locale's alternative representation. |
%U | The week number of the year as a decimal number. %OU produces the locale's alternative representation. |
%V | The ISO week-based week number as a decimal number. %OV produces the locale's alternative representation. |
%w | The weekday as a decimal number. %Ow produces the locale's alternative representation. |
%W | The week number of the year as a decimal number. OW produces the locale's alternative representation. |
%x | The locale's date representation. %Ex produces the locale's alternate date representation. |
%X | The locale's time representation. %EX produces the locale's alternate time representation. |
%y | The last two decimal digits of the year. %Oy produces the locale's alternative representation. %Ey produces the locale's alternative representation of offset from %EC (year only). |
%Y | The year as a decimal number. %EY produces the locale's alternative full year representation. |
%z | The offset from UTC in the ISO 8601:2004 format. %Ez and %Oz insert a : between the hours and minutes. |
%Z | The time zone abbreviation. |
The C++11 std::put_time
could be leveraged to obtain the platform's locale-dependent names, but would involve std::basic_ostream
and could be slow.
Also, arbitrary time zones would not be feasible without hinnant/date's tz.h
. The local time zone offset is probably doable without resorting to 3rd party libraries.
Note that your example already works (godbolt):
#include <fmt/chrono.h>
int main() {
std::chrono::time_point t = std::chrono::system_clock::now();
auto s = fmt::format(std::locale::classic(), "{:%FT%TZ}", t);
fmt::print("{}", s);
}
Output:
2021-04-01T17:19:54Z
Do you have an example that doesn't?
It appears I misinterpreted the fmt library code and assumed my example wouldn't work. I apologize. I'm going to try all of the above listed format specifiers and report back on which ones don't work.
They all work in Godbolt in C++11 mode, GCC 6.1. Sorry for the trouble.
When I was perusing the code, I saw report_no_date()
on this line https://github.com/fmtlib/fmt/blob/7c43f8b896be886acd4e6e0ba61f71a8aa1ebc35/include/fmt/chrono.h#L702 and incorrectly assumed that calendar-related specifiers were not supported. I should have known better to test before raising the issue.
It would be useful to have the chrono date formatting flags supported. @HowardHinnant 's date library could be used to perform the Gregorian date calculations.
__has_include
or some other preprocessor magic could be used to detect the presence of<date/date.h>
and then provide the implementation accordingly.If using hinnant/date is not feasible, then his algorithms are provided here: http://howardhinnant.github.io/date_algorithms.html