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

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

In Pocket speichern vorlesen Druckansicht 78 Kommentare lesen
Frau dreht an der Uhr

(Bild: New Africa/Shutterstock.com)

Lesezeit: 4 Min.
Von
  • Rainer Grimm
Inhaltsverzeichnis

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:

  • Winterzeit und Sommerzeit: Viele europäische Länder wie Deutschland verwenden eine sogenannte Sommerzeit und Winterzeit. Die Sommerzeit ist der Winterzeit in Deutschland eine Stunde voraus.
  • Weitere Zeitzonen: Länder wie China oder die Vereinigten Staaten haben unterschiedliche Zeitzonen. In den Vereinigten Staaten liegt zum Beispiel zwischen der Hawaii Standard Time (UTC-10) und der Eastern Daylight Time (UTC-4) ein Unterschied von sechs Stunden.
  • Zeitzonenunterschiede: Zeitzonenunterschiede sind oft Bruchteile von Stunden, wie 30 oder 45 Minuten. Die australische Zentralzeit ist UTC+9:30, und die australische Central Western Standard Time ist UTC+8:45.
  • Zeitzonenabkürzungen sind mehrdeutig: ADT kann Arabic Daylight Time (UTC+4) oder Atlantic Daylight Time (UTC-3) sein.

Die Zeitzonenbibliothek in C++20 ist ein vollständiger Parser der IANA timezone database. 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 ist der wichtigste Zeitstandard weltweit. Ein Computer verwendet die Unix-Zeit, 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)