Время чтения из строки как GMT в C ++ - PullRequest
0 голосов
/ 04 июля 2019

Я записываю текущее время по Гринвичу в виде строки следующим образом:

  const std::time_t now = std::time(nullptr);
  std::stringstream ss;
  ss << std::put_time(std::gmtime(&now), "%Y-%m-%d %H:%M:%S");

Позже я хочу выполнить обратную операцию, считывая время из строкового потока как GMT и сравнивая его с текущей меткой времени:

std::tm tm = {};
ssTimestamp >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S");
const std::time_t&& time = std::mktime(&tm);
const double timestampDiff((std::difftime(std::time(nullptr), time)));

Чего-то не хватает в приведенном ниже коде, потому что декодированное время никогда не преобразуется в GMT, поэтому я получаю разницу во времени в 1 час из-за моего местного часового пояса

PS: можно использовать только стандартныебиблиотеки, и не может изменить формат строки даты

Ответы [ 2 ]

0 голосов
/ 04 июля 2019

Проект спецификации C ++ 2a (мы надеемся, что 'a' равен '0') имеет удобный способ сделать это:

using namespace std::chrono;
sys_seconds tp;
ssTimestamp >> parse("%Y-%m-%d %H:%M:%S", tp);
std::time_t time = system_clock::to_time_t(tp);

Ни один поставщик еще не реализовал эту часть C ++ 2a, но есть пример реализации здесь, в namespace date.

Нет библиотеки поддержки для выполнения этой операции в C ++ до C ++ 2a.

Лучшее, что вы можете сделать, используя только стандартные стандартные библиотеки, - это проанализировать поля в tm, используя std::get_time (как показывает ваш вопрос), а затем преобразовать эту структуру {y, m, d, h, M, s} в time_t используя вашу собственную математику, и предположение (что обычно верно), что std::time_t равно Unix Time с точностью до секунд.

Вот коллекция календарей общего доступа , чтобы помочь вам в этом. Это , а не сторонняя библиотека. Это поваренная книга для написания вашей собственной библиотеки дат.

Например:

#include <ctime>

std::time_t
to_time_t(std::tm const& tm)
{
    int y = tm.tm_year + 1900;
    unsigned m = tm.tm_mon + 1;
    unsigned d = tm.tm_mday;
    y -= m <= 2;
    const int era = (y >= 0 ? y : y-399) / 400;
    const unsigned yoe = static_cast<unsigned>(y - era * 400);      // [0, 399]
    const unsigned doy = (153*(m + (m > 2 ? -3 : 9)) + 2)/5 + d-1;  // [0, 365]
    const unsigned doe = yoe * 365 + yoe/4 - yoe/100 + doy;         // [0, 146096]
    return (era * 146097 + static_cast<int>(doe) - 719468)*86400 +
           tm.tm_hour*3600 + tm.tm_min*60 + tm.tm_sec;
}

Ссылка выше содержит очень подробное описание этого алгоритма и модульных тестов, чтобы убедиться, что он работает в диапазоне +/- миллионов лет.

Вышеупомянутый to_time_t по сути является переносной версией timegm, которая поставляется на платформах Linux и BSD. Эта функция также называется _mkgmtime в Windows.

0 голосов
/ 04 июля 2019

Структура tm не хранит информацию о часовом поясе, это mktime, которая по умолчанию использует местный часовой пояс.После этой темы лучшим вариантом будет использовать:

#include "time.h" 
timestamp = mktime(&tm) - timezone; //or _timezone

, если timezone или _timezone доступны для вашего компилятора.Комментарий в связанном ответе предупреждает, что он может вызвать проблемы с переходом на летнее время, но это не должно относиться к GMT.

...