为何C++日期格式化无法随不同locale产生差异?
问题描述
预期不同locale环境下,以下C++程序的日期格式化输出会有差异,但实际运行时,输出仅随时间变化,locale切换无影响:
#include <chrono> #include <iostream> #include <locale> #include <format> // 注:原代码可能遗漏该头文件,std::format依赖它 using namespace std; int main(int, char *argv[]) { auto now = chrono::system_clock::now(); auto znow = chrono::zoned_time{argv[1], now}; locale::global(locale(argv[2])); // 尝试使用locale相关格式说明符 cout << std::format("{:%X %x %a %b %c %p %r}", znow) << std::endl; }
运行测试命令(本机已安装885个locale):
$ for locale in $(locale -a); do ./locale-time "Europe/London" ${locale}; done | sort | uniq
输出结果(仅时间变化,locale无影响):
14:51:04 10/21/24 Mon Oct Mon Oct 21 14:51:04 2024 PM 02:51:04 PM 14:51:05 10/21/24 Mon Oct Mon Oct 21 14:51:05 2024 PM 02:51:05 PM 14:51:06 10/21/24 Mon Oct Mon Oct 21 14:51:06 2024 PM 02:51:06 PM 14:51:07 10/21/24 Mon Oct Mon Oct 21 14:51:07 2024 PM 02:51:07 PM 14:51:08 10/21/24 Mon Oct Mon Oct 21 14:51:08 2024 PM 02:51:08 PM 14:51:09 10/21/24 Mon Oct Mon Oct 21 14:51:09 2024 PM 02:51:09 PM
解决方案
std::format默认使用**"C" locale**,不会自动读取全局设置的locale。要让格式化结果随locale变化,需显式将目标locale传递给std::format。
修改后的代码:
#include <chrono> #include <iostream> #include <locale> #include <format> using namespace std; int main(int, char *argv[]) { auto now = chrono::system_clock::now(); auto znow = chrono::zoned_time{argv[1], now}; // 创建目标locale对象 locale target_locale(argv[2]); // 可选:设置全局locale(供其他需要locale的模块使用) locale::global(target_locale); // 显式传递locale给std::format,按目标locale规则格式化 cout << std::format(target_locale, "{:%X %x %a %b %c %p %r}", znow) << std::endl; }
关键说明
std::format提供了接受std::locale对象的重载版本,此时会严格遵循该locale的规则处理日期、时间、文本等内容。- 直接传递目标locale给
std::format比依赖全局设置更可靠,避免全局locale被其他模块修改的干扰。 - 编译时需启用C20及以上标准(
std::format和<chrono>的zoned_time特性依赖C20)。
重新运行测试命令,即可看到不同locale下的格式化差异,比如使用fr_FR.utf8会输出法语的星期、月份名称,日期格式切换为欧洲风格。
内容的提问来源于stack exchange,提问作者John Graham
相关产品推荐
相关产品推荐

