时间点" 2016-12-31 23:59:60 ";是一个有效的时间。在"1970- jan -1"之后的1483228826秒。":60";在秒的显示是正确的,因为在那里插入了一个闰秒(参见wikipedia闰秒)。
我的问题:我如何将这个时间的std::chrono::utc_clock::time_point
转换为本地时间(或任何时区)并打印它,包括":60"第二部分呢?
std::chrono::utc_clock::time_point then;
then += seconds(1483228826);
// Output: 2016-12-31 23:59:60
cout << std::format("{}", time_point_cast<seconds>(then));
// Now convert it to local time
// But this will fail, since zoned_time requires a sys_time
auto local = zoned_time{"Europe/Berlin", then};
我的问题是:负责处理时区的zoned_time
,只接受sys_time
,不接受utc_time
。但是sys_time
忽略闰秒。
如果我在构建zoned_time
之前将utc_time
转换为sys_time
,我的输出将是"…23:59:59"而闰秒就丢失了。
auto local = zoned_time{"Europe/Berlin", clock_cast<system_clock>(then));
cout << std::format("{}", time_point_cast<seconds>(local));
我认为即使在当地时间也应该显示闰秒。毕竟闰日也显示在当地时间里。
不幸的是,没有干净的方法可以做到这一点。使用的时区数据库不识别闰秒。
然而,总是有解决问题的方法。
对于seconds
精度输出,通过运行then
到get_leap_second_info
来找出then
是否指向闰秒是相当容易的:
utc_seconds then{};
then += 1483228826s;
cout << format("{}", then) << 'n';
auto local = zoned_time{"Europe/Berlin", clock_cast<system_clock>(then)};
auto [is_leap_second, elapsed] = get_leap_second_info(then);
if (is_leap_second)
cout << format("{:%F %H:%M:60}", local) << 'n';
else
cout << format("{}", local) << 'n';
输出:
2017-01-01 00:59:60
这可以扩展到亚秒精度,但只是有点混乱。这里是毫秒:
utc_time<milliseconds> then{};
then += 1483228826023ms;
cout << format("{}", then) << 'n';
auto local = zoned_time{"Europe/Berlin", clock_cast<system_clock>(then)};
auto [is_leap_second, elapsed] = get_leap_second_info(then);
if (is_leap_second)
{
cout << format("{:%F %H:%M:60.}", local);
cout << setfill('0') << setw(3) << (then-floor<seconds>(then))/1ms << 'n';
}
else
cout << format("{}", local) << 'n';
输出:
2017-01-01 00:59:60.023
所以简而言之,找出你是否在闰秒。如果不是,就打印当地时间。否则,硬连接":60"
,并计算/格式化子秒(如果适用)。