frage zu zeitfunktionen aus time.h
-
Hallo,
ich bräuchte eine Funktion, der ich ein struct tm übergeben kann, die mir dann die Sekunden seit 1970 in UTC bis zu dem übergebenen Zeitpunkt zurückgibt.
Wenn ich ein struct tm "manuell" beschreibe und dieses dann der Funktion mktime() aus time.h übergebe, besteht das Problem, dass diese Funktion vor der Umrechnung noch die Differenz von meiner Local Time zur UTC abzieht.
Beispiel:
Ich übergebe mktime ein struct tm mit dem datum '10.02.2005 15:53:22'. mktime() "erkennt", dass wir hier 60 Minuten Zeitverschiebung zur UTC haben und berechnet die Sekunden von 1970 bis '10.02.2005 14:53:22'.Ich könnte das umgehen, indem ich meinem struct vor dem Funktionsaufruf eine Stunde hinzu addiere, das gibt aber schon wieder ein Problem, weil bei Sommerzeit 2 Stunden subtrahiert werden. Oder das Ergebnis stimmt nicht, wenn das Programm in einer anderen Zeitzone eingesetzt wird. Ich brauch was universelles. Hat jemand eine Lösung parat? Da das ganze Plattform unabhängig sein soll, kann ich auch nicht solche Windows spezifischen Dinge wie getTimeZoneInformation() verwenden.
Wäre dankbar für Hilfe,
Grüße,
cuomo
-
Hallo Cuomo,
wenn ich Dich richtig verstanden habe, dann bist Du einem Irrtum aufgesessen. Die Funktion mktime() liefert immer(!) einen time_t mit den Sekunden seit dem 01.01.1970 00:00:00 Uhr UTC (Epoch) zurück. Die Funktion localtime macht dann aus dem time_t wieder eine lokale Zeit.
Falls Du vor einer Linux-Kiste hockst, kannst Du ja mal folgendes probieren:
int main(int argc, char *argv[]) { tm tmNow = { 0 }; tmNow.tm_mday = 11; // Freitag, der 11. tmNow.tm_mon = 1; // Februar tmNow.tm_year = 2005 - 1900; // 2005 tmNow.tm_hour = 12; // High-Noon in MEZ time_t myTime = mktime( &tmNow ); // Sekunden seit 01.01.1970 00:00:00 Uhr UTC std::cout << myTime << endl; std::cout << ctime( &myTime ); return EXIT_SUCCESS; }
Das wird Dir folgende Ausgabe zurückliefern:
1108119600 Fri Feb 11 12:00:00 2005
Alles in Ordnung soweit.
An der Konsole läßt Du Dir nun mal mit den oben ausgegebenen Sekunden mal mit "date" das Datum in UTC und lokaler Zeit zurückliefern.
In UTC kommt da raus:
date --date="1970-01-01 00:00:00 UTC +1108119600 sec" -u Konsolenausgabe: Fr Feb 11 11:00:00 UTC 2005
In lokaler Zeit;
date --date="1970-01-01 00:00:00 UTC +1108119600 sec" -R Konsolenausgabe: Fri, 11 Feb 2005 12:00:00 +0100
Wenn Du magst, kannst Du mal ein paar Source-Schnipsel posten. Vielleicht kann ich Dir vielleicht ein wenig konkreter helfen.
Gruß
H.-Gerd
-
Hallo H.-Gerd,
ich hab zwar mittlerweile eine Lösung für mein Problem gefunden (deswegen antworte ich so spät), bin aber trotzdem an einer besseren Lösung interessiert.
Es ist richtig, was du schreibst. mktime() liefert immer die Sekunden seit 01.01.1970 UTC zurück. Die Frage ist nur bis zu welchem Zeitpunkt. Wenn ich die momentane Zeit in einem struct tm übergebe, bekomme ich natürlich die Sekunden von 1970 bis jetzt zurück.
Ich bin jedoch in folgender Situation:Aus einem Log-File lese ich einen Zeitstempel aus, der irgendwann mal in UTC dort reingeschrieben wurde. Jetzt brauche ich die Anzahl der Sekunden seit 1970 bis zu diesem Zeitpunkt. Lese ich den Zeitstempel in ein struct tm ein und übergebe dieses an mktime(), sieht diese Funktion die Zeit als Localtime an und korrigiert sie intern nochmals auf UTC. Der Zeitstempel ist aber nicht Localtime, da er, wie beschrieben, bereits als UTC ins LogFile geschrieben wurde. Also muss ich vor dem Aufruf von mktime() die Differenz zwischen meiner Zeitzone und der UTC noch hinzu addieren, damit sie nach der internen Korrektur wieder beim ursprünglichen Zeitstempel ist.
Alles ein bisschen schwer zu beschreiben, aber ich hoffe du verstehst das Problem. Dieses ist übrigens auch in der MSDN beschrieben, wie ich im nachhinein bemerkt habe.
After an adjustment to Greenwich Mean Time (GMT), mktime handles dates from midnight, January 1, 1970, to January 19, 3:14:07, 2038. This adjustment may cause mktime to return -1 (cast to time_t) even though the date you specify is within range. For example, if you are in Cairo, Egypt, which is two hours ahead of GMT, two hours will first be subtracted from the date you specify in timeptr; this may now put your date out of range.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_mktime.asp
meine Lösung sieht nun folgendermaßen aus:
time_t curtime; time(&curtime); struct tm ltime = *localtime(&curtime); struct tm gtime = *gmtime(&curtime); time_t diff = mktime(<ime) - mktime(>ime); struct tm dateTime; // date in UTC dateTime.tm_year = atoi(timeString.substr(0, 4).c_str()) - 1900; dateTime.tm_mon = atoi(timeString.substr(4, 2).c_str()) - 1; dateTime.tm_mday = atoi(timeString.substr(6, 2).c_str()); dateTime.tm_hour = atoi(timeString.substr(9, 2).c_str()); dateTime.tm_min = atoi(timeString.substr(11, 2).c_str()); dateTime.tm_sec = atoi(timeString.substr(13, 2).c_str()) + diff; dateTime.tm_isdst = -1; uint64_t usec = _mktime64(&dateTime);
Vielleicht hilft das ja anderen, die irgendwann mal das gleiche Problem haben, mich hats ganz schön lange aufgehalten...
Schöne Grüße,
cuomo
-
timeString ist natürlich der Zeitstempel, den ich in seine Einzelteile zerlege. Hab ich vergessen anzupassen
grüße