fmt icon indicating copy to clipboard operation
fmt copied to clipboard

Invalid (local) %Z and %z with std::chrono::time_point<system_clock> but correct UTC Timestamp (%T) on MSVC

Open wbitesi opened this issue 2 years ago • 4 comments

Printing with MSVC does not work properly using the Timezone.

When running this example with MSVC

fmt::print("Got now as {:%FT%T%z}\n", std::chrono::time_pointstd::chrono::system_clock::clock::now());

I get the output: Got now as 2024-01-18T07:09:51.3559309+0100

The timestamp is UTC (local time was 08:09) and UTC time is indeed 07:09, but my time zone (+0100) is printed instead of the correct +0000. On GCC (12.2 on debian) I get the correct time and timezone.

Tested with fmt 10.2.1 and current master. Minimum sample is here: minimum sample.zip

Changing CXX_STANDARD from 20 to 11 does not lead to different results.

wbitesi avatar Jan 18 '24 07:01 wbitesi

What's the expected behavior? It should just print the UTC time with (+0000) or UTC appended? Or it should print the local time with (+0100)?

zivshek avatar Mar 26 '24 14:03 zivshek

System clock is normally UTC as far as i know (https://en.cppreference.com/w/cpp/chrono/system_clock), so it should print UTC time +0000. This is done on my gcc 12.2 on debian. I got the weird behavior with timestamp in fact as within UTC but local timezone (+0100) instead of UTC Timezone (+0000) appended.

wbitesi avatar Mar 26 '24 14:03 wbitesi

yes, I was able to repro it on Visual Studio, UTC time + EST

zivshek avatar Mar 26 '24 15:03 zivshek

the issue seems to lie in

const auto& facet = std::use_facet<std::time_put<Char>>(loc);
auto end = facet.put(os, os, Char(' '), &time, format, modifier);

in do_write in chrono.h, after calling facet.put, we get the local timezone for Z/z.

Edit: It does look it's getting the localized timezone, since there is no info about what the timezone actually is in this function, I am suprised it works fine on GCC.

https://stackoverflow.com/questions/58288964/why-does-stdput-timestdgmtime-with-the-z-format-give-back-0100-for-utc based on this answer, it's not advised to use 'z'/'Z' to get the timezone other than local timezone from std::put_time, I have repro the same result using std::put_time, there is no timezone info once the tm is produced.

my guess is that on GCC, it always prints the UTC timezone, even you pass in a local time.

zivshek avatar Mar 27 '24 02:03 zivshek