3

To be portable, while I'm using the {fmt} library for formatting dates and times, I encounter a small problem with printing times. Probably fmt treats time as local time, whereas <iostream> prints time as UTC?

Minimal example:

#include <chrono>
#include <fmt/chrono.h>

int main(){ 
    using TimePoint = std::chrono::system_clock::time_point;

    TimePoint localTime = std::chrono::system_clock::now();

    auto localTimeStr = fmt::format("{:%F %T}", localTime);

    std::cout << localTimeStr << std::endl
              << localTime;

     return 0;
}

Output:

2023-03-15 21:47:46
2023-03-15 20:47:46.0631142

I'm using MSVC 19.34, fmt 9.1.0

How to set up fmt to format time correctly in this case?

I read the documentation, but I don't see any solution. I expect to print the same value for the <iostream> and fmt strings. How to format time to be printed in always in UTC using fmt lib?

Kaaml
  • 31
  • 2
  • 3

2 Answers2

3

std::chrono::system_clock represents UTC time.

When you print the clock with fmt::format() using the "{:%F %T}" format, the output is locale-independent. However, when you print the clock with operator<<, that is equivalent to printing it with std::format() using the {:L%F %T} format and the ostream's currently assigned locale.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • From you response I understand that using `fmt::format("{:%F %T}", sth);` is locale independent - so it should print in UTC time? But in code which i show you fmt prints time in local, iostream prints in UTC. So it's no clear for my why? – Kaaml Mar 16 '23 at 16:59
0

It is non-conformance of the fmt library.

By the standard, std::chrono::system_clock::time_point is a point in Unix time, which is very similar to UTC time but without the leap seconds. If %Z is used, the formatter should insert the string "UTC" in the output. The fmt library does something else.

The standard specifies formatters for other clocks such as utc_clock and tai_clock, but fmt [doesn't seem to implement those] as of now.(https://godbolt.org/z/ch3T4TnK8).

For maximum portability, use std::gmtime.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243