簡體   English   中英

std :: string中的std :: chrono :: time_point

[英]std::chrono::time_point from std::string

我試圖將日期(以std::string形式)轉換為std::chrono::time_point 為此,我使用加速日期時間。 在下面,您可以找到一個最小的工作示例。 但是,我不明白為什么我認為無效的某些輸入字符串似乎不會以任何方式引發異常。 我不知道這是怎么回事。

#include <iostream>
#include <chrono>
#include <sstream>
#include <boost/date_time.hpp>

using Clock = std::chrono::system_clock;
using TimePoint = std::chrono::time_point<Clock>;

TimePoint timePointFromString(const std::string& date, const std::string& format) {
  // local takes care of destructing time_input_facet
  auto loc = std::locale(std::locale::classic(), new boost::posix_time::time_input_facet(format));

  std::stringstream ss{date};
  ss.imbue(loc);

  boost::posix_time::ptime pt;
  ss >> pt;

  if (!ss.good()) {
    throw std::runtime_error("Cannot parse string");
  }

  boost::posix_time::ptime time_t_epoch{boost::gregorian::date(1970, 1, 1)};
  boost::posix_time::time_duration diff = pt - time_t_epoch;

  Clock::duration duration{diff.total_nanoseconds()};

  return TimePoint{duration};
}

int main() {
  std::string format{"%Y-%m-%d"};

  std::vector<std::string> strings {"2018", "2018-", "19700101", "19700103", "19700301"};
  for (const auto& s: strings) {
    auto tp = timePointFromString(s, format);
    std::cout << s << ": " << TimePoint::clock::to_time_t(tp) << std::endl;
  }
}

輸出:

2018: 1514764800
2018-: 1514764800
19700101: 23587200
19700103: 23587200
terminate called after throwing an instance of 'std::runtime_error'
  what():  Cannot parse string

更新:我以為它將執行某種模式匹配,從而誤解了這段代碼。 事實並非如此(請參見ÖöTiib的回答和其回答下方的評論)! 顯然,最好使用Howard Hinnant的日期/時間庫。

如果您使用Howard Hinnant的免費開放源日期/時間庫,則代碼如下所示:

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

std::chrono::system_clock::time_point
timePointFromString(const std::string& date, const std::string& format)
{
    std::stringstream ss{date};
    std::chrono::system_clock::time_point pt;
    ss >> date::parse(format, pt);
    if (ss.fail())
        throw std::runtime_error("Cannot parse date");
    return pt;
}

int
main()
{
    std::string format{"%Y-%m-%d"};
    std::vector<std::string> strings{"2018", "2018-", "19700101", "19700103", "19700301",
                                     "1970-03-01"};
    for (const auto& s: strings)
    {
        try
        {
            auto tp = timePointFromString(s, format);
            using date::operator<<;
            std::cout << s << ": " << tp << '\n';
        }
        catch (std::exception const& e)
        {
            std::cout << s << ": " << e.what() << '\n';
        }
    }
}

輸出將是:

2018: Cannot parse date
2018-: Cannot parse date
19700101: Cannot parse date
19700103: Cannot parse date
19700301: Cannot parse date
1970-03-01: 1970-03-01 00:00:00.000000

我在向量的末尾添加了有效的字符串/日期,以顯示使用此format接受的內容。 1970-03-01 00:00:00.0...上的尾隨零的數量將根據平台的std::chrono::system_clock::time_point的精度而變化。

同樣,此代碼應輕松移植到C ++ 20:

  • 刪除#include "date/date.h"
  • using date::operator<<;刪除
  • date::parse更改為std::chrono::parse

更新

為了幫助您解釋結果:

  • 1970-01-01 00:00:00之后的1514764800s是2018-01-01 00:00:00
  • 1970-01-01 00:00:00之后的23587200s是1970-10-01 00:00:00

(所有忽略leap秒,這是正常現象)

您沒有解釋您的期望以及原因,因此我僅描述您的程序的作用。

對於“ 19700101”和“ 19700103”,它解析“ 1970”跳過一個字符,解析“ 10”跳過一個字符並找到字符串的末尾,因此得出結論,兩者都是1970年10月1日。

對於“ 19700301”,它分析“ 1970”會跳過字符分析“ 30”,並且由於第30個月是胡說八道而拋出。

另外,您的輸出描述有錯字,您將拋出“無法解析日期”而不是“無法解析字符串”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM