从时代开始将ISO8601字符串转换为毫秒

时间:2018-11-13 21:13:57

标签: c++ c++14

示例字符串:

  

2018-10-31T14:45:21.778952-07:00

我想将其转换为int64_t,表示自纪元以来的毫秒(甚至微秒)。时区可能会有所不同。该代码将在linux机器上执行,但我只能访问std和folly(不能使用任何任意的3P库)。

我进行了搜索,发现了几种对我不起作用的方法:

  1. strptime()和std :: get_time()失去毫秒精度
  2. 更重要的是,它们都不可以处理时区偏移
  3. 其他一些解决方案取决于3P库

有一些简单的方法吗?

1 个答案:

答案 0 :(得分:3)

来自上面的评论:

  

我正在研究使用霍华德的图书馆。但是,它进行了网络通话让我停下来。我假设如果呼叫失败,它将仅使用本地存储的时区名称数据?我们不会处理时区名称,所以我不在乎那些。但是,进行网络呼叫可能是一个问题。

Howard's library是分层的:

  1. 不需要foundational layer的IANA时区数据库,因此从不进行网络呼叫。这是一个单独的标头,仅标头的库。

  2. 一个知道IANA时区数据库的time zone layer。可以将这一层配置为进行网络调用或不进行网络调用(取决于构建标志),甚至使用操作系统的时区数据库(Windows除外)。

您的应用程序不需要time zone layer,因为它只处理UTC偏移量,而不处理时区名称或规则。

这里是将具有示例格式的std::string转换为std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds>的功能。该类型对于system_clock::time_point来说非常冗长,除非保证具有microseconds的精度。 foundational layer的类型别名为date::sys_time<std::chrono::microseconds>

#include "date/date.h"
#include <chrono>
#include <iostream>
#include <sstream>

auto
to_sys_time(std::string s)
{
    using namespace date;
    using namespace std;
    using namespace std::chrono;
    istringstream in{move(s)};
    in.exceptions(ios::failbit);
    sys_time<microseconds> tp;
    in >> parse("%FT%T%z", tp);
    return tp;
}
  • string放入istringstream
  • (可选)将istringstream设置为在解析某些内容失败时引发异常(您可以选择以其他方式处理错误)。
  • 以所需的精度声明您的time_point
  • 以所需的格式对其进行解析。
  • 退货。

您可以像这样行使此功能:

int
main()
{
    auto tp = to_sys_time("2018-10-31T14:45:21.778952-07:00");
    using date::operator<<;
    std::cout << tp << " UTC\n";
    std::cout << tp.time_since_epoch() << '\n';
}
  • 使用所需的输入字符串调用to_sys_time
  • 使namespace date中的流运算符可用。
  • 打印出time_point(这是UTC time_point)。
  • 提取并打印出duration中的time_point

该程序的输出为:

2018-10-31 21:45:21.778952 UTC
1541022321778952µs

当前,该程序将通过删除#include "date/date.h"using namespace date;using date::operator<<;移植到C ++ 20规范草案。