How to compute GPS time of week (gps_tow) from std::chrono::gps_clock::now
?
gps_clock::now
is provided by latest compiler/std: https://en.cppreference.com/w/cpp/chrono/gps_clock/now.
How to compute GPS time of week starting from there https://godbolt.org/z/81vK3n3rG using std::chrono
only?
You can take advantage of the fact that the gps epoch starts at the beginning of the week (where they defined the beginning of the week as Sunday 00:00:00 UTC).
auto gps_now = gps_clock::now();
cout << "GPS Time: " << gps_now << std::endl;
auto gps_weeks = floor<weeks>(gps_now);
auto gps_tow = gps_now - gps_weeks;
cout << "GPS week: " << gps_weeks.time_since_epoch()/weeks{1} << '\n';
cout << "GPS tow: " << gps_tow << '\n';
You just floor
the time to weeks
precision, and then subtract off the integral number of weeks
from the time to get time of week.
This gives you a duration
of the same precision that gps_now
has (nanoseconds
with gcc). This formats the tow
as just a number of nanoseconds
. You can reformat it into days, hours, minutes and fractional seconds with:
auto gps_days = floor<days>(gps_tow);
gps_tow -= gps_days;
cout << "GPS tow: " << gps_days.count() << " days " << format("{:%T}", gps_tow) << '\n';
The full demo currently outputs:
GPS Time: 2023-08-26 12:49:22.394953138
GPS week: 2276
GPS tow: 564562394953138ns
GPS tow: 6 days 12:49:22.394953138
Note that the although the gps epoch was defined to start at the beginning of the UTC week:
cout << format("{:%a %F %T %Z}", clock_cast<utc_clock>(gps_seconds{})) << '\n';
Outputs:
Sun 1980-01-06 00:00:00 UTC
The GPS weeks and UTC weeks become unaligned by 1 second every time there is a leap second (because all GPS weeks are exactly 7*86400 seconds long). So currently the GPS week begins 18s before the UTC week:
cout << format("{:%a %F %T %Z}", gps_seconds{weeks{2276}}) << '\n';
cout << format("{:%a %F %T %Z}", clock_cast<utc_clock>(gps_seconds{weeks{2276}})) << '\n';
Output:
Sun 2023-08-20 00:00:00 GPS
Sat 2023-08-19 23:59:42 UTC
Note how you can use clock_cast
to convert back and forth between UTC and GPS time points. This provides a more homogenous interface compared to the from_utc
/to_utc
static member functions. But otherwise they are the same thing. clock_cast
calls from_utc
/to_utc
under the hood.