使用std :: chrono/date :: gps_clock将double gps时间戳转换为utc/tai [英] Using std::chrono / date::gps_clock for converting a double gps timestamp to utc/tai
问题描述
我从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的日期和时区库(适用于C ++ 20)似乎提供了这一确切功能.不幸的是,至少从我所看到的来看,date/tz/chrono库没有方便的方法来实现这种简单的用法.
我必须首先以某种方式将我的双打转移"到已知的时间/日期类型.但是好吧,因为我了解了总体概念,即 时间点 被定义为(或之后的 持续时间 之前) 时钟 的 时代 ,我认为这是一个漂亮的模型.
假设
我应该能够非常轻松地转换模型以适合我的问题,对吧?
就我而言,我有一个时间戳,它是一个时间点,指定为距gps纪元以来的持续时间.现在,我想想,应该有一个时钟类可以为我抽象和处理所有这些.是的!有一个date :: gps_clock和一个date :: gps_time肯定可以完成工作.
问题
我不能让它对我有用.我敢肯定解决方案是微不足道的.
问题
有人可以帮助我,说明如何使用霍华德的日期库解决问题吗?
正是由于未明确指定问题的输入,所以很难回答这个问题:
我从gps_data结构中的GPS设备获得一个时间戳记,将其作为double值,指定为距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
存储在精度为microseconds
的gps时间点中,或者更好.可以使用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 ++ 11/14/17.并进行了少量修改,现在它已成为官方C ++ 20规范的一部分.
I get a timestamp from a GPS device in a gps_data struct as a double.
I'd like to convert this GPS timestamp to UTC and TAI times, something simple as:
void handle_gps_timestamp(double timestamp)
{
double utc = utc_from_gps(timestamp);
double tai = tai_from_gps(timestamp);
do_stuff(gps, utc, tai);
}
Luckily I found Howard Hinnant's date and timezone library (proposed for C++20) that seems to provide this exact functionality. Unfortunately, at least from what I can see, the date/tz/chrono library has no convenient methods that allow this simple usage.
I must first somehow "transfer" my double into a known chrono/date type. But OK, since I understand the overall concept, namely that the timepoint is defined as a duration after (or before) the epoch of a clock, and I think that this is a beautiful model.
Assumption
I should be able to very easily translate that model to fit my problem, right?
In my case, I have a timestamp that is a point in time, specified as the duration since the gps epoch. Now, there should be a class type of a clock that abstracts and handles all of this for me, I'd like to think. And yes! There is a date::gps_clock and a date::gps_time, which surely should do the work.
Problem
I cannot make it work for me. I'm sure the solution is trivial.
Question
Can someone give me a helping hand, showing how I should use Howard's date library applied to my problem?
It is difficult to answer this question precisely because the input to the problem is underspecified:
I get a timestamp from a GPS device in a gps_data struct as a double ... specified as the duration since the gps epoch.
Therefore I'm going to make some assumptions. I'll state all of my assumptions, and hopefully it will be clear how to alter my answer for other guesses/facts about what that double
represents.
Let's say that the double
is a non-integral count of milliseconds since the gps epoch. Let's furthermore assume that I want to capture the precision of this input down to microseconds.
#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";
}
I've arbitrarily created an example input and stored it in gps_input
.
Some using directives make the code a lot less verbose.
A custom chrono::duration
type that exactly matches the documented specification for what the double
represents makes things much simpler, and lessens the chance for errors. In this case I've made a chrono::duration
that stores milliseconds
in a double
and named that type dms
.
Now you simply convert the double
to dms
, and then using round
, convert the dms
to microseconds
, and store those microseconds
in a gps time point with precision microseconds
or finer. One could use duration_cast
in place of round
, but when converting from floating point to integral, I usually prefer round
, which means round-to-nearest-and-to-even-on-tie.
Now that you have a gps_time
, one can use the clock_cast
function to convert to other times such as utc_time
and tai_time
.
This program outputs:
2011-09-14 01:46:40.000001 GPS
2011-09-14 01:46:25.000001 UTC
2011-09-14 01:46:59.000001 TAI
Adjust the milliseconds
and microseconds
units above as needed. For example if the input represents seconds
, the easiest thing to do is to default the second template argument on dms
:
using dms = duration<double>;
This library works with C++11/14/17. And with minor modifications it is now part of the official C++20 specification.
这篇关于使用std :: chrono/date :: gps_clock将double gps时间戳转换为utc/tai的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!