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

使用std::chrono::from_stream解析"DD/MM/YYYY at hh:mm:ss"等时间格式

问题根因与修复方案

1. 绝对时间(带日期)解析失败的原因

你使用duration类型接收包含年/月/日的解析结果是错误的:std::chrono::duration是时间间隔的抽象,本身不携带日期锚点,对应的from_stream重载根本不支持%d、%m、%Y这类日期格式符,因此解析直接失败,返回的dur是调试模式下未初始化的脏值,或是Release模式下的默认0值。

解析带日期的绝对时间应该使用std::chrono::sys_time<Duration>(system_clock时间点的别名),它本身以1970-01-01为基准存储时间,完全支持日期类格式符的解析。

2. 时间间隔解析值正确但误报失败的原因

你的解析结果判断逻辑错误:ss.good()要求流的eofbit、failbit、badbit全部为0,判断条件过于严格。from_stream只要完整解析完所有格式符内容,就算流还没到末尾也不会设置failbit,判断解析是否成功应该用!ss.fail()。你解析5秒间隔时实际已经解析成功,只是被错误的判断逻辑误报了失败。

修复后代码示例

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

using nano = std::chrono::duration<std::uint64_t, std::nano>;
using SysNanoTime = std::chrono::sys_time<nano>;

// 解析时间间隔
template <typename Duration>
Duration ParseDuration(const std::string& str,
                    const std::string& fmt,
                    const Duration& default_val)
{
    Duration dur;
    std::stringstream ss{ str };
    std::chrono::from_stream(ss, fmt.c_str(), dur);

    if (!ss.fail())
    {
        std::cout << "Duration parse success!" << std::endl;
        std::cout << dur.count() << std::endl;
        return dur;
    }
    else
    {
        std::cout << "Duration parse failed!" << std::endl;
        return default_val;
    }
}

// 解析绝对时间点
SysNanoTime ParseTimePoint(const std::string& str,
                          const std::string& fmt,
                          const SysNanoTime& default_val)
{
    SysNanoTime tp;
    std::stringstream ss{ str };
    std::chrono::from_stream(ss, fmt.c_str(), tp);

    if (!ss.fail())
    {
        std::cout << "Time point parse success!" << std::endl;
        std::cout << tp.time_since_epoch().count() << std::endl;
        return tp;
    }
    else
    {
        std::cout << "Time point parse failed!" << std::endl;
        return default_val;
    }
}

int main()
{
    std::string str1("08/03/2021 at 09:37:25"), str2("00:00:05");
    std::string fmt1("%d/%m/%Y at %H:%M:%S"), fmt2("%H:%M:%S");

    auto test1 = ParseTimePoint(str1, fmt1, SysNanoTime{});
    auto test2 = ParseDuration<nano>(str2, fmt2, nano::zero());

    // Windows文件时间转换示例:1601-01-01到1970-01-01的间隔是11644473600秒
    constexpr nano win_file_time_epoch_offset = nano(11644473600LL * 1000000000ULL);
    uint64_t win_file_time = (test1.time_since_epoch() + win_file_time_epoch_offset).count() / 100;
    std::cout << "Windows file time: " << win_file_time << std::endl;
}

额外说明

你选择纳秒作为时间单位完全适配Windows文件时间的处理需求:Windows文件时间以1601-01-01为基准、以100纳秒为单位,只需要计算解析得到的system_clock时间点和1601-01-01基准的差值,再除以100即可得到标准Windows文件时间值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 18:45:06