UTC Offset von z. B. "CEST" ermitteln



  • Hi,

    es gibt unter C++ ja nichts grausameres als mit Zeitobjekten zu arbeiten.
    Nun stehe ich vor dem Problem einen Zeitstempel wie z. B.

    "Sa, 01 November 2008 19:35:00 CEST"

    einlesen zu wollen. Bis auf die "CEST" Zeitzone klappt das auch schon.
    Daher die Fragen:

    1. Wie bekomme ich zu einer abgekürzten Zeitzone die sich nicht in meiner Zeitzone befindet den UTC Offset? Es gibt ja nun diese neue "chrono::zoned_time".

    2. Und auch der umgekehrte Fall, dass man die abgekürzte Zeitzone ausgeben will. Wie kann ich einen "Offset" wieder in einen abgekürzten Zeitzonennamen wandeln? Das "%Z" der "stftime" Funktion gibt ja leider "Mitteleuropäische Zeit" aus. Facepalm.



  • Alle Funktionen für die Zeitzonen in der C++ Standard Bibliothek sind erst ab C++20 verfügbar. D.h. Du wirst nicht darum herum kommen eine OS Funktion zu nutzen. Unter UNIX/Linux würde man dazu die Systemfunktionen strftime und strptime nutzen.



  • @Enumerator Gleich vorweg: Ich hab die mit C++-Zeitzonen-Funktionen noch nicht verwendet, aber woran fehlt es denn konkret bei den z.B. auf cppreference bereitgestellten Informationen?

    1. Wie bekomme ich zu einer abgekürzten Zeitzone die sich nicht in meiner Zeitzone befindet den UTC Offset? Es gibt ja nun diese neue "chrono::zoned_time".

    Was ist z.B. mit std::chrono::locate_zone, std::chrono::time_zone::get_info und std::chrono::sys_info::offset? Damit müsste man den Offset ermitteln können, denke ich.

    Eine wichtige Erkenntnis ist wohl, dass der Offset nicht nur von der Zeitzone, sondern auch von einem Datum und einer Uhrzeit abhängig ist, z.B. wegen Sommer/Winterzeit ...

    1. Und auch der umgekehrte Fall, dass man die abgekürzte Zeitzone ausgeben will. Wie kann ich einen "Offset" wieder in einen abgekürzten Zeitzonennamen wandeln? Das "%Z" der "stftime" Funktion gibt ja leider "Mitteleuropäische Zeit" aus. Facepalm.

    ... das bedeutet auch, dass sich Offsets schonmal überschneiden können. Z.B. wenn es zwei benachbarte Zonen gibt, wo die eine Zone Sommer/Winterzeit hat und die andere nicht. Daher ist die Umkehrabbildung von (Zeitpunkt, Offset) -> Zeitzone wohl nicht immer eindeutig.

    Ich denke, man kann wohl via std::chrono::tzdb_list und std::chrono::tzdb::zones an alle Zeitzonen kommen und über die o.g. Funktionen zu bestimmten Zeitpunkten deren Offsets ermitteln. Wie man da dann jedoch die Mehrdeutigkeiten auflöst, dazu musst du dir wohl selbst was überlegen. Und wenn es nur ist, diese Rückabbildung einfach nicht zu unterstützen.

    @john-0 sagte in UTC Offset von z. B. "CEST" ermitteln:

    Alle Funktionen für die Zeitzonen in der C++ Standard Bibliothek sind erst ab C++20 verfügbar. D.h. Du wirst nicht darum herum kommen eine OS Funktion zu nutzen. Unter UNIX/Linux würde man dazu die Systemfunktionen strftime und strptime nutzen.

    Ja, ich denke die C++20-Funktionen nutzen ebenfalls diese OS-Funktionen. Ich kann mir nicht vorstellen, dass die Standardbibliothek wirklich sowas wie eigene Zeitzonen-Datenbanken pflegen will, die sich durchaus auch immer mal wieder aus diversen Gründen ändern können (politische Gründe, Abschaffung/Einführung von Sommer/Winterzeit, etc.). Daher sind beide Lösungen vermutlich äquivalent. Die C++20-Variante hat halt lediglich ein C++-Interface.



  • @Finnegan sagte in UTC Offset von z. B. "CEST" ermitteln:

    Eine wichtige Erkenntnis ist wohl, dass der Offset nicht nur von der Zeitzone, sondern auch von einem Datum und einer Uhrzeit abhängig ist, z.B. wegen Sommer/Winterzeit ...

    Die Bezeichnungen der Zeitzonen berücksichtigen das ja schon. MEZ ist UTC+1, MESZ ist UTC+2.
    Aus MEZ bzw. MESZ kann man auch die Daten berechnen, an denen zwischen beiden umgeschaltet wird.

    Was man mit Angaben wie 1.1.2022 12:00 MESZ macht, kann man sich ja überlegen.

    Nur aus dem Offset bekommt man keine Zeitzone raus, da die auch vom Ort abhängen.
    Die NATO-Zeitzonen würden gerade noch gehen.



  • @DirkB sagte in UTC Offset von z. B. "CEST" ermitteln:

    @Finnegan sagte in UTC Offset von z. B. "CEST" ermitteln:

    Eine wichtige Erkenntnis ist wohl, dass der Offset nicht nur von der Zeitzone, sondern auch von einem Datum und einer Uhrzeit abhängig ist, z.B. wegen Sommer/Winterzeit ...

    Die Bezeichnungen der Zeitzonen berücksichtigen das ja schon. MEZ ist UTC+1, MESZ ist UTC+2.
    Aus MEZ bzw. MESZ kann man auch die Daten berechnen, an denen zwischen beiden umgeschaltet wird.

    Ja, stimmt. Das braucht man eher um schwammigere Angaben wie "Europe/Berlin" in eine eindeutige Zeitzone aufzulösen. Hatte einfach angenommen, dass das wohl der Grund ist, weshalb std::chrono::time_zone::get_info auch noch einen Zeitpunkt haben will. Ich denke da gibt es wohl noch andere Gründe. Kann es vielleicht sein, dass die Datenbank eventuell auch historische Änderungen der Zeitzonen abbildet, weshalb man den Zeitpunkt braucht?

    Nur aus dem Offset bekommt man keine Zeitzone raus, da die auch vom Ort abhängen.

    Ja, das sehe ich auch als das größte Problem bei dem Vorhaben. Wenn man es aus welchen Gründen auch immer unbedingt haben will, kann man vielleicht eine simple Prioritätsliste definieren. Bei Mehrdeutigkeiten wird dann immer die erste passende Zone der Liste genommen, ansonsten der erste Treffer aus der Datenbank.



  • @Finnegan sagte in UTC Offset von z. B. "CEST" ermitteln:

    Kann es vielleicht sein, dass die Datenbank eventuell auch historische Änderungen der Zeitzonen abbildet, weshalb man den Zeitpunkt braucht?

    Eigentlich nur, wenn das Datum unvollständig ist.
    Historisch ja, denn früher endete die Sommerzeit (in Deutschland) schon am letzten Sonntag im September.
    Bei der Umstellung auf Oktober war dann ein Windows 95 Update fällig.



  • Ob C++20 oder Systemfunktion ist mir egal, es soll einfach funktionieren. Ich wollte mir jetzt mal alle Zeitzonen ausgeben lassen. Im Zweifel hätte ich mir die gesuchte Zone "CEST" halt selber anhand der "Abbreviation" rausgesucht:

    auto now = system_clock::now();
    		const std::chrono::time_zone* pZone = nullptr;
    		const std::chrono::tzdb_list& lstTimeZones = get_tzdb_list();
    		for (auto itTimeZones = lstTimeZones.begin(); itTimeZones != lstTimeZones.end(); ++itTimeZones)
    		{
    			const std::vector<std::chrono::time_zone>& rNestedTimeZones = itTimeZones->zones;
    			for (auto itNestedTimeZones = rNestedTimeZones.begin(); itNestedTimeZones != rNestedTimeZones.end(); ++itNestedTimeZones)
    			{
    				const std::chrono::time_zone& rNestedTimeZone = *itNestedTimeZones;
    				const std::string& sNestedTimeZone = rNestedTimeZone.get_info(now).abbrev;
    				std::cout << sNestedTimeZone << std::endl;
    			}
    		}
    

    Aber der Code gibt nur "GMT+-XX" aus. Was machen die im C++ Standardisierungkommittee eigentlich. Seit Jahren nur Scheiße die die farbrizieren. Man kann jetzt bald im Jahr 2022 noch immer keinen Zeitstempel ala "Sa, 01 November 2008 19:35:00 CEST" parsen. Über ...

    const std::chrono::time_zone* pZone = std::chrono::get_tzdb().locate_zone("Australia/Perth")
    

    ...kommt man z.B. an eine Zeitzone. Aber das geht nicht mit den Abkürzungen "AEST", "CEST" und so weiter. Woher soll ich denn wissen was "CEST" ist. Soll ich mir das selber in einem Lookup Table Speichern. Kann doch nicht deren Ernst sein. Von Vorne bis Hintern nicht durchdacht der std::chrono Murks.



  • @Enumerator Soll das C++-Standardkomitee jetzt auch noch Zeitzonen regulieren? Nein!

    Was ist überhaupt CET? Ich habe CET sowohl im Sommer als auch im Winter in Benutzung gesehen, mal bedeutete es +0100, mal +0200.

    Andere Abkürzungen gibt es gar mehrfach wie z.B. CST (wenn du Amerikaner bist, natürlich Central Standard Time, als Chinese vielleicht eher Shanghai Time...)

    Siehe hier für eine Antwort auf deine nur scheinbar leichte Frage: https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes#convert_by_timezone_abbreviation

    Edit: was ist das überhaupt für eine Zeit, "November ... CEST". Einerseits scheinst du deutsche Namen zu verwenden, dann müssten wir aber von MEZ und MESZ sprechen. Und im November gibt es keine Sommerzeit (bei uns). November 2008 mit CEST ist also eh nicht gültig.



  • Guter Link, dann ist das C++-Standardkommitee tatsächlich unschuldig. Ich bekomme die Zeitstempel per HTTP Header. Ich bin ja auch davon ausgegangen, dass diese immer in UTC/GMT sind hatte das auch so gelesen, das das laut ISO irgendwas so vorgeschrieben ist. Aber scheint wohl doch nicht so zu sein. Ich frage mich halt warum man sich dann gerade auf diese Darstellung eines Zeitstempels festgelegt hat wenn das so problematisch ist. Und gerade im Web ist man doch schnell mal auch auf Servern im Auslang unterwegs. Ein Zeitstempel in GMT bzw. der Form "2021-12-16 12:00:00Z+01:00" wäre doch viel einfacher für alle beteiligten gewesen. Eigentlich ist mir auch egal welche Zeitzone sich hinter der Abbreviation verbirgt solange diese den selben UTC Offset haben. Aber das scheint ja auch nicht der Fall zu sein.



  • @Enumerator sagte in UTC Offset von z. B. "CEST" ermitteln:

    Ich frage mich halt warum man sich dann gerade auf diese Darstellung eines Zeitstempels festgelegt hat wenn das so problematisch ist.

    Wer ist "man"? "Man", im Sinne von die Gesamtheit der IT-Branche, hat sich ganz sicher nicht darauf festgelegt so komische Timestamps zu verwenden. So komische Formatierungen wie "Sa, 01 November 2008 19:35:00 CEST" sind eher unüblich, und werden meist dort verwendet wo Leute am Werk waren die keinen Tau haben und/oder es für wichtig befunden wurde dass nicht-IT-ler die Zeitangabe lesen können.

    Standard wäre eigentlich ISO-8601 bzw. leichte Abwandlungen davon ,ala

    • 2021-12-16T11:37:40+01:00
    • 2021-12-16 11:37:40 (GMT+01:00)
    • 2021-12-16 11:37:40 (GMT+1)

    etc.



  • @hustbaer sagte in UTC Offset von z. B. "CEST" ermitteln:

    So komische Formatierungen wie "Sa, 01 November 2008 19:35:00 CEST" sind eher unüblich,

    Kommen aber oft beim date Befehl in der shell, strftime() mit "%c" oder der .toString Methode in Javascript.



  • @DirkB sagte in UTC Offset von z. B. "CEST" ermitteln:

    @hustbaer sagte in UTC Offset von z. B. "CEST" ermitteln:

    So komische Formatierungen wie "Sa, 01 November 2008 19:35:00 CEST" sind eher unüblich,

    Kommen aber oft beim date Befehl in der shell, strftime() mit "%c" oder der .toString Methode in Javascript.

    Kontext. Es geht in diesem Thread darum solche Strings zu parsen. Und überall dort wo man die Daten wieder parsen möchte, sind solche Formatierungen unüblich.


Anmelden zum Antworten