zurück zum Artikel

Zeit in C++20: Details zu der Arbeit mit Zeitzonen

Rainer Grimm
Frau dreht an der Uhr

(Bild: New Africa/Shutterstock.com)

Der Umgang mit Zeitzonen ist mit einigen Herausforderungen verbunden. Die Chrono-Erweiterung in C++20 helfen dabei, sie zu bewältigen.

Dieser Artikel ist der siebte in meiner ausführlichen Reise durch die Chrono-Erweiterung in C++20:

Eine Zeitzone ist zunächst eine Region und ihre gesamte Datumsgeschichte, wie Sommerzeit oder Schaltsekunden.

Modernes C++ – Rainer Grimm

Rainer Grimm ist seit vielen Jahren als Softwarearchitekt, Team- und Schulungsleiter tätig. Er schreibt gerne Artikel zu den Programmiersprachen C++, Python und Haskell, spricht aber auch gerne und häufig auf Fachkonferenzen. Auf seinem Blog Modernes C++ beschäftigt er sich intensiv mit seiner Leidenschaft C++.

Der Umgang mit Zeitzonen bringt einige Herausforderungen mit sich:

Die Zeitzonenbibliothek in C++20 ist ein vollständiger Parser der IANA timezone database [7]. Die folgende Tabelle soll einen ersten Eindruck von der neuen Funktionalität vermitteln.

Die Nutzung der Zeitzonendatenbank erfordert ein Betriebssystem. Daher führt die Verwendung der Zeitzonendatenbank auf einem eigenständigen System normalerweise zu einer Ausnahme. Die Zeitzonendatenbank wird während der Aktualisierung des Betriebssystems, beispielsweise bei einem Neustart, aktualisiert. Wenn ein System die Aktualisierung der IANA-Zeitzonendatenbank ohne Neustart unterstützt, kann man std::chrono::reload_tzdb() verwenden. Die neue Datenbank wird atomar an den Anfang der verknüpften Liste gesetzt. Aufrufe wie std::chrono::get_tzdb_list() oder std::chrono::get_tzdb() parsen den Anfang der Liste. Folglich erhalten die Datenbankabfragen die aktualisierten Datenbankeinträge. std::chrono::get_tzdb().version gibt die Version der verwendeten Datenbank zurück.

Die beiden elementaren Datentypen für Zeitzonen sind std::chrono::time_zone und std::chrono::zoned_time.

Die möglichen Zeitzonen sind durch die IANA-Zeitzonendatenbank vordefiniert. Die Aufrufe std::chrono::current_zone() und std::chrono::locate_zone(name) geben einen Zeiger auf die aktuelle oder per Name angeforderte Zeitzone zurück. Der Aufruf std::chrono::locate_zone(name) führt zu einer Suche nach name in der Datenbank. Wenn die Suche erfolglos ist, wirft das System eine std::runtime_error-Ausnahme.

std::chrono::zoned_time() stellt eine Zeitzone in Kombination mit einem Zeitpunkt dar. Man kann einen Systemzeitpunkt oder einen lokalen Zeitpunkt als Zeitpunkt verwenden. Ein Systemzeitpunkt verwendet std::chrono::system_clock und ein lokaler Zeitpunkt verwendet die Pseudo-Uhr std::chrono::local_t.

Mein erstes Beispiel ist ganz einfach. Es zeigt die UTC-Zeit und die Ortszeit an.

Die UTC oder Coordinated Univeral Time [8] ist der wichtigste Zeitstandard weltweit. Ein Computer verwendet die Unix-Zeit [9], die eine sehr gute Annäherung an die UTC ist. Die UNIX-Zeit ist die Anzahl der Sekunden seit der Unix-Epoche. Die Unix-Epoche ist 00:00:00 UTC am 1. Januar 1970.

std::chrono::system_clock::now() in (1) gibt im folgenden Programm localTime.cpp die Unix-Zeit zurück.

// localTime.cpp

#include <chrono>
#include <iostream>

int main() {

    std::cout << '\n';

    using std::chrono::floor;
 
    std::cout << "UTC  time" << '\n';                        // (1)             
    auto utcTime = std::chrono::system_clock::now();
    std::cout << "  " << utcTime << '\n';
    std::cout << "  " << floor<std::chrono::seconds>(utcTime) 
              << '\n';

    std::cout << '\n';
    
    std::cout << "Local time" << '\n';                       // (2)                
    auto localTime = 
      std::chrono::zoned_time(std::chrono::current_zone(),
                              utcTime);

    std::cout << "  " << localTime << '\n';
    std::cout << "  " << floor<std::chrono::seconds>
                         (localTime.get_local_time()) 
                      << '\n';

    auto offset = localTime.get_info().offset;               // (3)    
    std::cout << "  UTC offset: "  << offset << '\n';

    std::cout << '\n';

}

Ich habe dem Programm nicht allzu viel hinzuzufügen. Der Codeblock, der mit (1) beginnt, holt sich den aktuellen Zeitpunkt, schneidet ihn auf Sekunden ab und zeigt ihn an. Der Aufruf std::chrono::zoned_time erzeugt std::chrono::zoned_time localTime. Der folgende Aufruf localTime.get_local_time() gibt den gespeicherten Zeitpunkt als lokale Zeit zurück. Auch dieser Zeitpunkt wird auf Sekunden abgeschnitten. localTime (3) kann auch verwendet werden, um Informationen über die Zeitzone zu erhalten. In diesem Fall bin ich an der Abweichung von der UTC interessiert.

Mein nächster Artikel beantwortet eine wichtige Frage, wenn ich in einer anderen Zeitzone unterrichte: Wann soll ich meinen Online-Kurs beginnen? (rme [10])


URL dieses Artikels:
https://www.heise.de/-9705367

Links in diesem Artikel:
[1] https://www.heise.de/blog/Zeit-in-C-20-Einfuehrung-in-die-Chrono-Terminologie-9642462.html
[2] https://www.heise.de/blog/Zeit-in-C-20-Grundlegende-Chrono-Terminologie-mit-Zeitdauer-und-Zeitpunkt-9651792.html
[3] https://heise.de/-9664010
[4] https://heise.de/-9671530
[5] https://heise.de/-9684590
[6] https://heise.de/-9692091
[7] https://www.iana.org/time-zones
[8] https://en.wikipedia.org/wiki/Coordinated_Universal_Time
[9] https://en.wikipedia.org/wiki/Unix_time
[10] mailto:rme@ix.de