std::format %z 说明符不适用于 local_time

MHe*_*bes 5 c++ c++20 fmt

我想获取格式为“YYYY-MM-DD hh::mm::ss.fff +zz”的时间戳。

我以为我可以使用%z说明符 forstd::format来执行此操作,但我在 MSVC 上收到此错误:

error C7595: 'std::basic_format_string<char,const std::chrono::time_point<
std::chrono::local_t,std::chrono::duration<std::chrono::system_clock::rep,std::chrono::system_clock::period>> &>::basic_format
_string': call to immediate function is not a constant expression
Run Code Online (Sandbox Code Playgroud)
error C7595: 'std::basic_format_string<char,const std::chrono::time_point<
std::chrono::local_t,std::chrono::duration<std::chrono::system_clock::rep,std::chrono::system_clock::period>> &>::basic_format
_string': call to immediate function is not a constant expression
Run Code Online (Sandbox Code Playgroud)

如果我用作"{:%F %T}"格式字符串,它工作正常(但显然不包括时区)。这告诉我该错误消息是无意义的,但是有什么办法可以解决这个问题吗?这是编译器中的错误吗?


对于后代,这里有一个使用 good old 的解决方法strftime

#include <chrono>
#include <format>
#include <iostream>

std::string get_current_time_and_date() {
  auto const time =
      std::chrono::current_zone()->to_local(std::chrono::system_clock::now());
  return std::format("{:%F %T %z}", time);
}

int main() {
  std::cout << get_current_time_and_date() << "\n";
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

hea*_*run 7

std::chrono::time_zone::to_local返回 an std::chrono::local_time,它是std::chrono::time_point使用 anstd::chrono::local_t作为其第一个模板参数的 an。然而,cppreference 上的引用std::chrono::local_t(强调我的):

\n
\n

该类local_t是一个伪时钟/\xe2\x80\xa6/ ,指示该时间点表示相对于尚未指定的时区的本地时间。

\n
\n

换句话说,这样的时间点(返回std::chrono::time_zone::to_local的)是与时区无关的,它不包含有关所使用时区的任何信息。

\n

如果你尝试改变

\n
return std::format("{:%F %T %z}", time);\n
Run Code Online (Sandbox Code Playgroud)\n

\n
return std::vformat("{:%F %T %z}", std::make_format_args(time));\n
Run Code Online (Sandbox Code Playgroud)\n

你会看到它抛出一个std::format_error带有描述的“format argument does not contains the information required by the chrono-specs”

\n

标准草案中有一条注释(#13):

\n
\n

如果使用%Z%z或 的修改版本,则会引发%z类型异常。format_error

\n
\n

换句话说,%z不支持local_time(因为无论如何都不包含时区信息local_time)。

\n
\n

正如巴里所建议的,也许std::choro::zoned_time这就是你的想法。它确实允许%z说明符。这是一个修改后的例子:

\n
#include <chrono>\n#include <format>\n#include <iostream>\n#include <string>\n\nstd::string get_current_time_and_date()\n{\n    const auto zt{ std::chrono::zoned_time{\n        std::chrono::current_zone(),\n        std::chrono::system_clock::now() } };\n    return std::format("{:%F %T %z}", zt);\n}\n\nint main()\n{\n    std::cout << get_current_time_and_date() << \'\\n\';\n}\n
Run Code Online (Sandbox Code Playgroud)\n

  • 可以补充一点,OP可能想要的不是“current_zone()-&gt;to_local(now)”,而是“zoned_time(current_zone(), now)”,它确实与该说明符一起使用。 (3认同)