我正在研究一个机器人项目,它具有来自不同位置的传感器数据,精确到毫秒级(gps同步ntp到1ms内)。
如何将历史日期,时间和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偏移的历史日期时间转换为毫秒的有效方法是什么?
答案 0 :(得分:2)
这是一个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 -= hours{ih};
cout << tp.time_since_epoch() << '\n';
}
输出:
1476157739456ms
自纪元以来,这是Unix Time毫秒的正确数量。如果您需要包含闰秒,则上述链接中有相应的设施,但该部分不是标题(需要使用IANA timezone database)。
此库基于<chrono>
。特别是tp
的类型是std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>
,但语法更漂亮。
如果您的输入流遵循标准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);
如果你想要毫秒的积分值,<chrono>
的{{1}}成员函数可以使用
duration.count()
无论如何切片,这是几行类型安全的代码,没有明确的转换因子。
我注意到你用[c ++]和[c]标记了你的问题。这个答案只涉及C ++语言。 C和C ++是两种不同的语言,如果你必须用C语言编程,那么在C级抽象程序中编程的其他答案之一会更好。
对于好奇的,如果只输出cout << tp.time_since_epoch().count() << '\n';
1476157739456
:
tp
然后输出预期的UTC时间戳:
cout << tp << '\n';
答案 1 :(得分:0)
如果你有以小时+/- 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;
答案 2 :(得分:0)
如果你查看你提到的问题的接受答案,它会处理个别整数。它将字符串拆分为部分,将它们转换为整数,然后使用它们。只需删除转换部分即可。
tm t;
// Fill tm_sec, tm_min, tm_hour and so on
return (mktime(&t) - tz * SECONDS_IN_TIMEZONE) * 1000 + milliseconds
如果时区是一个整数,您可以将它乘以时区的秒数,然后将减去。 +4区域意味着时间比UTC大4小时。另请注意,并非所有时区都有完整的小时数。因此,您可能希望以秒/毫秒或至少几分钟存储时区。