问题
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?
回答1:
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.
回答2:
The other answer isn't bad but it does require you to have c++17, curl, run cmake, and acquire some custom libraries.
Something that is much easier to drop in as a .h and .cpp would be http://www.leapsecond.com/tools/gpsdate.c.
That doesn't handle the TAI conversion but that might also be on that list.
来源:https://stackoverflow.com/questions/49452157/using-stdchrono-dategps-clock-for-converting-a-double-gps-timestamp-to-utc