Zeit in C++20: Grundlegende Chrono-Terminologie mit Zeitdauer und Zeitpunkt

Der Blogbeitrag setzt die Reise durch die grundlegenden Datentypen mit Zeitdauern und Zeitpunkten fort.

In Pocket speichern vorlesen Druckansicht 3 Kommentare lesen

(Bild: by-studio/Shutterstock.com)

Lesezeit: 4 Min.
Von
  • Rainer Grimm
Inhaltsverzeichnis

Die Zeitzonenfunktionalität (C++20) basiert im Wesentlichen auf der Kalenderfunktionalität (C++20), die wiederum auf der Chrono-Funktionalität (C++11) beruht. Nach dem Überblick zur grundlegenden Chrono-Terminologie im letzten Beitrag stelle ich diesmal neue Datentypen in C++20 vor.

In C++14 wurden Datentypen wie std::chrono::seconds für Zeitdauern und entsprechende Zeitliterale wie 5s eingeführt. C++20 fügte neue Datentypen hinzu. Die folgende Tabelle zeigt alle der Vollständigkeit halber.

Oft werden die Zeitdauer std::chrono::days und das Kalenderdatum std::chrono::day verwechselt. Das Gleiche gilt für die Zeitdauer std::chrono::years und das Kalenderdatum std::chrono::year.

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

In C++20 wurden zwei neue Literale für die neuen Kalendertypen std::chrono::day und std::chrono::year hinzugefügt. Die Literale d und y beziehen sich auf einen std::chrono::day und std::chrono::year.

  • Das Tagesliteral steht für einen Tag des Monats und ist nicht spezifiziert, wenn es außerhalb des Bereichs [0, 255] liegt.
  • Das Jahresliteral steht für ein Jahr im gregorianischen Kalender und ist nicht spezifiziert, wenn es außerhalb des Bereichs [-32767, 32767] liegt.

Das folgende Programm verdeutlicht den Unterschied zwischen std::chrono::days und std::chrono::day und dementsprechend zwischen std::chrono::years und std::chrono::year.

// dayDays.cpp

#include <iostream>
#include <chrono>

int main() {

    std::cout << '\n';

    using namespace std::chrono_literals; 

    std::chrono::days days1 
      = std::chrono::day(30) - std::chrono::day(25);        // (1)
    std::chrono::days days2 = 30d - 25d;                    // (3)
    if ( days1 == days2 && 
         days1 == std::chrono::days(5)) std::cout << "Five days\n";

    std::chrono::years years1 
      = std::chrono::year(2021) - std::chrono::year(1998);  // (2)
    std::chrono::years years2= 2021y - 1998y;               // (4)
    if ( years1 == years2 && 
         years1 == std::chrono::years(23)) 
       std::cout << "Twenty-three years\n";

    std::cout << '\n';

}

Wer zwei Objekte vom Typ std::chrono::day subtrahiert (1), erhält ein Objekt vom Typ std::chrono::days. Das Gleiche gilt für das std::chrono::year (2) und std::chrono::years. Dank der using-Deklaration mit Namespace std::chrono_literals kann ich die Zeitliterale für std::chrono::day und std::chrono::year direkt angeben (3 und 4).

Es gibt verschiedene Möglichkeiten, die Literale einzuschließen.

  • using namespace std::literals: enthält alle C++-Literale,
  • using namespace std::chrono: schließt den gesamten Namensraum std::chrono ein,
  • using namespace std::chrono_literals: enthält alle Zeitliterale und
  • using namespace std::literals::chrono_literals: schließt alle Zeitliterale ein.

Das Programm literals.cpp zeigt die Verwendung der verschiedenen using-Deklarationen.

// literals.cpp

#include <chrono>
#include <string>

int main() {

    {
        using namespace std::literals;

        std::string cppString = "C++ string literal"s;     // (1)
        auto aMinute = 60s;                                // (2)
        // duration aHour = 0.25h + 15min + 1800s;
    }

    {
        using namespace std::chrono;

        // std::string cppString = "C++ string literal"s;
        auto aMinute = 60s;
        duration aHour = 0.25h + 15min + 1800s;            // (3)
    }

    {
        using namespace std::chrono_literals;

        // std::string cppString = "C++ String literal"s;
        auto aMinute = 60s;
        // duration aHour = 0.25h + 15min + 1800s;
    }

}

Die Deklarationen im Namensraum std::literals ermöglichen es, alle Built-in-Literale wie das String-Literal ("C++ String-Literal "s in 1) oder das Zeitliteral (60s in Zeile 2) zu verwenden. std::chrono::duration kann nicht unqualifiziert verwendet werden. Im Gegenteil, die using-Deklaration using namespace std::chrono erlaubt es, die Zeitliterale und den Datentyp std::chrono::duration (3) unqualifiziert zu verwenden: duration aHour = 0.25h + 15min + 1800s. Dank der using-Deklaration using namespace::std::chrono::literals sind alle Zeitliterale verfügbar.

Neben der Uhr und der Zeitdauer war der dritte grundlegende Typ in C++11 std::chrono::time_point.

template<typename Clock, 
         typename Duration = typename Clock::duration> 
class time_point;

Ein std::chrono::time_point hängt von der Uhr und der Zeitdauer ab. C++20 bietet Aliasnamen für zusätzliche Zeitpunkte an.

Mit Ausnahme von std::chrono::steady_clock kann man einen Zeitpunkt mit der angegebenen Zeitdauer definieren. Bei allen außer der Uhr std::chrono::file_clock ist es möglich, diese für Sekunden anzugeben. Mit std::chrono::local_t und std::chrono::system_clock kann man sie auch für Tage festlegen.

std::chrono::hh_mm_ss ist die Zeitdauer seit Mitternacht, aufgeteilt in Stunden, Minuten, Sekunden und Bruchteile von Sekunden. Dieser neue Datentyp in C++20 steht für die Zeit des Tages. (rme)