RFC 1123日期格式是Sun, 06 Nov 1994 08:49:37 GMT,共29字符,严格要求英文缩写、逗号空格位置及GMT时区;C++中需用std::put_time配合gmtime、C locale和"%a, %d %b %Y %H:%M:%S GMT"格式字符串生成。

什么是RFC 1123日期格式
RFC 1123定义的日期格式是:Sun, 06 Nov 1994 08:49:37 GMT,共29字符(含空格),严格区分大小写、逗号、空格位置和时区缩写。它被HTTP协议广泛用于Date、Last-Modified等响应头,不是ISO 8601,也不接受UTC或+0000替代GMT。
用std::put_time生成RFC 1123格式(C++11起)
标准库std::put_time能直接格式化std::tm,但必须注意:时区必须为GMT(即UTC+0),且tm.tm_isdst = 0;否则%Z可能输出CST或CEST,违反RFC。
-
std::tm需手动设为GMT时间(例如用gmtime_r或gmtime_s,不可用localtime) - 格式字符串必须为
"%a, %d %b %Y %H:%M:%S GMT"——%a和%b依赖当前locale,若locale非C,可能输出中文星期/月份,导致非法 - 务必在格式化前调用
std::setlocale(LC_TIME, "C"),否则%a和%b不输出英文缩写
示例:
std::setlocale(LC_TIME, "C");
std::time_t now = std::time(nullptr);
std::tm tm_buf {};
#ifdef _WIN32
gmtime_s(&tm_buf, &now);
#else
gmtime_r(&now, &tm_buf);
#endif
std::ostringstream oss;
oss << std::put_time(&tm_buf, "%a, %d %b %Y %H:%M:%S GMT");
std::string rfc1123 = oss.str(); // e.g. "Wed, 01 Jan 2025 00:00:00 GMT"
解析RFC 1123字符串到std::time_t
std::get_time无法可靠解析RFC 1123,因它不处理时区字段(GMT),且对空格/逗号敏感。更稳妥的做法是:先用strptime(POSIX)或手动切分+查表。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
strptime支持%a, %d %b %Y %H:%M:%S %Z,但%Z在glibc中仅识别GMT、UTC、UT,不识别UTC+0000;Windows无strptime - 必须验证解析后
tm.tm_zone == "GMT"(或等价判断),防止客户端伪造时区 - 月份和星期缩写必须匹配英文(
Jan、Sun),不能依赖locale —— 解析前也应设setlocale(LC_TIME, "C")
简化的安全解析逻辑(省略错误检查):
std::setlocale(LC_TIME, "C");
char buf[32];
strncpy(buf, rfc_str.c_str(), sizeof(buf)-1);
buf[sizeof(buf)-1] = '\0';
std::tm tm_parsed {};
if (strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm_parsed)) {
// 注意:strptime不设置tm_isdst,需手动置0
tm_parsed.tm_isdst = 0;
std::time_t t = timegm(&tm_parsed); // 非POSIX,但glibc/BSD支持;Windows需用_mkgmtime
}
跨平台兼容性陷阱
Windows和Linux对timegm、gmtime_s、strptime的支持不一致,直接混用会导致编译失败或运行时未定义行为。
- Windows无
timegm和strptime,需用_mkgmtime和自定义解析,或引入date.h(Howard Hinnant) -
gmtime_r在Windows不可用,要用gmtime_s(带下划线前缀) - MSVC的
std::put_time在早期版本(%a可能仍输出本地语言
如果项目需强跨平台且不引入第三方,建议封装一层适配函数,统一调用gmtime_s/gmtime_r、_mkgmtime/timegm,并硬编码星期/月份英文映射表用于解析——这比依赖系统函数更可控。
真正麻烦的不是格式化,而是确保“GMT”二字被当作时区而非字面字符串校验,以及跨平台时区转换的隐式偏差。稍不留神,GMT就变成UTC+0100,HTTP头立刻失效。

















