如何用Howard Hinnant的date库将GPS时间戳(double)转UTC/TAI?
Great question! Howard Hinnant's date/chrono library (now integrated into C++20's standard library) makes this conversion straightforward once you map your double GPS timestamp to the library's time point types. Let's break this down step by step.
First, let's clarify the basics: your double timestamp is presumably the number of seconds since the GPS epoch (1980-01-06 00:00:00 UTC). The library's gps_clock is explicitly tied to this epoch, so we just need to wrap that double value into a gps_time time point, then use clock_cast to handle conversions between GPS, UTC, and TAI clocks—this takes care of all leap second offsets automatically.
Step 1: Include necessary headers
If you're using C20+, you can rely on the standard library directly. For older C versions, you'll need Howard Hinnant's standalone date library:
#include <chrono> // For pre-C++20: #include "date/date.h" using namespace std::chrono; using namespace date; // Required for pre-C++20; in C++20, all types live in std::chrono
Step 2: Implement the conversion functions
We'll build the utc_from_gps and tai_from_gps functions you need, which convert the double GPS timestamp to double values representing seconds since the UTC and TAI epochs respectively:
double utc_from_gps(double gps_seconds) { // Wrap the double seconds into a GPS time point (uses double-precision duration) gps_time<duration<double>> gps_tp{duration<double>{gps_seconds}}; // Convert GPS time point to UTC time point (handles leap seconds automatically) utc_time<duration<double>> utc_tp = clock_cast<utc_clock>(gps_tp); // Extract total seconds since the UTC epoch (1970-01-01 00:00:00) return utc_tp.time_since_epoch().count(); } double tai_from_gps(double gps_seconds) { gps_time<duration<double>> gps_tp{duration<double>{gps_seconds}}; // Convert GPS time point to TAI time point (TAI is consistently 19 seconds ahead of GPS) tai_time<duration<double>> tai_tp = clock_cast<tai_clock>(gps_tp); // Extract total seconds since the TAI epoch (1958-01-01 00:00:00) return tai_tp.time_since_epoch().count(); }
Step 3: Use in your handler function
Now your original handle_gps_timestamp works exactly as you intended:
void handle_gps_timestamp(double timestamp) { double utc = utc_from_gps(timestamp); double tai = tai_from_gps(timestamp); do_stuff(timestamp, utc, tai); // Adjust parameters to match your do_stuff implementation }
Key Notes
- Duration Precision: We use
duration<double>to match your input's double type, avoiding unnecessary precision loss. If your timestamp uses milliseconds (or another unit), adjust the duration accordingly (e.g.,duration<double, std::milli>for milliseconds). - Leap Second Accuracy:
clock_castautomatically applies the correct leap second offsets between GPS and UTC. Ensure you're using the latest version of the library (or C++20 standard library) for up-to-date leap second data. - Human-Readable Formatting: If you need to convert time points to a readable string (e.g.,
YYYY-MM-DD HH:MM:SS), use the library'sformatfunction:auto gps_tp = gps_time<duration<double>>{duration<double>{timestamp}}; auto utc_tp = clock_cast<utc_clock>(gps_tp); std::cout << format("%Y-%m-%d %H:%M:%S", utc_tp) << std::endl;
内容的提问来源于stack exchange,提问作者tompa

