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

为何chrono::parse无法解析POSIX日期时间字符串?

问题:使用<chrono>解析POSIX日期字符串失败(不受全局locale影响)

尝试用C++的<chrono>库解析POSIX格式的日期时间字符串,确保不受全局区域设置影响,编写了如下代码,但程序始终输出解析错误,无法得到预期结果。

环境:Arch Linux(内核6.10.7-arch1-1)、g14.2.1,编译时使用C20/C++23标准。
输入字符串:"Fri Jul 5 14:58:21 2019"
预期输出:2019-07-5 14:58:21

代码:

#include <iostream>
#include <locale>
#include <sstream>
#include <string>
#include <chrono>

using namespace std;

void printPosixDateString(string const &str) {
    istringstream stringStream{};
    stringStream.str(str);
    
    locale cLocale{"C"};//locale of C/POSIX language
    stringStream.imbue(cLocale);

    chrono::sys_seconds timeHolder{};//default value is unix time

    stringStream >> chrono::parse("%c", timeHolder);

    if(stringStream.fail()) {
        cout << "Error while parsing date string : " << stringStream.str() << endl;
    }
    else {
        cout << timeHolder;//should print the date object
    }
}

int main(int argc, char **argv) {
    locale french("fr_FR.UTF8");
    locale::global(french);
    cout.imbue(french);
    printPosixDateString("Fri Jul 5 14:58:21 2019");//must work no matter the global locale

    return 0;
}

问题现象:程序始终输出"Error while parsing date string: Fri Jul 5 14:58:21 2019"。


解答

核心原因

问题出在%c格式符的定义与输入字符串的不匹配:
在C/POSIX locale("C" locale)中,%c对应的标准日期时间格式是"%a %b %e %H:%M:%S %Y",其中%e表示日部分为带前导空格的两位字符(例如5号会被格式化为 5,而非单个数字5)。你的输入字符串中日期是5(无前置空格),与%c要求的格式不匹配,导致解析失败。

解决办法

根据你的需求(希望依赖locale的%c而非自定义格式),有两种可行方案:

  1. 调整输入字符串格式
    将输入字符串的日期部分改为带前导空格的形式,例如:

    printPosixDateString("Fri Jul  5 14:58:21 2019"); // Jul后为两个空格,日期是" 5"
    

    这样就能匹配%c在C locale下的格式,解析成功。

  2. 使用自定义格式符匹配输入
    若无法修改输入字符串,可放弃%c,改用与输入完全匹配的自定义格式符:

    stringStream >> chrono::parse("%a %b %d %H:%M:%S %Y", timeHolder);
    

    其中%d可以匹配1位或2位的日数字(g++的<chrono>实现支持这种匹配),能正确解析5或05格式的日期。

额外说明

若要输出2019-07-5(日不带前导零)的格式,默认的operator<<无法实现,需要使用chrono::format自定义输出格式:

cout << chrono::format("%F %T", timeHolder); // 默认输出2019-07-05 14:58:21
// 若要日不带前导零,使用:
cout << chrono::format("%Y-%m-%-d %H:%M:%S", timeHolder);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 23:43:16