【问题标题】:Read time from std::string as UTC time从 std::string 读取时间作为 UTC 时间
【发布时间】:2016-08-11 13:21:42
【问题描述】:

在我的一个程序中,我必须多次阅读几种不同的格式。然而,在所有格式中,时间都以 UTC 给出(即不在我当地的时区)。对于接受日期字符串和格式字符串并输出std::time_t 时间戳的函数来说,最好的方法是什么?

目前我正在使用 boost

#include "boost/date_time/gregorian/gregorian.hpp"
#include "boost/date_time/posix_time/posix_time.hpp"

std::time_t to_timestamp_utc(const std::string& _dateString) {
    using namespace boost::gregorian;
    using namespace boost::posix_time;
    return to_time_t(ptime(from_undelimited_string(_dateString)));
}

但这仅适用于“YYYYMMDD”格式。另一方面,标准库函数std::get_time 假定输入日期在我的本地时间而不是UTC 格式(或者至少我还没有找到改变它的方法)。欢迎提出任何建议。

当前解决方案基于 Maxim Egorushkin 的建议。

std::time_t utc_to_timestamp(const std::string& _dateString, const std::string& _format) {
    // Set sec, min, hour to zero in case the format does not provide those
    std::tm timeStruct;
    timeStruct.tm_sec = 0;
    timeStruct.tm_min = 0;
    timeStruct.tm_hour = 0;
    char* const result = strptime(_dateString.c_str(), _format.c_str(), &timeStruct);
    // Throw exception if format did not work
    REQUIRE(result == _dateString.c_str()+_dateString.size(), "Failed to parse dateTime.");
    return timegm(&timeStruct);
}

【问题讨论】:

  • 您需要哪些格式? (英国、美国、?)
  • 您需要知道您期望的格式。例如。 07-06-2016 是模棱两可的,因为在美国他们做 mm-dd-yyyy,而在欧盟他们做 dd-mm-yyyy。
  • @BiagioFesta 我主要需要yyyy-mm-dd hh:mm:ssyyyymmdddd.mm.yyyy hh:mm,但最好让函数像std::get_time 那样采用任意格式作为参数。
  • @MaximEgorushkin 我确实事先知道它们,我只是希望能够将格式作为附加参数,因为我需要几种格式(请参阅前面的评论)。
  • 如果日期最初是从流中读取的,您可以使用std::ge_time 将其解析为tm

标签: c++ datetime boost c++14


【解决方案1】:

如果您事先知道可能的格式,您可以使用strptime 函数找到成功解析字符串的格式。它返回struct tm,您将其视为分解的UTC,并将其传递给timegm 以获取time_t

【讨论】:

  • 谢谢,我根据你的建议实现了这个功能(见更新),到目前为止它正在工作。
  • @Haatschii 到目前为止接受答案。
【解决方案2】:

这是一个 free, open-source C++11/14 library 和一个 parse 函数,它接受一个 std::basic_istream<CharT, Traits>、一个格式字符串 (std::basic_string<CharT, Traits>) 和一个 std::chrono::time_point<system_clock, seconds>

template <class CharT, class Traits, class Duration>
void
parse(std::basic_istream<CharT, Traits>& is,
      const std::basic_string<CharT, Traits>& format, sys_time<Duration>& tp);

你可以这样使用它:

std::istringstream in{"2014-11-12 19:12:14"};
date::sys_seconds tp;
in >> date::parse("%F %T", tp);

如果退出时未设置failbit,则tp 将是Unix Time,精度为秒。您可以将其转换为 time_t,如下所示:

time_t t = system_clock::to_time_t(tp);

或者你可以直接打印出来:

cout << tp.time_since_epoch().count() << '\n';

如果您确实设置了failbit,您可以使用其他格式字符串重试。

如果您的时间戳具有亚秒级精度,这也将处理。所有输出都将是 UTC,因为这是一个类型安全的库,其中time_point&lt;system_clock, whatever-duration&gt; 表示 UTC(技术上它表示Unix Time)。该库还可以解析当地时间。

如果您的格式不明确,则可能会成功并返回错误的值,从而使您尝试格式的顺序很重要。

【讨论】:

  • 嘿,谢谢。我一定会看看的。不过现在我正在寻求一个更轻量级的解决方案。
猜你喜欢
  • 1970-01-01
  • 2018-07-02
  • 1970-01-01
  • 2016-10-11
  • 2012-10-08
  • 2018-08-07
  • 1970-01-01
  • 2012-04-08
  • 2012-02-28
相关资源
最近更新 更多