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
相关产品推荐
相关产品推荐

