在我能够将其转换为可用的 gmtime 对象或其他任何东西之后,我需要在整点后获得秒...
您可以使用基于<chrono> 的Howard Hinnant's, free, open-source, C++11/14/17 timezone library 将表示自 1970 年 1 月 1 日 00:00:00 UTC 以来的毫秒数的双精度数转换为本地小时后的秒数:
#include "date/tz.h"
#include <iostream>
int
main()
{
using namespace std::chrono;
using namespace date;
double my_utc_ts = 1512695257869;
using ms = duration<double, std::milli>;
sys_time<milliseconds> utc_ms{round<milliseconds>(ms{my_utc_ts})};
auto loc_s = make_zoned(current_zone(), floor<seconds>(utc_ms)).get_local_time();
auto sec_past_hour = loc_s - floor<hours>(loc_s);
std::cout << utc_ms << " UTC\n";
std::cout << sec_past_hour << " past the local hour\n";
}
这为我输出:
2017-12-08 01:07:37.869 UTC
457s past the local hour
如果您的本地时区不是与 UTC 偏移的整数小时数,则输出的第二行将与您不同。
代码说明:
我们从您的输入开始my_utc_ts。
下一行创建了一个自定义std::chrono::duration,它以double 作为表示,milliseconds 作为精度。这个类型别名被命名为ms。
下一行构造utc_ms,它是一个std::chrono::time_point<system_clock, milliseconds>,持有1512695257869,表示时间点2017-12-08 01:07:37.869 UTC。到目前为止,还没有进行实际的计算。只需将 double 1512695257869 转换为表示自 1970-01-01 00:00:00 UTC 以来整数毫秒的类型。
这一行开始计算:
auto loc_s = make_zoned(current_zone(), floor<seconds>(utc_ms)).get_local_time();
这将创建一个 {time_zone, system_time} 对,能够在 UTC 和本地时间之间进行映射,使用 time_zone 作为该映射。它使用current_zone() 查找计算机的当前时区,并将时间点utc_ms 从毫秒精度截断为秒精度。最后尾随的.get_local_time() 从此映射中提取本地时间,精度为秒,并映射到当前时区。也就是说,loc_s 是自 1970-01-01 00:00:00 UTC 以来的秒数,由您的本地时区在 2017-12-08 01:07:37 生效的 UTC 偏移量抵消世界标准时间。
现在,如果您将 loc_s 截断为小时的精度,并从 loc_s 中减去该截断的时间点,您将获得本地小时后的秒数:
auto sec_past_hour = loc_s - floor<hours>(loc_s);
整个计算只是上面的两行代码。接下来的两行简单地流出utc_ms 和sec_past_hour。
假设您的本地时区在 2017 年 12 月 8 日 01:07:37 UTC 时与 UTC 偏移了整数小时,您可以仔细检查:
457 == 7*60 + 37
确实,如果你可以假设你的本地时区总是与UTC偏移整数小时,上面的程序可以通过不映射来简化当地时间:
sys_time<milliseconds> utc_ms{round<milliseconds>(ms{my_utc_ts})};
auto utc_s = floor<seconds>(utc_ms);
auto sec_past_hour = utc_s - floor<hours>(utc_s);
结果将是相同的。
(警告:并非所有时区都与 UTC 偏移整数小时)
如果已知您的数据库是使用不是计算机当前本地时区的时区生成的,则可以通过将 current_zone() 替换为您的数据库生成时使用的 IANA 时区标识符来考虑这一点,例如:
auto loc_s = make_zoned("America/New_York", floor<seconds>(utc_ms)).get_local_time();
更新
整个库基于 C++11 引入的 std<chrono> 库。以上utc_ms和loc_s的类型是std::chrono::time_point的实例化,sec_past_hour的类型是std::chrono::seconds(它本身就是std::chrono::duration的实例化)。
durations 可以使用.count() 成员函数转换为它们的“表示”类型。对于seconds,此表示类型将是带符号的 64 位整数。
有关<chrono> 的更详细视频教程,请参阅此Cppcon 2016 presentation。本演示文稿将鼓励您尽可能避免使用.count() 成员函数。
例如,不是将sec_past_hour 转换为long 以便您可以将其与数据集的其他值进行比较,而是将数据集的其他值转换为std::chrono::durations 以便您可以将它们与sec_past_hour 进行比较.
例如:
long other_data = 123456789; // past the hour in microseconds
if (microseconds{other_data} < sec_past_hour)
// ...
这个 sn-p 显示 <chrono> 将如何为您处理单位转换。这意味着您不会犯错误,例如当您应该乘以除以 1,000,000 时,或者用错误的零个数拼写“百万”。