UTC (ISO 8601) in lokale Zeitzone konvertieren
-
Hallo,
ich bin mal wieder zu blöd und sehe bei google scheinbar den Wald vor lauter Bäumen nicht:
Ich bekomme einen ISO8601-Timestring mit UTC-Zeit (z.B. 2008-08-02T21:57:08.000Z). Diesen möchte ich als 'lokale Zeit' ausgeben also z.B. 02.08.2008 21:57:08.
Die Konvertierung bekomme ich nicht hin. Ich versuche das Ganze ohne .NET oder ähnliches.
Hat jmd einen Tip / eine Lösung?
THX
-
Du musst diesen String erstmal in einen richtigen Unix-Timestamp parsen.
Mit diesem kannst du dann ganz leicht weiterarbeiten und beispielsweise mit
den Funktionen localtime und strftime das ganze wieder als lokale Zeit ausgeben.
-
Kannst Du auch noch einen Parser o.ä. empfehlen oder einfach Jahre-1970, Monate etc. in Sekunden umrechnen? Letzteres müßte ja eigentlich gehen, wenn ich immer UTC bekomme.
Für meinen Layout-Fall ist dann ja wohl 'strftime' auch die bessere Variante.
-
Ich hab dir mal schnell ein Beispiel geschrieben wie's ich ungefähr machen würde:
#include <iostream> #include <string> #include <ctime> using namespace std; time_t strToTime(string str) { struct tm timeinfo; timeinfo.tm_year = atoi(str.substr(0, 4).c_str()) - 1900; timeinfo.tm_mon = atoi(str.substr(5, 2).c_str()) - 1; timeinfo.tm_mday = atoi(str.substr(8, 2).c_str()); timeinfo.tm_hour = atoi(str.substr(11, 2).c_str()); timeinfo.tm_min = atoi(str.substr(14, 2).c_str()); timeinfo.tm_sec = atoi(str.substr(17, 2).c_str()); return mktime(&timeinfo); } int main () { time_t time = strToTime("2008-08-02T21:57:08.000Z"); struct tm *timeinfo = localtime(&time); char buffer[80]; strftime(buffer, 80, "%c", timeinfo); cout << buffer << endl; return 0; }
-
Wow! Sehr genial. In die Richtung hatte ich auch gedacht und ich verstehe den Code sogar!!
Und ich weiß definitiv, dass ich die -1 beim Monat auch vergessen hätte. Allerdings frage ich mich jetzt, was mit dem Tag ist, da sollte man doch auch einen abziehen, oder nicht? Einen 0. gibt's doch auch da nicht.
-
Nee beim Tag, also tm_mday, musst du nichts abziehen.
Das liegt daran dass tm_mday die Werte 1-31 haben kann, was ja auch praktisch schon passt.
Beim Monat, tm_mon, ist es jedoch so, dass dieser Wert 0-11 sein kann, wobei 0 eben der Januar ist und 11 der Dezember.
Und vom Jahr tm_year muss man prinzipiell immer die 1900 subtrahieren.Nachlesen kannst du das ganze auch nochmal in der MSDN.

-
Ja, ich hatte da wohl auch einen Denkfehler drin.
Aber spätestens mit dem Blick in die Doku ist das jetzt klar.Dank Dir!
-
Hmm, schade:
Ich bekomme am Ende wieder GMT raus. Muss man vorm 'localtime' noch etwas machen, damit wirklich die Zeitzonen bedacht werden?
Habe 2 Stunden Abweichung (+1 Deutschland und +1 Sommerzeit).
-
-
Versuchs mal mit der Funktion gmtime anstelle von localtime,
da ja alles andere auch irgendwie rückwärts gemacht werden musste.
-
...oder erst mal lesen, ich war gestern nicht wirklich bei der Sache:
- MSDN:
localtime corrects for the local time zone if the user first sets the global environment variable TZ. When TZ is set, three other environment variables (_timezone, _daylight, and _tzname) are automatically set as well. If the TZ variable is not set, localtime attempts to use the time zone information specified in the Date/Time application in Control Panel. If this information cannot be obtained, PST8PDT, which signifies the Pacific time zone, is used by default. See _tzset for a description of these variables. TZ is a Microsoft extension and not part of the ANSI standard definition of localtime.
...Oh Mist, Umgebungsvariable hört sich nicht praktikabel an.
- @lächeln: Weiß noch nicht ganz, was Du mir sagen willst, aber das finde ich schon noch heraus
- kann das im Moment leider nicht testen, werde das aber heute nachmittag (hoffentlich wacher) machen.
-
Boost's Date/Time hat sowas iirc eingebaut, ist sicherer/einfacher als selber schreiben:
http://www.boost.org/doc/libs/1_35_0/doc/html/date_time.html
solltest du mit "ohne .NET oder sowas" gemeint haben "ohne externe Bibliotheken", dann bedenke, dass boost qausi ein erweiterter C++ Standard ist

-
Sehe ich mir auch mal an.
Mit dem .NET.... meinte ich, dass ich keine weiteren Installationen auf dem Anwenderrechner voraussetzen möchte.
-
So, ich habe das jetzt mit den 'alten' Hausmitteln hinbekommen. Hatte mir das einfacher vorgestellt, aber so sollte es gehen:
string l_endzeit("2008-08-02T21:57:08.000Z"); _tzset(); long l_timezone; _get_timezone(&l_timezone); struct tm timeinfoInput; timeinfoInput.tm_year = atoi(l_endzeit.substr(0, 4).c_str()) - 1900; timeinfoInput.tm_mon = atoi(l_endzeit.substr(5, 2).c_str()) - 1; timeinfoInput.tm_mday = atoi(l_endzeit.substr(8, 2).c_str()); timeinfoInput.tm_hour = atoi(l_endzeit.substr(11, 2).c_str()); timeinfoInput.tm_min = atoi(l_endzeit.substr(14, 2).c_str()); // mktime macht die Zeitzonen-Anpassung, timeinfoInput ist aber schon gmt // und sollte nicht angepasst werden, also abziehen timeinfoInput.tm_sec = atoi(l_endzeit.substr(17, 2).c_str()) - l_timezone; timeinfoInput.tm_isdst = 0; // Wir wollen GMT erstellen! time_t time = mktime(&timeinfoInput); struct tm timeinfoOutput = *(localtime(&time)); .... timeinfoOutput funzt(Falls es jemanden interessiert.)
