날짜 문자열을 C++11 std::chrono time_point 또는 이와 유사한 것으로 구문 분석하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com//questions/21021388

문제

다음과 같은 형식의 과거 날짜 문자열을 고려하세요.

Thu Jan 9 12:35:34 2014

이러한 문자열을 일종의 C++ 날짜 표현으로 구문 분석한 다음 그 이후로 경과된 시간을 계산하고 싶습니다.

결과 기간에서 초, 분, 시간 및 일 수에 액세스해야 합니다.

새로운 C++11로 이 작업을 수행할 수 있습니까? std::chrono 네임스페이스?그렇지 않다면 오늘 이 문제를 어떻게 해결해야 합니까?

나는 g++-4.8.1을 사용하고 있지만 아마도 대답은 C++11 사양을 대상으로 해야 할 것입니다.

도움이 되었습니까?

해결책

std::tm tm = {};
std::stringstream ss("Jan 9 2014 12:35:34");
ss >> std::get_time(&tm, "%b %d %Y %H:%M:%S");
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
.

버전 5 이전의 GCC는 std::get_time를 구현하지 않습니다.또한 쓸 수 있어야합니다 :

std::tm tm = {};
strptime("Thu Jan 9 2014 12:35:34", "%a %b %d %Y %H:%M:%S", &tm);
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
.

다른 팁

이전 질문에 대한 새로운 답변입니다.새로운 답변의 근거:당시 도구로는 요청된 내용을 정확하게 처리할 수 없었기 때문에 질문은 원래 형식에서 편집되었습니다.그리고 결과적으로 허용된 답변은 원래 질문에서 요청한 것과 미묘하게 다른 동작을 제공합니다.

나는 받아 들인 대답을 내려 놓으려고하지 않습니다.좋은 답변입니다.C API는 단지 그래서 이런 실수가 일어날 수밖에 없다는 사실이 혼란스럽습니다.

원래 질문은 구문 분석이었습니다. "Thu, 9 Jan 2014 12:35:34 +0000".분명히 의도는 UTC 시간을 나타내는 타임스탬프를 구문 분석하는 것이었습니다.하지만 strptime (표준 C 또는 C++는 아니지만 POSIX임) UTC 타임스탬프임을 나타내는 후행 UTC 오프셋을 구문 분석하지 않습니다. %z, 그러나 구문 분석하지는 않음).

그런 다음 질문을 편집하여 질문했습니다. "Thu Jan 9 12:35:34 2014".하지만 질문은 ~ 아니다 이것이 UTC 타임스탬프인지 아니면 컴퓨터의 현재 타임스탬프인지 명확히 하기 위해 편집되었습니다. 현지의 시간대.허용된 답변 암묵적으로 타임스탬프는 다음을 사용하기 때문에 컴퓨터의 현재 현지 시간대를 나타낸다고 가정합니다. std::mktime.

std::mktime 필드 유형을 변환할 뿐만 아니라 tm 직렬형으로 time_t, 컴퓨터의 현지 시간대에서 UTC로 오프셋 조정도 수행합니다.

하지만 원래(편집되지 않은) 질문에 따라 UTC 타임스탬프를 구문 분석하려면 어떻게 해야 할까요?

오늘은 이 새로운 기능을 사용하여 이 작업을 수행할 수 있습니다. 무료 오픈 소스 라이브러리.

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

int
main()
{
    using namespace std;
    using namespace date;
    istringstream in{"Thu, 9 Jan 2014 12:35:34 +0000"};
    sys_seconds tp;
    in >> parse("%a, %d %b %Y %T %z", tp);
}

이 도서관 ~할 수 있다 분석하다 %z.그리고 date::sys_seconds 다음의 형식 정의일 뿐입니다.

std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>

질문은 또한 다음과 같이 묻습니다.

결과 기간에서 초, 분, 시간 및 일 수에 액세스해야 합니다.

그 부분은 답이 없는 상태로 남아있습니다.수행 방법은 다음과 같습니다. 이 도서관.이 부분에서는 두 번째도 사용하겠습니다. 헤더 전용 라이브러리 "chrono_io.h":

#include "chrono_io.h"
#include "date.h"
#include <iostream>
#include <sstream>

int
main()
{
    using namespace std;
    using namespace date;
    istringstream in{"Thu, 9 Jan 2014 12:35:34 +0000"};
    sys_seconds tp;
    in >> parse("%a, %d %b %Y %T %z", tp);
    auto tp_days = floor<days>(tp);
    auto hms = make_time(tp - tp_days);
    std::cout << "Number of days    = " << tp_days.time_since_epoch() << '\n';
    std::cout << "Number of hours   = " << hms.hours() << '\n';
    std::cout << "Number of minutes = " << hms.minutes() << '\n';
    std::cout << "Number of seconds = " << hms.seconds() << '\n';
}

