Я пытаюсь получить текущий год, хранящийся в дате от 1970 года, используя std::chrono::time_point<std::chrono::system_clock>
, однако я столкнулся с проблемой, связанной с чтением из ее содержимого в структуру std::tm
.localtime_s не удается, когда gmtime_s преуспевает с датами до 1-1-1970
Сначала конвертируйте time_point
в time_t
, после чего я прочитал его значения, чтобы получить значение tm_year
. Однако при попытке сделать это код не работает при использовании localtime_s
, однако он преуспевает, когда я использую gmtime_s
. Это только для дат до 1-1-1970, даты после этого работают отлично, используя обе функции.
Приведенный ниже код воспроизводит ошибку. Если terstGmTimeVsLocalTime
вызывается с utc=true
, он работает, если он вызывается с utc=false
, он не производит правильный вывод.
#include <iomanip>
#include <time.h>
#include <iostream>
void testGmTimeVsLocaltime(const bool& utc) {
// Create time
std::tm timeInfoWrite = std::tm();
timeInfoWrite.tm_year = 1969 - 1900; // Year to parse, here it is 1969
timeInfoWrite.tm_mon = 0;
timeInfoWrite.tm_mday = 1;
timeInfoWrite.tm_hour = 1;
timeInfoWrite.tm_min = 0;
timeInfoWrite.tm_sec = 0;
timeInfoWrite.tm_isdst = -1;
std::chrono::time_point<std::chrono::system_clock> timePoint = std::chrono::system_clock::from_time_t(utc ? _mkgmtime(&timeInfoWrite) : std::mktime(&timeInfoWrite));
// Convert to time_t
std::time_t timeT = std::chrono::system_clock::to_time_t(timePoint);
// Read values
std::tm timeInfoRead;
if (utc) {
gmtime_s(&timeInfoRead, &timeT);
} else {
localtime_s(&timeInfoRead, &timeT);
}
// Output result
std::cout << (timeInfoRead.tm_year + 1900) << '\n';
// Wait for input
std::getchar();
}
int main() {
testGmTimeVsLocaltime(true); // Set to false to show bug
return 0;
}
utc=true
выходов 1969, как и следовало ожидать. Однако utc=false
выдает 1899 (предположительно, так как возникает ошибка, а tm_year
устанавливается в -1).
Есть ли что-нибудь, что мне не хватает? The documentation конкретно не указывает, что localtime_s
должен завершиться с даты до 1-1-1970.
Я нахожусь в Windows 10 x64, если это имеет значение.
Документы MSDN предполагают, что это не удастся: «До полуночи, 1 января 1970 года». См. Https://msdn.microsoft.com/en-us/library/bf12f0hc.aspx –
@RichardCritten Ах, я вижу, я, должно быть, использовал конкретную реализацию ОС. Не понял, что «localtime_s» не входит в стандарт. Будет ли еще одна функция, которая не подведет значения до полуночи, 1 января 1970 года? Или, может быть, другая стратегия? Я предполагаю, что могу получить разницу между UTC и localtime, просто используйте функцию 'gmtime_s', а затем добавьте разницу в результат, когда требуется локальное время, однако похоже, что это можно сделать проще. – Qub1
Документы, которые вы связываете, говорят _ «Преобразует заданное время с __epoch __» _; где эпоха - это когда реализация определяет время начала.В Windows есть вызовы ОС, которые будут работать в любое время, но я не знаю ни одного стандартного API. –