You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

std::format的%z说明符对local_time无效,MSVC编译报错求解

问题:MSVC中使用std::format的%z说明符编译报错

我需要生成格式为YYYY-MM-DD hh:mm:ss.fff +zz的时间戳,原本打算用std::format的%z说明符实现,但在MSVC中触发编译错误:

error C7595: 'std::basic_format_string<char,const std::chrono::time_point<std::chrono::local_t,std::chrono::durationstd::chrono::system_clock::rep,std::chrono::system_clock::period> &>::basic_format_string': call to immediate function is not a constant expression

对应的测试代码如下:

#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;
}

仅使用"{:%F %T}"作为格式字符串时可正常运行,但无法包含时区信息。请问:

  • 有没有解决办法?
  • 这是编译器的Bug吗?

附:使用strftime的替代实现方案:

#include <chrono>
#include <format>
#include <iostream>
#include <sstream>
#include <iomanip>

std::string get_current_time_and_date() {
  auto time = std::chrono::system_clock::now();
  auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                time.time_since_epoch()) %
            1000;
  auto localT = std::chrono::system_clock::to_time_t(time);
  std::tm timeStruct;
  localtime_s(&timeStruct, &localT);
  std::ostringstream oss;
  const size_t TIME_STR_LEN = 32;

  char buf[TIME_STR_LEN];
  std::strftime(buf, TIME_STR_LEN, "%F %T", &timeStruct);

  char timezonebuf[16];
  std::strftime(timezonebuf, sizeof(timezonebuf), " %z", &timeStruct);

  oss << buf << '.' << std::setfill('0') << std::setw(3) << ms.count() << timezonebuf;
  return oss.str();
}

回答

这是MSVC的编译器Bug

该错误属于MSVC对C++20 std::format处理chrono::local_t类型时的实现缺陷,目前在Visual Studio 2022 17.6及以上版本中已修复,升级编译器版本即可直接解决问题。

现有环境下的解决办法

如果暂时无法升级编译器,除了已提供的strftime方案,还有两种更简洁的替代方式:

  1. 拆分格式化逻辑,单独处理时区
    将日期时间与时区的格式化分开,避免在同一std::format调用中使用%z:

    std::string get_current_time_and_date() {
      auto const sys_time = std::chrono::system_clock::now();
      auto const local_time = std::chrono::current_zone()->to_local(sys_time);
      // 格式化日期时间部分
      auto dt_str = std::format("{:%F %T}", local_time);
      // 计算并格式化时区偏移
      auto offset = std::chrono::current_zone()->get_info(sys_time).offset;
      auto offset_min = std::chrono::duration_cast<std::chrono::minutes>(offset).count();
      auto sign = offset_min >= 0 ? "+" : "-";
      auto hours = std::abs(offset_min) / 60;
      auto mins = std::abs(offset_min) % 60;
      // 拼接完整字符串
      return std::format("{} {}{:02}{:02}", dt_str, sign, hours, mins);
    }
    
  2. 使用zoned_time替代local_t
    std::chrono::zoned_time可以直接被std::format正确格式化,避开local_t相关的实现问题:

    std::string get_current_time_and_date() {
      std::chrono::zoned_time zt{std::chrono::current_zone(), std::chrono::system_clock::now()};
      return std::format("{:%F %T %z}", zt);
    }
    

    该方法无需拆分逻辑,代码简洁且能直接生成符合要求的时间戳。


内容的提问来源于stack exchange,提问作者MHebes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 10:05:31