rfc 1123时间格式严格要求为“sun, 06 nov 1994 08:49:37 gmt”,须满足:星期/月份缩写全大写且固定(sun–sat、jan–dec)、日期两位补零、年份四位、时间hh:mm:ss补零、时区必须字面量“gmt”(非utc或小写)、各字段间空格数量固定,且std::get_time无法可靠解析逗号和%z,需手动校验。

什么是RFC 1123时间格式的准确要求
RFC 1123定义的HTTP日期格式是:Sun, 06 Nov 1994 08:49:37 GMT。它不是任意带时区的ISO格式,也不是strftime里常见的%a, %d %b %Y %H:%M:%S %Z就能直接匹配的——关键陷阱在于:%Z在多数C++标准库实现中无法可靠输出GMT(而会输出UTC、空字符串或本地时区缩写),且std::get_time对周几和月份的英文缩写敏感,大小写必须严格匹配。
它必须满足以下全部条件:
- 首字段是英文星期缩写(
Sun–Sat),全大写,后跟逗号和空格 - 日为两位十进制数(
01–31),前面补零 - 月为英文缩写(
Jan–Dec),全大写 - 年为四位十进制数
- 时间部分为
HH:MM:SS(24小时制,补零) - 时区必须是字面量
GMT,不能是UTC、UT或空格 - 各字段间空格数量固定:日与月之间一个空格,月与年之间一个空格,年与时间之间一个空格,时间与时区之间一个空格
用std::get_time解析但必须手动校验时区
std::get_time能解析前七项(星期、日、月、年、时、分、秒),但无法约束时区字段为字面量GMT。它会把GMT、UTC甚至ABC都当作有效时区读入(存入tm.tm_isdst等字段),且不报错。
正确做法是先用std::get_time尝试解析前七字段,再单独检查剩余字符串是否恰好为" GMT"(注意开头有一个空格):
std::string s = "Sun, 06 Nov 1994 08:49:37 GMT";
std::tm t = {};
std::istringstream iss(s);
iss >> std::get_time(&t, "%a, %d %b %Y %H:%M:%S");
if (iss.fail()) {
// 解析失败,格式不对
}
// 检查是否剩下" GMT"
std::string leftover;
iss >> leftover;
if (leftover != "GMT") {
// 不符合RFC 1123(比如剩了"UTC"或为空)
}
注意:%a和%b依赖当前locale。必须在调用前设为"C" locale,否则中文系统可能匹配不了Nov:
std::ios_base::sync_with_stdio(false);
std::cin.imbue(std::locale("C"));
// 或对iss单独设置:
iss.imbue(std::locale("C"));
为什么不用std::chrono::parse(C++20)
C++20的std::chrono::parse看起来更现代,但它对RFC 1123支持不完整:parse(iss, "%a, %d %b %Y %T %Z", tp)中的%Z仍无法强制限定为GMT字面量;且%Z实际行为依赖底层C库,Linux上常只识别GMT,macOS可能接受UTC,Windows表现不一。
更严重的是:std::chrono::parse不提供“剩余输入”检查能力——它可能成功解析到1994-11-06 08:49:37,却忽略后面多出的XYZ,导致"Sun, 06 Nov 1994 08:49:37 XYZ"被误判为合法。
所以即使你用C++20,仍需手动验证结尾是否严格等于" GMT",并确保输入流已到末尾。
最稳妥的方案:先正则粗筛,再get_time精验
纯靠std::get_time易受locale和残留输入干扰。建议前置正则快速排除明显非法格式:
用std::regex匹配整体结构(注意C++ regex对\s跨平台兼容性差,显式写空格):
const std::regex r(R"(^[A-Z][a-z]{2}, \d{2} [A-Z][a-z]{2} \d{4} \d{2}:\d{2}:\d{2} GMT$)");
if (!std::regex_match(s, r)) return false;
这个正则只做字符级校验,不解析语义(比如不检查Feb 30),但它能立刻拦截:"sun, 6 Nov..."(小写)、"06 Nov 94..."(两位年)、"GMT "(尾部空格)、"UTC"等典型错误。通过后再走std::get_time + locale + 剩余字段检查流程,效率和健壮性都更高。
RFC 1123的坑不在年月日逻辑,而在那些看似微小的字面量约束——GMT必须全大写、必须紧贴前面空格、不能多不能少。漏掉任一细节,HTTP服务器就可能拒绝你的请求头。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











