2012-08-25 2 views
9

Ich führe den folgenden Code aus.Verwirrendes Verhalten der Funktion mktime(): tm_hour count um eins erhöhen

int main() 
{ 
struct tm storage={0,0,0,0,0,0,0,0,0}; 
char *p = NULL; 
p = (char *)strptime("2012-08-25 12:23:12","%Y-%m-%d %H:%M:%S",&storage); 
char buff[1024]={0}; 
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage); 
cout << buff << endl; 
storage.tm_sec += 20; 
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage); 
cout << buff << endl; 
mktime(&storage); 
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage); 
cout << buff << endl; 
return 0; 
} 

Wenn oben Programm ausgeführt wird, druckt er '2012-08-25 13.23.32' anstelle von '2012-08-25 00.23.32'. Bitte helfen Sie, warum es tm_hour Wert erhöht. Dies funktioniert korrekt, wenn ich Eingabedatum als '2012-02-25 12:23:32' in Programm, was verwirrend ist.

Ausgabe ->

[[email protected] root]$ ./a.out 
2012-08-25 12:23:12 
2012-08-25 12:23:32 
2012-08-25 13:23:32 
[[email protected] root]$ 

Datum Info auf meinem System ->

[[email protected] root]$ date 
Sat Aug 25 08:28:26 EDT 2012 
+0

Der Code zeigt nicht, dass die Stunde zunimmt.Zeigen Sie dazu das Ergebnis von 'strptime' sowie das Ergebnis des Aufrufs von' mktime' an. Das wird helfen herauszufinden, was tatsächlich passiert. –

+0

Sorry, ich kann das nicht analysieren. Es hat drei Ausgänge anstelle von einem, aber keinen Hinweis darauf, woher sie kommen. Bitte aktualisieren Sie den Beispielcode, damit er der Ausgabe entspricht. –

Antwort

11

Was

geschieht

Das Datum, das Sie Sommer wirksam angegeben hat, aber wenn mktime Aufruf storage.tm_isdst Null ist. mktime sieht dies und denkt "Hey, sie gaben mir ein Datum mit einer falschen Sommerflagge, lass es reparieren". Dann setzt es tm_isdst auf 1 und ändert tm_hour.

Siehe auch this antwort.

es

  • Gebrauch zu beheben timegm statt mktime
  • stellen Sie die Zeitzone UTC vor mktime (siehe auch Beispiel von timegm) Aufruf:
    setenv("TZ", "", 1); 
    tzset(); 
    mktime();
  • eine gute Datum- verwenden Zeitbibliothek (wie boost::locale::date_time/boost::date_time, lesen Sie aber den Abschnitt Q & A auf der boost::locale::date_time Seite vor der Auswahl eines)
+1

Danke, es half mir und erklärte mir meine Zweifel. Jetzt muss ich meinen Code auf beiden Systemen ausführen (Sommerzeit ein und aus). z.B. Wenn ich tm_isdst = 1 in code vor dem Aufruf von mktime() setze, gibt es ein falsches Ergebnis auf dem System, auf dem DST deaktiviert ist (es wird am Ende tm_hour um eins verringern). Gibt es eine andere Möglichkeit, einem bestimmten Datum Sekunden hinzuzufügen? (Es kann sein "Vermeiden Sie die Verwendung von mktime()" oder "Machen Sie eine intelligente Verwendung von mktime(), die tm_isdst Flag ignorieren") –

+0

@DhirajNeve: Ich habe ein paar Fixes hinzugefügt. Wenn Sie mehr Datum/Zeit verwandte Dinge tun müssen, sollten Sie eine gute C++ Datum/Zeit-Bibliothek verwenden. – rve

+0

Ist POSIX nicht nur "timegm"? – stackptr

4

Wow, es gibt einfach keinen Weg drum herum. Es muss ein Fehler in der Systemimplementierung von mktime (3) sein. mktime (3) sollte die übergebene struct tm * nicht ändern.

Ich würde vorschlagen, den Wert von storage.tm_isdst zu überprüfen. Versuchen Sie, es auf 0 zu setzen, um sicherzustellen, dass es nicht mit der Sommerzeit verwechselt wird. Wenn das nicht funktioniert, versuchen Sie es auf -1 zu setzen, damit es automatisch den richtigen Wert ermittelt.

mktime - convert broken-down time into time since the Epoch

A positiv oder 0-Wert für tm_isdst verursacht Mktime() zunächst, dass die Sommerzeit bzw. anzunehmen, ist oder in der Tat für die angegebene Zeit nicht. Ein negativer Wert für tm_isdst veranlasst mktime() zu versuchen, zu bestimmen, ob die Sommerzeit für die angegebene Zeit gilt.


Ich war falsch über mktime (3) nicht struct tm * ändern. Es ist das richtige Verhalten, um den Wert zu normalisieren.

+0

Laut 'man mktime' (http://linux.die.net/man/3/mktime) kann es' stuct tm' ändern (und tut es). Es normalisiert seine Werte und füllt fehlende Felder aus. – rve

+0

@rve es sieht aus wie du bist richtig. Ich wurde die Formulierung missverstanden. Ich dachte, dass es sich für den Zweck, der time_t setzt, normalisierte. –

+0

Ja, die Implementierung ist falsch ... –

Verwandte Themen