Как разобрать строку даты в 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));
.

GCC до версии 5 не реализует 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);
}

Эта библиотека может анализировать %zdate::sys_seconds это просто typedef для:

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 к a дни-точность time_point.Если вычесть дни-точность time_point От tp, вы остаетесь с duration это соответствует времени, прошедшему с полуночи (UTC).

Заводская функция make_time принимает любые duration (в данном случае время с полуночи) и создает {hours, minutes, seconds} введите поле с геттерами для каждого поля.Если длительность имеет точность меньше секунд, этот тип поля также будет иметь геттер для подсекунд.

Наконец, используя "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 - это 16079 дней после 1970-01-01.

Это скорее C-ISH, а не так элегантное решение как простое ответа, но я думаю, что это может работать. Этот ответ, вероятно, неверный, но я оставлю это, чтобы кто-то могло публиковать исправления.

#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( );

  • между двумя дата + часы (поскольку эпоха до данной даты)

    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