Zeit in C++20: EinfĂĽhrung in die Chrono-Terminologie
Die Zeitzonenfunktionalität in C++20 setzt auf die Chrono-Terminologie aus C++11 zum Arbeiten mit Zeitpunkten, Zeitdauern und Uhren auf.

(Bild: by-studio/Shutterstock.com)
- Rainer Grimm
Im Wesentlichen basiert die Zeitzonenfunktionalität (C++20) auf der Kalenderfunktionalität (C++20), die wiederum auf der Chrono-Funktionalität (C++11) beruht. Daher beginnt diese grundlegende Chrono-Terminologie mit den drei C++11-Komponenten Zeitpunkt, Zeitdauer und Uhr.
Grundlegende Chrono-Terminologie
- Ein Zeitpunkt hat einen Startpunkt, die sogenannte Epoche und eine zusätzliche Zeitdauer seit der Epoche.
- Eine Zeitdauer ist die Differenz zwischen zwei Zeitpunkten. Die Anzahl der Ticks der Uhr definiert die Zeitdauer.
- Eine Uhr hat einen Startpunkt (Epoche) und einen Tick zur Berechnung des aktuellen Zeitpunkts.
Das Subtrahieren von Zeitpunkten ergibt eine Zeitdauer. Man erhält einen neuen Zeitpunkt, wenn man eine Zeitdauer zu einem Zeitpunkt addiert. Ein Jahr ist die typische Genauigkeit der Uhr und das Maß für die Zeitdauer.
Ich werde die drei Konzepte verwenden, um die Lebenszeit des 2011 verstorbenen Vaters der Programmiersprache C vorzustellen: Dennis Ritchie. Der Einfachheit halber interessiere ich mich nur fĂĽr die Jahre.
Dennis Ritchie wurde 70 Jahre alt. Die Geburt von Christus ist die Epoche. Wenn ich die Epoche mit der Zeitdauer kombiniere, erhalte ich die Zeitpunkte 1941 und 2011. Die Subtraktion des Zeitpunkts 1941 von 2011 ergibt die Zeitdauer in Jahresgenauigkeit.
C++11 hat die drei Uhren std::chrono::system_clock, std::chrono::steady_clock
und std::chrono::high_resolution_clock
. Die Zeitdauer kann positiv und negativ sein. Jede der drei Uhren hat eine Mitgliedsfunktion now
, die den aktuellen Zeitpunkt zurĂĽckgibt.
Mehr zu Zeitpunkt, Zeitdauer und Uhr steht in meinen vorherigen Artikeln:
C++20 fĂĽgt der Chronobibliothek neue Komponenten hinzu:
- Die Tageszeit ist die Zeitdauer seit Mitternacht, aufgeteilt in Stunden, Minuten, Sekunden und Sekundenbruchteile.
- Kalender steht fĂĽr verschiedene Kalenderdaten wie Jahr, Monat, Wochentag oder den n-ten Tag einer Woche.
- Eine Zeitzone steht fĂĽr eine bestimmte Zeit in einem bestimmten geografischen Gebiet.
- Eine zonierte Zeit kombiniert einen Zeitpunkt mit einer Zeitzone.
Zeit ist ein Mysterium
Ehrlich gesagt, ist die Zeit für mich ein Mysterium. Einerseits hat jeder von uns eine intuitive Vorstellung von Zeit, andererseits ist es äußerst schwierig, sie formal zu definieren. So hängen zum Beispiel die drei Komponenten Zeitpunkt, Zeitdauer und Uhr voneinander ab.
Zunächst möchte ich die grundlegenden Datentypen und Literale vorstellen.
Grundtypen und Literale
Dieser Abschnitt enthält der Vollständigkeit halber die grundlegenden Datentypen und Literale der bisherigen C++ Standards.
Uhren
Neben der Wanduhr std::chrono::system_clock
, der monotonen Uhr std::chrono::steady_clock
und der genauesten Uhr std::chrono::high_resolution_clock
in C++11, kennt C++20 fĂĽnf weitere Uhren. Die folgende Tabelle zeigt die Eigenschaften aller C++-Uhren und ihre Epoche.
Die Uhren std::chrono::steady_clock
und std::chrono::file_clock
haben eine implementierungsspezifische Epoche. Die Epochen von std::chrono::system_clock, std::chrono::gps_clock, std::chrono::tai_clock
und std::chrono::utc_clock
beginnen um 00:00:00. std::chrono::file_clock
ist die Uhr für Dateisystemeinträge.
Zusätzlich unterstützt C++11 die std::chrono::high_resolution_clock
. Diese Uhr ist auf allen Implementierungen nicht umgesetzt und ist lediglich ein Alias fĂĽr std::chrono::steady_clock
oder std::chrono::high_resolution_clock.
Ein Zeitpunkt lässt sich zwischen den Uhren umrechnen.
Konvertierung von Zeitpunkten zwischen Uhren
Die Funktion std::chrono::clock_cast
rechnet Zeitpunkte zwischen den Uhren um, die eine Epoche haben. Dies sind die Uhren std::chrono::system_clock, std::chrono::utc_clock, std::chrono::gps_clock
und std::chrono::tai_clock
. AuĂźerdem unterstĂĽtzt std::chrono::file_clock
die Konvertierung.
Das folgende Programm konvertiert den Zeitpunkt 2021-8-5 17:00:00
zwischen den verschiedenen Uhren.
// convertClocks.cpp
#include <iostream>
#include <sstream>
#include <chrono>
int main() {
std::cout << '\n';
using namespace std::literals;
std::chrono::utc_time<std::chrono::utc_clock::duration>
timePoint;
std::istringstream{"2021-8-5 17:00:00"}
>> std::chrono::parse("%F %T"s, timePoint);
auto timePointUTC
= std::chrono::clock_cast<std::chrono::utc_clock>(timePoint);
std::cout << "UTC_time: "
<< std::format("{:%F %X %Z}", timePointUTC) << '\n';
auto timePointSys =
std::chrono::clock_cast<std::chrono::system_clock>(timePoint);
std::cout << "sys_time: "
<< std::format("{:%F %X %Z}", timePointSys) << '\n';
auto timePointFile =
std::chrono::clock_cast<std::chrono::file_clock>(timePoint);
std::cout << "file_time: "
<< std::format("{:%F %X %Z}", timePointFile) << '\n';
auto timePointGPS =
std::chrono::clock_cast<std::chrono::gps_clock>(timePoint);
std::cout << "GPS_time: "
<< std::format("{:%F %X %Z}", timePointGPS) << '\n';
auto timePointTAI =
std::chrono::clock_cast<std::chrono::tai_clock>(timePoint);
std::cout << "TAI_time: "
<< std::format("{:%F %X %Z}", timePointTAI) << '\n';
std::cout << '\n';
}
Die Funktion std::chrono::parse
parst das Chrono-Objekt aus dem Stream. In den folgenden Zeilen wandelt std::chrono::clock_cast
den timePoint
in die angegebene Uhr um. In der folgenden Zeile wird der Zeitpunkt angezeigt, wobei das Datum (%F
), die Darstellung der lokalen Zeit (%X
) und die AbkĂĽrzung der Zeitzone (%Z
) angegeben werden. Einer meiner nächsten Artikel wird tiefer auf den Formatstring eingehen.
Die Ausgabe wird manche ĂĽberraschen: Die GPS-Zeit liegt 18 Sekunden vor der UTC-Zeit. Die TAI-Zeit liegt 37 Sekunden vor der UTC-Zeit und 19 Sekunden vor der GPS-Zeit.
Wie geht's weiter?
In meinem nächsten Artikel werde ich meine Reise durch die Datentypen mit Zeitdauern und Zeitpunkten fortsetzen.
(rme)