floor<days> 초 정밀도를 자릅니다. time_point일 정밀도 time_point.일 정밀도를 빼면 time_point ~에서 tp, 당신은 duration 이는 자정(UTC) 이후의 시간을 나타냅니다.

공장 기능 make_time 무엇이든 받아들인다 duration (이 경우 자정 이후 시간)을 생성하고 {hours, minutes, seconds} 각 필드에 대한 게터가 있는 필드 유형입니다.기간의 정밀도가 초보다 작은 경우 이 필드 유형에는 하위 초에 대한 getter도 포함됩니다.

마지막으로, "chrono_io.h", 이 기간을 모두 인쇄할 수 있습니다.이 예제는 다음을 출력합니다.

Number of days    = 16079[86400]s
Number of hours   = 12h
Number of minutes = 35min
Number of seconds = 34s

그만큼 [86400]s 의 단위를 나타냅니다. duration 그것은 일 정밀도를 가지고 있습니다.따라서 2014-01-09는 1970-01-01로부터 16079일 후입니다.

이것은 단순한 대답으로 솔루션의 우아하지는 않지만, 나는 그것이 일할 수 있다고 생각합니다.이 대답은 잘못되었지만 누군가가 수정을 거부 할 수 있도록 그것을 떠날 것입니다.

#include <iostream>
#include <ctime>

int main ()
{
  struct tm timeinfo;
  std::string buffer = "Thu, 9 Jan 2014 12:35:00";

  if (!strptime(buffer.c_str(), "%a, %d %b %Y %T", &timeinfo))
    std::cout << "Error.";

  time_t now;
  struct tm timeinfo2;
  time(&now);
  timeinfo2 = *gmtime(&now);

  time_t seconds = difftime(mktime(&timeinfo2), mktime(&timeinfo));
  time(&seconds);
  struct tm result;
  result = *gmtime ( &seconds );
  std::cout << result.tm_sec << " " << result.tm_min << " "
            << result.tm_hour << " " << result.tm_mday;
  return 0;
}
.

사례 (코드가 아래) :

  • 지금까지 지금까지

    long int min0 = getMinutesSince( "2005-02-19 12:35:00" );

  • 지금까지 에포크 이후

    long int min1 = getMinutesSince1970( );

  • 두 날짜 + 시간 (주어진 날짜까지 EPOCH 이후)

    long int min0 = getMinutesSince1970Until( "2019-01-18 14:23:00" );

    long int min1 = getMinutesSince1970Until( "2019-01-18 14:27:00" );

    cout << min1 - min0 << endl;

코드 완료 :

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

using namespace std;

// ------------------------------------------------
// ------------------------------------------------
long int getMinutesSince1970Until( string dateAndHour ) {

  tm tm = {};
  stringstream ss( dateAndHour );
  ss >> get_time(&tm, "%Y-%m-%d  %H:%M:%S");

  chrono::system_clock::time_point tp = chrono::system_clock::from_time_t(mktime(&tm));


  return
    chrono::duration_cast<chrono::minutes>(
                                           tp.time_since_epoch()).count();

} // ()
// ------------------------------------------------
// ------------------------------------------------
long int getMinutesSince1970() {
  chrono::system_clock::time_point now = chrono::system_clock::now();

  return
    chrono::duration_cast<chrono::minutes>( now.time_since_epoch() ).count();
} // ()

// ------------------------------------------------
// ------------------------------------------------
long int getMinutesSince( string dateAndHour ) {

  tm tm = {};
  stringstream ss( dateAndHour );
  ss >> get_time(&tm, "%Y-%m-%d  %H:%M:%S");

  chrono::system_clock::time_point then =
    chrono::system_clock::from_time_t(mktime(&tm));

  chrono::system_clock::time_point now = chrono::system_clock::now();

  return
    chrono::duration_cast<chrono::minutes>(
                                           now.time_since_epoch()-
                                           then.time_since_epoch()
                                           ).count();
} // ()


// ------------------------------------------------
// ------------------------------------------------
int main () {

  long int min = getMinutesSince1970Until( "1970-01-01 01:01:00" );

  cout << min << endl;


  long int min0 = getMinutesSince1970Until( "2019-01-18 14:23:00" );
  long int min1 = getMinutesSince1970Until( "2019-01-18 14:27:00" );

  if ( (min1 - min0) != 4 ) {
    cout << " something is wrong " << endl;
  } else {
    cout << " it appears to work !" << endl;
  }

  min0 = getMinutesSince( "1970-01-01 01:00:00" );
  min1 = getMinutesSince1970( );

  if ( (min1 - min0) != 0 ) {
    cout << " something is wrong " << endl;
  } else {
    cout << " it appears to work !" << endl;
  }

} // ()
.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top