我从gps_data结构中的GPS设备获取时间戳作为double。
我想将此GPS时间戳转换为UTC和TAI时间,简单如下:
void handle_gps_timestamp(double timestamp)
{
double utc = utc_from_gps(timestamp);
double tai = tai_from_gps(timestamp);
do_stuff(gps, utc, tai);
}
幸运的是,我发现Howard Hinnant's date and timezone library(建议用于C ++ 20)似乎提供了这种确切的功能。不幸的是,至少从我所看到的,date / tz / chrono库没有方便的方法允许这种简单的用法。
我必须首先以某种方式将我的双重“转移”为已知的计时/日期类型。但是好的,因为我理解整体概念,即时间点被定义为时钟之后(或之前)的持续时间,我认为这是一个漂亮的模型。
假设
我应该能够非常轻松地翻译该模型以适应我的问题,对吧?
在我的例子中,我有一个时间戳,它是一个时间点,指定为自gps纪元以来的持续时间。现在,应该有一个类型的时钟抽象和处理所有这些,我想,我想。是的!有一个日期:: gps_clock和一个日期:: gps_time,肯定应该做的工作。
问题
我无法让它对我有用。我确信这个解决方案很简单。
题
有人可以帮助我,展示我应该如何使用霍华德的日期库应用于我的问题?
很难准确回答这个问题,因为对问题的输入是不明确的:
我从gps_data结构中的GPS设备获得时间戳作为双倍...指定为自gps纪元以来的持续时间。
因此,我将做一些假设。我将陈述我的所有假设,并希望如何改变我关于double
代表什么的其他猜测/事实的答案。
让我们说double
是自gps时代以来毫秒的非整数计数。让我们进一步假设我想要将此输入的精度捕获到微秒。
#include "date/tz.h"
#include <cstdint>
#include <iostream>
int
main()
{
double gps_input = 1e+12 + 1e-3;
using namespace date;
using namespace std::chrono;
using dms = duration<double, std::milli>;
gps_time<microseconds> gt{round<microseconds>(dms{gps_input})};
auto utc = clock_cast<utc_clock>(gt);
auto tai = clock_cast<tai_clock>(gt);
std::cout << gt << " GPS\n";
std::cout << utc << " UTC\n";
std::cout << tai << " TAI\n";
}
我随意创建了一个示例输入并将其存储在gps_input
中。
一些使用指令使代码更简洁。
自定义的chrono::duration
类型与double
所代表的文档规范完全匹配,使事情变得更加简单,并减少了出错的可能性。在这种情况下,我做了一个chrono::duration
存储milliseconds
在double
并命名为dms
类型。
现在你只需将double
转换为dms
,然后使用round
,将dms
转换为microseconds
,并将这些microseconds
存储在gps时间点,精确microseconds
或更精细。人们可以使用duration_cast
代替round
,但是当从浮点转换为积分时,我通常更喜欢round
,这意味着圆形到最近和甚至在平衡。
现在您有了gps_time
,可以使用clock_cast
函数转换为其他时间,如utc_time
和tai_time
。
该计划输出:
2011-09-14 01:46:40.000001 GPS
2011-09-14 01:46:25.000001 UTC
2011-09-14 01:46:59.000001 TAI
根据需要调整上面的milliseconds
和microseconds
单位。例如,如果输入表示seconds
,最简单的方法是在dms
上默认第二个模板参数:
using dms = duration<double>;
另一个答案并不错,但它确实需要你拥有c ++ 17,curl,运行cmake,并获得一些自定义库。
作为.h和.cpp更易于插入的东西是http://www.leapsecond.com/tools/gpsdate.c。
这不会处理TAI转换,但也可能在该列表上。