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.

In Pocket speichern vorlesen Druckansicht

(Bild: by-studio/Shutterstock.com)

Lesezeit: 4 Min.
Von
  • Rainer Grimm
Inhaltsverzeichnis

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.

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++.

  • 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.

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.

Dieser Abschnitt enthält der Vollständigkeit halber die grundlegenden Datentypen und Literale der bisherigen C++ Standards.

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.

In meinem nächsten Artikel werde ich meine Reise durch die Datentypen mit Zeitdauern und Zeitpunkten fortsetzen.

(rme)