J'essaie d'obtenir l'année en cours stockée dans une date d'avant 1970 en utilisant un std::chrono::time_point<std::chrono::system_clock>
, mais j'ai rencontré un problème concernant la lecture de son contenu dans une struct std::tm
.localtime_s échoue où gmtime_s réussit avec des dates avant le 1-1-1970
Je convertis le time_point
en un time_t
d'abord, après quoi j'ai lu ses valeurs pour obtenir la valeur tm_year
. Toutefois, lorsque vous essayez de le faire, le code échoue lors de l'utilisation localtime_s
, mais il réussit lorsque j'utilise gmtime_s
. C'est seulement pour les dates avant le 1-1-1970, les dates après cela fonctionnent bien en utilisant les deux fonctions.
Le code ci-dessous reproduit l'erreur. Si terstGmTimeVsLocalTime
est appelé avec utc=true
cela fonctionne, s'il est appelé avec utc=false
il ne produit pas la bonne sortie.
#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
sorties 1969, comme on pouvait s'y attendre. Cependant, utc=false
sort 1899 (probablement parce qu'une erreur se produit et que tm_year
est mis à -1).
Y at-il quelque chose qui me manque? The documentation ne spécifie pas spécifiquement que localtime_s
doit échouer pour les dates antérieures à 1-1-1970.
Je suis sur Windows 10 x64 si cela fait une différence.
Les documents MSDN suggèrent qu'il échouera: "Avant minuit, 1er janvier 1970." Voir https://msdn.microsoft.com/en-us/library/bf12f0hc.aspx –
@RichardCritten Ah, je vois que j'ai dû utiliser une implémentation spécifique au système d'exploitation. Je n'ai pas réalisé 'localtime_s' ne faisait pas partie de la norme. Y aurait-il une autre fonction qui ne manquerait pas pour les valeurs avant minuit, le 1er janvier 1970? Ou peut-être une autre stratégie? Je suppose que je pourrais récupérer la différence entre UTC et localtime, utilisez simplement la fonction 'gmtime_s', puis ajoutez la différence au résultat lorsque l'heure locale est requise, mais il semble que cela pourrait être fait plus simplement. – Qub1
Les documents que vous liez indiquent _ "Convertit le temps donné depuis __epoch __" _; où est l'époque où la mise en œuvre décide que le temps commence.Sous Windows, il y a des appels OS qui fonctionneront n'importe quand, mais je ne connais pas d'API standard. –