4

如何在 C++03 中解析RFC3339时间戳(“1985-04-12T23:20:50.52Z”)(即 ISO8601 的子集)?我正在使用 Boost,但 Boost 日期时间库似乎都没有包含执行此操作的函数。

实际时间对象的类型无关紧要,只要我可以轻松地将其与“现在”进行比较即可。我只关心 UTC 时区的时间戳。

4

2 回答 2

1

不使用 Boost,就strptime可以。

假设在此处发布相同的 _adaptive_parser_ 帮助器:使用 boost 解析日期时间字符串:使用单个数字小时格式

注意:样本取自 RFC 链接

#include "adaptive_parser.h"
#include <string>
#include <iostream>

int main() {    
    using namespace mylib::datetime;

    adaptive_parser parser;

    for (std::string const input : {
            "1985-04-12T23:20:50.52Z",
            "1996-12-19T16:39:57-08:00",
            "1990-12-31T23:59:60Z",
            "1990-12-31T15:59:60-08:00",
            "1937-01-01T12:00:27.87+00:20",
        })
    try {
        std::cout << "Parsing '" << input << "'\n";
        std::cout << " -> epoch " << parser(input).count() << "\n";
    } catch(std::exception const& e) {
        std::cout << "Exception: " << e.what() << "\n";
    }
}

印刷

Parsing '1985-04-12T23:20:50.52Z'
 -> epoch 482196050
Parsing '1996-12-19T16:39:57-08:00'
 -> epoch 851042397
Parsing '1990-12-31T23:59:60Z'
 -> epoch 662688000
Parsing '1990-12-31T15:59:60-08:00'
 -> epoch 662688000
Parsing '1937-01-01T12:00:27.87+00:20'
 -> epoch -1041335973

当然,您可以限制所需子集的接受模式的数量。

于 2017-06-30T09:58:49.923 回答
0

有解析时区的限制。

#include <sstream>
#include <iostream>
#include <string>
#include <iomanip>

int main() {
  std::tm t = {};
  std::string s = "2016-01-02T15:04:05+09:00";
  int tz_offset = 0;
  auto pos = s.find_last_of("+-Z");
  if (pos != s.npos) {
    std::string zone = s.substr(pos);
    tz_offset = std::atoi(zone.c_str());
    s.resize(pos);
  }
  std::stringstream ss(s);
  ss >> std::get_time(&t, "%Y-%m-%dT%H:%M:%S");
  if (ss.fail()) {
    std::cout << "Parse failed\n";
  } else {
    std::time_t l = std::mktime(&t);
    std::tm tm_utc(*std::gmtime(&l));
    std::time_t utc = std::mktime(&tm_utc);
    tz_offset += (utc - l);
    l = std::mktime(&t) - tz_offset;
    t = *std::gmtime(&l);
    std::cout << std::put_time(&t, "%c") << std::endl;
  }
}
于 2017-06-30T10:15:11.440 回答