将日期、时间和 UTC 偏移值转换为自 unix 纪元以来的毫秒数?

Posted

技术标签:

【中文标题】将日期、时间和 UTC 偏移值转换为自 unix 纪元以来的毫秒数?【英文标题】:Converting date, time and UTC offset values to milliseconds since unix epoch? 【发布时间】:2017-02-19 04:43:36 【问题描述】:

我正在从事一个机器人项目,该项目具有来自不同位置的传感器数据,精度为毫秒(gps 将 ntp 同步到 1 毫秒内)。

如何将历史日期、时间和 UTC 偏移分量转换为自 unix 纪元以来的毫秒数?也就是说,所有YYYY-mm-dd HH:MM:SS.mS +/-UTC offset 都可以作为单独的整数使用,而不是字符串。

偏移量考虑了夏令时,例如,UTC +1 的时区在夏令时期间的 UTC 偏移量将是 +2。

有一个similar post,但它处理的是字符串格式的日期时间,没有 UTC 偏移信息。

该帖子接受的答案是使用mktime,但在this post 中,一位超过60K 的代表用户评论说:

mktime 将使用您计算机的区域设置将该日期/时间转换为 GMT。如果您不想减去本地时区,请使用 mkgmtime。

我已经确认mktime 确实执行了依赖于夏令时标志tm_isdst 的时区转换。我没有信息是否在夏令时期间进行了观察,只有它们与 UTC 的偏移量。

自 unix 纪元以来,将具有 UTC 偏移量的历史日期时间转换为毫秒的稳健方法是什么?

【问题讨论】:

如果您查看您提到的问题的公认答案,它会处理单个整数。它将字符串拆分为部分,将它们转换为整数,然后使用它们。只需删除转换部分。 是的。请记住,有半小时的时区。所以 timeZone 不应该以小时为单位。 还有刻钟时区。 使用库。提升 Date_time 是一种选择。 @DirkEddelbuettel 感谢您对 Boost.Date_Time 的建议,我看了看,找不到使用 UTC 偏移量获取 unix 纪元的方法。您是否建议手动从 local_date_time 中减去 UTC 偏移量,其中 local_date_time 是使用未调整的日期时间值设置的? 【参考方案1】:

这是一个free, open-source C++11/14 header-only library,它可以完成这项工作。它是fully documented,可在所有 C++11/14 实现中移植。甚至还有一个video presentation。

#include "chrono_io.h"
#include "date.h"
#include <iostream>
#include <sstream>

int
main()

    using namespace std;
    using namespace std::chrono;
    using namespace date;
    istringstream in"2016-10-10 23:48:59.456 -4";
    sys_time<milliseconds> tp;
    int ih;
    in >> parse("%F %T", tp) >> ih;
    tp -= hoursih;
    cout << tp.time_since_epoch() << '\n';

这个输出:

1476157739456ms

这是自纪元以来的正确Unix Time 毫秒数。如果您需要包含闰秒,上述链接中有相应的功能,但该部分不是仅标题(需要使用IANA timezone database)。

这个库是基于&lt;chrono&gt; 的。特别是tp 的类型是std::chrono::time_point&lt;std::chrono::system_clock, std::chrono::milliseconds&gt;,但语法更漂亮。

如果您的输入流遵循标准的 UTC 偏移语法 +/-hhmm 而不是 +/-[h]h,则代码可以简化为:

istringstream in"2016-10-10 23:48:59.456 -0400";
sys_time<milliseconds> tp;
in >> parse("%F %T %z", tp);

这将为tp 输出完全相同的值。

1476157739456ms

也支持这种修改后的语法:

istringstream in"2016-10-10 23:48:59.456 -4:00";
sys_time<milliseconds> tp;
in >> parse("%F %T %Ez", tp);

如果你想要毫秒的整数值,可以使用&lt;chrono&gt;duration.count()成员函数:

cout << tp.time_since_epoch().count() << '\n';

1476157739456

