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

如何使用std::chrono::parse解析RFC 3164格式的Syslog时间戳?

解决方法

你的测试2失败的核心原因是:Syslog时间戳(%b %e %T)仅包含月、日、时分秒,缺少年份信息,而std::chrono::system_clock的时间点必须包含完整的年月日时分秒,std::chrono::parse无法自动推断年份;%e输出的带前导空格的日期本身不影响解析,但年份缺失是主要障碍。

以下是两种可行的修复方案:

方案1:手动指定年份(适合测试场景)

直接在解析时补充已知年份,将时间戳转换为包含完整日期的格式后解析:

修改test函数中的解析逻辑,针对Syslog格式单独处理:

void test
(
    std::string const& out_fmt,
    std::string const& in_fmt,
    std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds> const& tp
)
{
    std::ostringstream out;
    out << std::vformat(out_fmt, std::make_format_args(tp));
    std::cout << "Tstamp: " << out.str() << "\n";

    std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds> tpp;
    std::istringstream in(out.str());

    if (in_fmt == "%b %e %T")
    {
        // 先解析月日和时分秒
        std::chrono::month_day md;
        std::chrono::hh_mm_ss<std::chrono::seconds> hms;
        if (!(in >> std::chrono::parse("%b %e", md) >> std::chrono::parse(" %T", hms)))
        {
            std::cout << "Parsing failed!\n";
            return;
        }
        // 补充测试用的年份2023
        std::chrono::year y{2023};
        std::chrono::sys_days sd = y/md;
        tpp = sd + hms.to_duration();
    }
    else
    {
        // 原有通用解析逻辑
        if (!(in >> std::chrono::parse(in_fmt, tpp)))
        {
            std::cout << "Parsing failed!\n";
            return;
        }
    }

    std::cout << "Parsed: " << std::vformat(out_fmt, std::make_format_args(tpp)) << "\n";
}

方案2:自动推断年份(符合Syslog规范)

根据RFC3164规则,Syslog时间戳默认使用当前系统年份;若当前月份小于时间戳的月份(比如1月解析12月的日志),则年份需减1。实现代码如下:

void test
(
    std::string const& out_fmt,
    std::string const& in_fmt,
    std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds> const& tp
)
{
    std::ostringstream out;
    out << std::vformat(out_fmt, std::make_format_args(tp));
    std::cout << "Tstamp: " << out.str() << "\n";

    std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds> tpp;
    std::istringstream in(out.str());

    if (in_fmt == "%b %e %T")
    {
        std::chrono::month_day md;
        std::chrono::hh_mm_ss<std::chrono::seconds> hms;
        if (!(in >> std::chrono::parse("%b %e", md) >> std::chrono::parse(" %T", hms)))
        {
            std::cout << "Parsing failed!\n";
            return;
        }
        // 获取当前系统的年月
        auto now = std::chrono::system_clock::now();
        std::chrono::year current_year = std::chrono::floor<std::chrono::years>(now);
        std::chrono::month current_month = std::chrono::floor<std::chrono::months>(now);
        // 自动调整年份
        std::chrono::year target_year = current_year;
        if (current_month < md.month())
        {
            target_year -= std::chrono::years{1};
        }
        // 生成完整时间点
        std::chrono::sys_days sd = target_year/md;
        tpp = sd + hms.to_duration();
    }
    else
    {
        if (!(in >> std::chrono::parse(in_fmt, tpp)))
        {
            std::cout << "Parsing failed!\n";
            return;
        }
    }

    std::cout << "Parsed: " << std::vformat(out_fmt, std::make_format_args(tpp)) << "\n";
}

测试结果

修改后运行代码,测试2将成功输出:

Test 2
Tstamp: May  9 18:25:51
Parsed: May  9 18:25:51

注:std::chrono::parse的%e格式说明符本身支持处理带前导空格或前导零的日期,无需额外处理空格问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:34:56