如何在 C++ 中将 gps 时间转换为 utc?
How to convert gps time to utc in c++?
我正在从传感器收集 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')
使用 link“”帮助我了解如何将 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";
Output: 2020-08-18 15:01:09.485516800 UTC
我的下一个问题是,如何从变量“utc_nano”中提取日期和时间?我对 chrono 或日期库不是很熟悉,因此在尝试分隔日期和时间时遇到问题。任何帮助将不胜感激。
我假设闰秒对你很重要,因为你正在处理 gps 时间,它代表物理秒数,UTC 标记为闰秒。用闰秒来操纵 date/times 是相当棘手的,这就是 Unix Time 在计算机系统中如此流行的原因。
在 C++20 计时预览库 中,Unix Time 由 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
和 returns 一个 {is leap second, count of leap seconds}
结构。如果参数指的是闰秒,则第一个成员为真,第二个参数告诉您参数和 1970 之间有多少闰秒。所以第一步是获取 utc_nano
的信息:
auto info = get_leap_second_info(utc_nano);
现在您可以使用此信息创建 sys_time
。因为 sys_time
就像 utc_time
不包括闰秒,你可以减去已发生的闰秒数:
sys_time<nanoseconds> sys_nano{utc_nano.time_since_epoch() - info.elapsed};
现在您在 Unix Time 中得到了纳秒数。截断到 days
精度可以得到 Unix Time:
中的天数
auto sys_day = floor<days>(sys_nano);
sys_day
是一个日期。一天中的时间只是 nanoseconds-precision time_point 和 days-precision time_point:
之间的差异
auto tod = sys_nano - sys_day;
tod
是一次。这是自午夜以来的持续时间。它可能会短一秒钟。该信息位于 info.is_leap_second
.
如果您希望这些类型作为“字段类型”,您可以将 sys_day
转换为类型 year_month_day
:
year_month_day ymd = sys_days;
year_month_day
有 year
、month
和 day
.
的吸气剂
您可以将 tod
转换为 {hours, minutes, seconds, nanoseconds}
结构:
hh_mm_ss hms{tod};
这有吸气剂:hours()
、minutes()
、seconds()
和 subseconds()
。上面的语法假定 C++17。如果在 C++11 或 14 中,语法为:
hh_mm_ss<nanoseconds> hms{tod};
hh_mm_ss
不直接支持 60 秒的计数,但该信息仍在 info.is_leap_second
中。例如
std::cout << hms.seconds().count() + info.is_leap_second << '\n';
当且仅当 info.is_leap_second
为真时才会输出 60。
您甚至可以尝试使用 C 时间相关函数的代码
uint64_t ns = 1281798087485516800ULL + 315964800000000000ULL; // offset between gps epoch and unix epoch is 315964800 seconds
struct timespec ts;
ts.tv_sec = ns / 1000000000ULL;
ts.tv_nsec = ns % 1000000000ULL;
struct tm stm;
gmtime_r(&ts.tv_sec, &stm);
std::cout << stm.tm_year + 1900 << "-" << stm.tm_mon + 1 << "-" << stm.tm_mday << " " << stm.tm_hour << ":" << stm.tm_min << ":" << stm.tm_sec << std::endl;
我正在从传感器收集 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')
使用 link“
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";
Output: 2020-08-18 15:01:09.485516800 UTC
我的下一个问题是,如何从变量“utc_nano”中提取日期和时间?我对 chrono 或日期库不是很熟悉,因此在尝试分隔日期和时间时遇到问题。任何帮助将不胜感激。
我假设闰秒对你很重要,因为你正在处理 gps 时间,它代表物理秒数,UTC 标记为闰秒。用闰秒来操纵 date/times 是相当棘手的,这就是 Unix Time 在计算机系统中如此流行的原因。
在 C++20 计时预览库 中,Unix Time 由 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
和 returns 一个 {is leap second, count of leap seconds}
结构。如果参数指的是闰秒,则第一个成员为真,第二个参数告诉您参数和 1970 之间有多少闰秒。所以第一步是获取 utc_nano
的信息:
auto info = get_leap_second_info(utc_nano);
现在您可以使用此信息创建 sys_time
。因为 sys_time
就像 utc_time
不包括闰秒,你可以减去已发生的闰秒数:
sys_time<nanoseconds> sys_nano{utc_nano.time_since_epoch() - info.elapsed};
现在您在 Unix Time 中得到了纳秒数。截断到 days
精度可以得到 Unix Time:
auto sys_day = floor<days>(sys_nano);
sys_day
是一个日期。一天中的时间只是 nanoseconds-precision time_point 和 days-precision time_point:
auto tod = sys_nano - sys_day;
tod
是一次。这是自午夜以来的持续时间。它可能会短一秒钟。该信息位于 info.is_leap_second
.
如果您希望这些类型作为“字段类型”,您可以将 sys_day
转换为类型 year_month_day
:
year_month_day ymd = sys_days;
year_month_day
有 year
、month
和 day
.
您可以将 tod
转换为 {hours, minutes, seconds, nanoseconds}
结构:
hh_mm_ss hms{tod};
这有吸气剂:hours()
、minutes()
、seconds()
和 subseconds()
。上面的语法假定 C++17。如果在 C++11 或 14 中,语法为:
hh_mm_ss<nanoseconds> hms{tod};
hh_mm_ss
不直接支持 60 秒的计数,但该信息仍在 info.is_leap_second
中。例如
std::cout << hms.seconds().count() + info.is_leap_second << '\n';
当且仅当 info.is_leap_second
为真时才会输出 60。
您甚至可以尝试使用 C 时间相关函数的代码
uint64_t ns = 1281798087485516800ULL + 315964800000000000ULL; // offset between gps epoch and unix epoch is 315964800 seconds
struct timespec ts;
ts.tv_sec = ns / 1000000000ULL;
ts.tv_nsec = ns % 1000000000ULL;
struct tm stm;
gmtime_r(&ts.tv_sec, &stm);
std::cout << stm.tm_year + 1900 << "-" << stm.tm_mon + 1 << "-" << stm.tm_mday << " " << stm.tm_hour << ":" << stm.tm_min << ":" << stm.tm_sec << std::endl;