Hel*_*den 4 c++ gps utc data-conversion c++11
我正在从传感器收集 GPS 时间(以 ns 为单位),并且正在寻找一种方法将其转换为 C++ 中的 UTC 时间。
我之前在 python 中有一个工作代码。
time_gps = time_gps * 10**(-9) # Converts ns -> s
gps_epoch = pd.datetime(year=1980, month=1, day=6)
delta = pd.to_timedelta(time_gps, unit='s')
time = gps_epoch + delta - pd.to_timedelta(19, unit='s')
Run Code Online (Sandbox Code Playgroud)
使用链接“使用 std::chrono / date::gps_clock 将双 gps 时间戳转换为 utc/tai ”帮助我弄清楚如何从 GPS 时间转换为 UTC。
uint64_t gps_input_ns = 1281798087485516800;
date::gps_time<std::chrono::nanoseconds> gt_nano{date::round<std::chrono::nanoseconds>(std::chrono::duration<uint64_t, std::nano>{gps_input_ns})};
auto utc_nano = date::clock_cast<date::utc_clock>(gt_nano);
std::cout << utc_nano << " UTC\n";
Run Code Online (Sandbox Code Playgroud)
Output: 2020-08-18 15:01:09.485516800 UTC
Run Code Online (Sandbox Code Playgroud)
我的下一个问题是,如何从变量“utc_nano”中提取日期和时间?我对 chrono 或日期库不太熟悉,因此在尝试分离日期和时间时遇到问题。任何帮助将非常感激。
我假设闰秒对您很重要,因为您正在处理 GPS 时间,它代表由 UTC 标记为闰秒的物理秒。使用闰秒来操作日期/时间是相当棘手的,这就是Unix 时间在计算机系统中如此流行的原因。
在C++20 chrono 预览库中,Unix 时间由 建模sys_time,而真正的 UTC 则由 建模utc_time。这两个模型之间的唯一区别是sys_time不计算闰秒和utc_time计算闰秒。
其优点sys_time是存在一种快速有效的算法,可以将自 1970-01-01 00:00:00 以来的持续时间转换为以下字段:年、月、日、时、分、秒、亚秒。因此,如果您想utc_time进入这些领域,诀窍是首先转向utc_time,sys_time同时记住您是否utc_time引用了闰秒。事实上,这正是流操作符所做的utc_time事情。
有一个辅助函数get_leap_second_info可以帮助完成此操作。该函数接受一个utc_time并返回一个{is leap second, count of leap seconds}结构。如果参数涉及闰秒,第一个成员为 true,第二个参数告诉您参数与 1970 年之间有多少个闰秒。因此第一步是获取以下信息utc_nano:
auto info = get_leap_second_info(utc_nano);
Run Code Online (Sandbox Code Playgroud)
现在您可以sys_time使用此信息创建一个。因为sys_time就像utc_time排除闰秒一样,您可以减去已发生的闰秒数:
sys_time<nanoseconds> sys_nano{utc_nano.time_since_epoch() - info.elapsed};
Run Code Online (Sandbox Code Playgroud)
现在您已经有了Unix Time的纳秒计数。截断为精度后可以得到Unix 时间days的天数:
auto sys_day = floor<days>(sys_nano);
Run Code Online (Sandbox Code Playgroud)
sys_day是一个日期。一天中的时间就是纳秒精度 time_point 和天精度 time_point 之间的差异:
auto tod = sys_nano - sys_day;
Run Code Online (Sandbox Code Playgroud)
tod是一个时间。这是自午夜以来的持续时间。可能会短一秒。该信息位于info.is_leap_second.
如果您希望这些类型作为“字段类型”,您可以转换sys_day为 type year_month_day:
year_month_day ymd = sys_days;
Run Code Online (Sandbox Code Playgroud)
year_month_day有year、month和 的吸气剂day。
您可以使用以下方法转换tod为{hours, minutes, seconds, nanoseconds}结构:
hh_mm_ss hms{tod};
Run Code Online (Sandbox Code Playgroud)
它有吸气剂: hours()、minutes()、seconds()和subseconds()。上述语法假定为 C++17。如果在 C++11 或 14 中,语法为:
hh_mm_ss<nanoseconds> hms{tod};
Run Code Online (Sandbox Code Playgroud)
hh_mm_ss不直接支持 60 秒的计数,但该信息仍在info.is_leap_second. 例如
std::cout << hms.seconds().count() + info.is_leap_second << '\n';
Run Code Online (Sandbox Code Playgroud)
info.is_leap_second当且仅当为 true时才会输出 60 。
| 归档时间: |
|
| 查看次数: |
7015 次 |
| 最近记录: |