【问题标题】:Using std::chrono / date::gps_clock for converting a double gps timestamp to utc/tai使用 std::chrono / date::gps_clock 将双 gps 时间戳转换为 utc/tai
【发布时间】:2018-09-02 06:40:09
【问题描述】:

我在 gps_data 结构中从 GPS 设备获取时间戳作为双精度。

我想将此 GPS 时间戳转换为 UTC 和 TAI 时间,如下所示:

void handle_gps_timestamp(double timestamp) 
{
    double utc = utc_from_gps(timestamp);
    double tai = tai_from_gps(timestamp);
    do_stuff(gps, utc, tai);
}

幸运的是,我发现 Howard Hinnant's date and timezone library(针对 C++20 提出的)似乎提供了这种确切的功能。不幸的是,至少从我所见,date/tz/chrono 库没有允许这种简单用法的便捷方法。

我必须首先以某种方式将我的替身“转移”到已知的计时/日期类型。但是好的,因为我理解了整体概念,即 timepoint 被定义为 duration 之后(或之前)时钟epoch,我认为这是一个漂亮的模型。

假设

我应该能够非常轻松地翻译该模型以适应我的问题,对吧?

在我的例子中,我有一个时间戳,它是一个时间点,指定为自 gps 纪元以来的持续时间。现在,应该有一个类类型的时钟为我抽象和处理所有这些,我想。是的!有一个 date::gps_clock 和一个 date::gps_time,它们肯定可以完成这项工作。

问题

我无法让它为我工作。我确信解决方案是微不足道的。

问题

谁能帮我一把,说明我应该如何使用 Howard 的日期库来解决我的问题?

【问题讨论】:

  • 您可以附上到目前为止您尝试过的内容吗?
  • 您的double 代表什么单位?自纪元以来的秒数?
  • 是的,对不起,自纪元以来的秒数。

标签: c++ date gps utc chrono


【解决方案1】:

很难准确地回答这个问题,因为问题的输入没有明确说明:

我在 gps_data 结构中从 GPS 设备获取时间戳作为双精度...指定为自 gps 纪元以来的持续时间。

因此,我将做一些假设。我将陈述我的所有假设,并希望能够清楚地了解如何改变我对double 所代表的其他猜测/事实的回答。

假设double 是自 gps 纪元以来的非整数毫秒数。让我们进一步假设我想将此输入的精度捕获到微秒。

#include "date/tz.h"
#include <cstdint>
#include <iostream>

int
main()
{
    double gps_input = 1e+12 + 1e-3;
    using namespace date;
    using namespace std::chrono;
    using dms = duration<double, std::milli>;
    gps_time<microseconds> gt{round<microseconds>(dms{gps_input})};
    auto utc = clock_cast<utc_clock>(gt);
    auto tai = clock_cast<tai_clock>(gt);
    std::cout << gt << " GPS\n";
    std::cout << utc << " UTC\n";
    std::cout << tai << " TAI\n";
}

我随意创建了一个示例输入并将其存储在gps_input

一些 using 指令使代码不那么冗长。

自定义chrono::duration 类型完全 匹配double 所代表的文档规范,使事情更加更简单,并减少出错的机会。在这种情况下,我创建了一个chrono::duration,将milliseconds 存储在double 中,并将该类型命名为dms

现在您只需将double 转换为dms,然后使用round,将dms 转换为microseconds,并将这些microseconds 存储在gps 时间点中,精度为microseconds 或更好。可以使用duration_cast 代替round,但是当从浮点数转换为整数时,我通常更喜欢round,这意味着从四舍五入到最近的平局。

现在您有了gps_time,可以使用clock_cast 函数转换为其他时间,例如utc_timetai_time

这个程序输出:

2011-09-14 01:46:40.000001 GPS
2011-09-14 01:46:25.000001 UTC
2011-09-14 01:46:59.000001 TAI

根据需要调整上面的millisecondsmicroseconds 单位。例如,如果输入代表seconds,最简单的做法是默认dms 上的第二个模板参数:

using dms = duration<double>;

This library 适用于 C++11/14/17。经过少量修改,它现在已成为官方 C++20 规范的一部分。

【讨论】:

  • 非常感谢霍华德提供这样一个描述性和信息丰富的答案!
  • 我想我对这种轮换和演员的约定不够满意,这让我在开始使用这个库时有点尴尬。
  • 这些是std::chrono 概念。也许这个关于chrono 的视频教程会有所帮助? youtube.com/watch?v=P32hvk8b13M
  • 为了完成这个例子,因为我想要双倍的输出: auto dur = utc.time_since_epoch();自动 duration_in_seconds = std::chrono::duration(dur);双 num_seconds = duration_in_seconds.count();
  • 我很乐意。我刚刚在-std=c++11-std=c++14-std=c++17 下在macOS 上编译它,没有任何错误。你看到了什么,在什么平台和标志上?
【解决方案2】:

另一个答案还不错,但它确实需要您拥有 c++17、curl、运行 cmake 并获取一些自定义库。

作为 .h 和 .cpp 更容易放入的东西是 http://www.leapsecond.com/tools/gpsdate.c

它不处理 TAI 转换,但它也可能在该列表中。

【讨论】:

    猜你喜欢
    • 2013-01-08
    • 2017-06-02
    • 2021-10-13
    • 1970-01-01
    • 1970-01-01
    • 2018-07-27
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    相关资源
    最近更新 更多