不管你怎么切,这是几行类型安全的代码,没有明确的转换因子。

我注意到您使用 [c++] 和 [c] 标记了您的问题。此答案仅针对 C++ 语言。 C 和 C++ 是两种不同的语言,如果您必须用 C 编程,那么在 C 抽象级别编程的其他答案之一会更好。

如果你只是输出tp

cout << tp << '\n';

然后它输出预期的 UTC 时间戳

2016-10-11 03:48:59.456

【讨论】:

你的演讲真的很棒! :) 该示例编译并运行,但是在运行in &gt;&gt; parse("%F %T", lt) &gt;&gt; ih; 行时我收到Segmentation fault (core dumped)。我错过了什么吗?我正在使用带有标志-std=c++11g++ 编译示例。 包含-0400 的第二个示例运行良好。你的图书馆很棒!有没有一种与创建日期类似的方法来创建日期时间?那是auto x1 = yeary/m/d;。我问的原因是年月日等都是int。您演示文稿中的 make_zoned 函数看起来可能能够获取 int 值?。 我的偏移值也不是时区,而是记录传感器数据时与 UTC 的实际偏移量。因此无需担心夏令时转换,UTC 可以映射到两个本地日期时间。 @rippleing 对于核心转储,在parse 之后检查in.fail()。如果为 true,则 ih 未初始化。哪个版本的 gcc 核心转储了? -std=c++11 应该足够了。 @ripple:日期时间是 chrono::time_point,sys_time 表示 UTC,或 local_time 表示本地要与 time_zone 配对。 auto x1 = sys_daysyeary/m/d + hoursh + minutesm + secondss + millisecondsms(达到你想要的任何精度)。如果您想要本地时间而不是 UTC 时间,请使用 local_days 而不是 sys_days【参考方案2】:

如果您查看您提到的问题的公认答案,它会处理单个整数。它将字符串拆分为部分,将它们转换为整数,然后使用它们。只需放下转换部分。

tm t;
// Fill tm_sec, tm_min, tm_hour and so on
return (mktime(&t) - tz * SECONDS_IN_TIMEZONE) * 1000 + milliseconds

如果 timezone 是整数,您可以将其乘以 timezone 的秒数,如果从 time 乘以 substract。 +4 区域表示时间比 UTC 多 4 小时。另请注意,并非所有时区都有整数小时数。因此,您可能希望以秒/毫秒或至少分钟为单位存储时区。

【讨论】:

【参考方案3】:

如果您的时区以小时 +/- UTC 表示,您可以首先使用 mktime(如链接答案所述)将日期/时间转换为自纪元以来的秒数。然后,添加/减去时区差异。

编辑:

由于mktime 函数假定给定时间是针对当前时区的,因此您还需要将结果移动该数量。

首先,运行tzset() 函数。这会设置两个全局变量:timezone 是当前时间落后于 GMT 的秒数,daylight 表示夏令时是否有效。

struct tm my_time;
// populate fields
int my_tz;
// set to timezone in question as seconds ahead of UTC
time_t t = mktime(&my_time);
t += timezone;
if (daylight) 
    t -= 3600;

t -= my_tz;

【讨论】:

我有 +/-UTC 的时区。我更新了这篇文章,以突出我读到的受人尊敬的用户(60K+ 代表)关于 mktime 自动将日期时间从当前时区转换为 UTC 的内容?这是正确的吗? mktime "将本地时间转换为日历值。"

以上是关于将日期、时间和 UTC 偏移值转换为自 unix 纪元以来的毫秒数?的主要内容,如果未能解决你的问题,请参考以下文章

将 unix 时间转换为 UTC 日期时间

将 UTC 偏移量转换为时区或日期

在 VBA 中,如何以简单的方式将 UTC UNIX 时间戳转换为本地时区日期?

将excel VBA中的日期类型(Sun Apr 01 00:00:00 UTC 2018)转换为自定义函数

如何将UTC时间转化为本地时间

在python中获取给定日期和UTC偏移量的GMT时间