Рассмотрим историческую строку даты в формате:
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);
}
Эта библиотека Можно разбор %z
, А также date::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
к дней точности 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 и не такое элегантное решение, как ответ Simple, но я думаю, что оно может сработать. Этот ответ, вероятно, неправильный, но я оставлю его, чтобы кто-то мог опубликовать исправления.
#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;
}