Closed wg21bot closed 4 years ago
I strongly object.
Implementations are allowed but not required to get gps_clock::now()
from a GPS receiver.
gps_clock
provides a unique mapping to the civil calendar in its formatting that other clocks to not share. gps_clock
currently reports a civil time that is 18s ahead of system_clock
and utc_clock
. And it correctly reports a physical time difference between two time_points straddling a leap second insertion (unlike system_clock
but like utc_clock
).
The main observable difference between gps_clock
and utc_clock
is its mapping to the civil calendar. This mapping never has 61 seconds in a minute.
Example code:
#include <chrono>
#include <iostream>
int
main()
{
using namespace std;
using namespace std::chrono;
auto now_sys = floor<seconds>(system_clock::now());
auto now_utc = clock_cast<utc_clock>(now_sys);
auto now_gps = clock_cast<gps_clock>(now_sys);
cout << "now_sys = " << now_sys << '\n';
cout << "now_utc = " << now_utc << '\n';
cout << "now_gps = " << now_gps << '\n';
}
Example output:
now_sys = 2019-10-25 16:54:30
now_utc = 2019-10-25 16:54:30
now_gps = 2019-10-25 16:54:48
Implementations are allowed but not required to get gps_clock::now()
from a GPS receiver. Whether they do or not, the example output above will have similar behavior. And this functionality can reduce the possibility of confusing errors when a programmer has to deal with mapping GPS time points to and from civil time.
I'm still unclear as to the actual real-world use, i.e. where would a user expect to get a GPS timepoint from? In this use case are we assuming a normalised GPS timepoint that is independent of the rollover behaviour? GPS rollover is "relatively" frequent so the epoch has short cycles and this is not really supported. I guess my question is, what does a gps_clock timepoint assume and how does that correlate to actual gps feeds (note that normalising may be the only correct behaviour here as different generations of GPS satellites have larger counters and thus different rollover behaviour.)
Let's just assume that a client has a GPS feed, not necessarily live, possibly on file, and knows that the rollover is 1024 weeks. Somehow he has to know or be fed the rollover data (rollover size and count). Here is how he could take the raw data, map it to a civil time not adjusted by leap seconds (the GPS mapping), then convert it to UTC, then convert it back to gps_time
, then recover the initial GPS feed data:
#include <chrono>
#include <iostream>
int
main()
{
using namespace std;
using namespace std::chrono;
// Helpful duration types
using Tow = duration<int, ratio<3, 2>>;
using Frame = duration<int, ratio_multiply<weeks::period, ratio<1'024>>>;
// GPS feed data in integral form
int week_count = 30;
int tow_count = 147'105;
int frame_count = 2;
// Form a gps_time and print out its mapping to the civil calendar
auto tp_gps = gps_seconds{weeks{week_count}} + Tow{tow_count} + Frame{frame_count};
cout << tp_gps << " GPS\n";
// Convert to UTC and print that out
auto tp_utc = clock_cast<utc_clock>(tp_gps);
cout << tp_utc << " UTC\n";
// Convert back to gps_time and recover the feed data
tp_gps = clock_cast<gps_clock>(tp_utc);
auto d_gps = tp_gps.time_since_epoch();
auto frame = duration_cast<Frame>(d_gps);
d_gps -= frame;
auto week = duration_cast<weeks>(d_gps);
d_gps -= week;
auto tow = duration_cast<Tow>(d_gps);
cout << "frame = " << frame.count() << " week = " << week.count()
<< " tow = " << tow.count() << '\n';
}
The output of the program above is:
2019-11-05 13:17:37.5 GPS
2019-11-05 13:17:19.5 UTC
frame = 2 week = 30 tow = 147105
I assert that this is useful functionality. Note that the feed could be live, or be historical data. One might start with the feed and need the UTC time point. Or one might start with the UTC time point and need the feed data.
One might only want the elapsed time since the GPS epoch, which in this example is an intermediate result.
One might want the elapsed time between two GPS feeds.
One might have a large program with both UTC time points and GPS time points and desire the compile-time type-safety that chrono affords to keep from accidentally mixing these two families of time points in an expression (e.g. subtracting a GPS time point from a UTC time point).
I agree that there is a compelling use-case for gps_time
. The concerns expressed in the national body comment (I am not the author) seem to revolve around the time returned by gps_clock::now()
.
Rather than rejecting this national body comment, perhaps it would increase consensus to either:
gps_clock::now()
gps_clock::now()
throw if no GPS clock source is available in the systemLEWG in Belfast: Rejected. No consensus for change.
Use of specific clocks may create expectations that are not delivered (GPS) The "gps" clock has nothing to do with the GNSS service known as GPS except for sharing a common anchor point (epoch) there is no calibration, no feed, no expectation that the "clock" correlates to GPS data streams. It seems a very niche use and given some of the other issues around its interpretation I would suggest it is removed.
Proposed change: delete gps_clock