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

C++14下使用Date库转换时区时hh_mm_ss模板参数匹配问题

GMT转指定时区tm结构体的hh_mm_ss模板参数匹配问题

我使用C++14和Howard Hinnant开发的Date库,尝试将GMT(UTC)时间转换为指定时区时间并转为tm结构体,流程逻辑正常,但构造date::hh_mm_ss对象时出现模板参数不匹配错误。相关代码如下:

tm Time_hrv::gmtTM_to_timezoneTM(const tm& timeTM_gmt, const std::string& wanted_timezoneStr){
    assert(timeTM_gmt.tm_year < 1000);// 年份是相对于1900的差值,比如2020对应120
    assert(timeTM_gmt.tm_mon < 12);// 月份范围[0,11]
    assert(timeTM_gmt.tm_mday > 0 && timeTM_gmt.tm_mday<=31);// 日期范围[1,31]

    time_t timeT_gmt = Time_hrv::timeTM_to_timeT(timeTM_gmt);
    auto chronoTime_gmt = std::chrono::system_clock::from_time_t(timeT_gmt);

    const date::time_zone* wanted_timeZone =  timeZone_fromString(wanted_timezoneStr);
    
    // local_time并非特指本地时区时间,只是未关联时区的本地时间表示
    // 构造zoned_time时才会将其与指定时区关联
    auto lt = wanted_timeZone->to_local(chronoTime_gmt);
    auto localDay = date::floor<date::days>(lt);

    date::year_month_day ymd{ localDay };
    date::hh_mm_ss<std::chrono::milliseconds> hms{ lt - localDay };  // <--- 错误位置
    tm result = {0};
    result.tm_year = int{ymd.year()} - 1900;
    result.tm_mon = unsigned{ymd.month()} -1;
    result.tm_mday = unsigned{ymd.day()};
    result.tm_hour = (int)hms.hours().count();
    result.tm_min = (int)hms.minutes().count();
    result.tm_sec = (int)hms.seconds().count();
    return result;
}

问题原因

错误根源在于lt - localDay的实际类型与指定的std::chrono::milliseconds不匹配:

  • lt是date::local_time类型,其底层时间精度由std::chrono::system_clock决定,C++14标准并未强制规定system_clock的精度,不同编译器实现可能是微秒、纳秒或其他精度。
  • 手动指定hh_mm_ss的模板参数为milliseconds,但lt - localDay的实际类型是system_clock对应的精度时长(比如microseconds或nanoseconds),导致模板参数类型不兼容。

解决方案

方案1:自动推导模板参数

让编译器自动推导lt - localDay的类型,无需手动指定:

auto hms = date::hh_mm_ss{lt - localDay};

方案2:显式转换为毫秒精度

如果业务逻辑必须使用毫秒精度,显式将差值转换为milliseconds:

auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(lt - localDay);
date::hh_mm_ss<std::chrono::milliseconds> hms{diff};

方案3:复用差值的原生类型

直接使用差值的实际类型作为hh_mm_ss的模板参数:

using diff_duration = decltype(lt - localDay);
date::hh_mm_ss<diff_duration> hms{lt - localDay};

补充说明

无论哪种方案,后续获取时分秒的代码无需修改,hh_mm_ss会自动适配对应的精度类型,正确返回小时、分钟、秒的计数值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 22:10:30