必须调用setlocale(lc_time, "")才能使strftime输出中文月份/星期,否则即使系统locale为中文也默认返回英文;需注意windows控制台编码匹配及缓冲区大小安全。

用 strftime 输出中文格式时间字符串,但要注意 locale 设置
直接调用 strftime 默认输出英文月份/星期,即使系统语言是中文也不会自动适配。关键在于必须先用 setlocale 切换 C 运行时的 locale,否则 %B、%A 等格式符始终返回英文。
常见错误是只设了系统 locale(如 Linux 的 LANG=zh_CN.UTF-8),却没在程序里调用 setlocale(LC_TIME, "") —— 这会导致 strftime 仍走默认 "C" locale。
-
setlocale(LC_TIME, "")表示按环境变量(LC_TIME或LANG)自动匹配,推荐优先使用 - 若需强制指定,可写
setlocale(LC_TIME, "zh_CN.UTF-8"),但要确保目标系统实际安装了该 locale(Ubuntu 可用locale -a | grep zh_CN查看) - Windows 上对应 locale 名为
Chinese_China.936或Chinese_China.utf8(取决于 MSVC 版本),不兼容zh_CN.UTF-8
struct tm 转字符串的最小安全调用模式
避免缓冲区溢出和未定义行为:必须预估最大长度,并检查 strftime 返回值。它返回实际写入字符数(不含结尾 \0),为 0 表示失败(通常是缓冲区太小或 locale 未生效)。
中文格式通常比英文长(如“十二月” vs “December”),建议缓冲区至少 64 字节;若含年月日时分秒+汉字,128 更稳妥。
char buf[128];
if (strftime(buf, sizeof(buf), "%Y年%m月%d日 %H:%M:%S", &tm) == 0) {
// 失败:可能是 locale 未设置,或格式串非法
strcpy(buf, "invalid time");
}
Windows 下中文输出乱码的典型原因
控制台默认使用 GBK 编码,而 strftime 在 UTF-8 locale 下输出 UTF-8 字节流,直接打印会显示乱码。这不是 strftime 的问题,而是终端编码不匹配。
- 方案一:改用
Chinese_China.936locale,输出 GBK 编码字符串,与 cmd 兼容 - 方案二:保持 UTF-8 locale,但调用
SetConsoleOutputCP(CP_UTF8)(需 Windows 10 1903+) - 方案三:不依赖控制台,将结果写入 UTF-8 文件或 GUI 控件,避免终端编码干扰
跨平台格式化建议:避免依赖 locale 的汉字硬编码
如果项目需稳定输出“一月”“星期一”等,且不能强求用户配置 locale,更可靠的做法是自己映射:
- 准备两个 const char* 数组:
const char* months_zh[] = {"一月", "二月", ..., "十二月"} - 用
tm.tm_mon直接索引,拼接字符串(注意tm_mon是 0–11) - 这样完全绕过 locale,无兼容性风险,也便于国际化(比如切换日语只需换数组)
- 代价是失去
strftime的灵活格式(如自动补零、本地化 AM/PM),但对固定中文需求已足够
真正卡住人的往往不是函数怎么写,而是 locale 没生效、Windows 控制台编码错位、或者以为设了系统环境变量程序就自动继承——这些点不手动验证,调试时容易反复绕圈。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











