Zeit in C++20: Neue Datentypen für die Tageszeit und das Kalenderdatum

Der neue Datentyp std::chrono::hh_mm_ss in C++20 steht für die Tageszeit und der Typ std::chrono::year_month_day für ein Kalenderdatum.

In Pocket speichern vorlesen Druckansicht 14 Kommentare lesen

(Bild: Kwangmoozaa/Shutterstock.com)

Lesezeit: 4 Min.
Von
  • Rainer Grimm
Inhaltsverzeichnis

Nach den Artikeln zu den grundlegenden Datentypen für die Chrono-Funktionalität beschäftige ich mich diesmal mit einem neuen Datentyp in C++20.

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

std::chrono::hh_mm_ss ist die Dauer seit Mitternacht, aufgeteilt in Stunden, Minuten, Sekunden und Bruchteile von Sekunden. Dieser Datentyp wird normalerweise als Formatierungswerkzeug verwendet. Die folgende Tabelle gibt zunächst einen kurzen Überblick über die std::chrono::hh_mm_ss-Instanz tOfDay.

Abhängig von der verwendeten Zeitdauer liefert das statische Mitglied die entsprechende tOfDay.fractional_width. Wenn kein solcher Wert für fractional_width im Bereich [0, 18] existiert, ist fractional_width gleich 6. Siehe zum Beispiel std::chrono::duration<int, std::ratio<1, 3>> in der folgenden Tabelle.

Die Verwendung des Datentyps std::chrono::hh_mm_ss ist ganz einfach.

// timeOfDay.cpp

#include <chrono>
#include <iostream>

int main() {
                                                            
  using namespace std::chrono_literals; 

  std::cout << std::boolalpha << '\n';
    
  auto timeOfDay = 
    std::chrono::hh_mm_ss(10.5h + 98min + 2020s + 0.5s);   // (1)
    
  std::cout<< "timeOfDay: " << timeOfDay << '\n';          // (2)

  std::cout << '\n';

  std::cout << "timeOfDay.hours(): " 
            << timeOfDay.hours() << '\n';                  // (4)
  std::cout << "timeOfDay.minutes(): " 
            << timeOfDay.minutes() << '\n';                // (4)
  std::cout << "timeOfDay.seconds(): " 
            << timeOfDay.seconds() << '\n';                // (4)
  std::cout << "timeOfDay.subseconds(): " 
            << timeOfDay.subseconds() << '\n';             // (4)
  std::cout << "timeOfDay.to_duration(): " 
            << timeOfDay.to_duration() << '\n';            // (5)

  std::cout << '\n';

  std::cout << "std::chrono::hh_mm_ss(45700.5s): " 
            << std::chrono::hh_mm_ss(45700.5s) << '\n';    // (6)

  std::cout << '\n';

  std::cout << "std::chrono::is_am(5h): " 
            << std::chrono::is_am(5h) << '\n';             // (7)    
  std::cout << "std::chrono::is_am(15h): " 
            << std::chrono::is_am(15h) << '\n';            // (7)

  std::cout << '\n';
  
  std::cout << "std::chrono::make12(5h): " 
            << std::chrono::make12(5h) << '\n';            // (7)   
  std::cout << "std::chrono::make12(15h): " 
            << std::chrono::make12(15h) << '\n';           // (7) 
}

In (1) erstelle ich eine neue Instanz von std::chrono::hh_mm_ss: timeOfDay. Dank der Chrono-Literale aus C++14 kann ich ein paar Zeitdauern hinzufügen, um ein Time-of-Day-Objekt zu initialisieren. Mit C++20 kann man timeOfDay direkt ausgeben (2). Der Rest sollte einfach zu lesen sein. (4) gibt die Komponenten der Zeit seit Mitternacht in Stunden, Minuten, Sekunden und Sekundenbruchteilen aus. (5) gibt die Zeitdauer seit Mitternacht in Sekunden zurück. (6) ist interessanter: Die angegebenen Sekunden entsprechen der Zeit, die in (2) angezeigt wird. (7) gibt zurück, ob die angegebene Stunde vormittags ist. (8) gibt schließlich das 12-Stunden-Äquivalent der angegebenen Stunde zurück.

Hier ist die Ausgabe des Programms:

Ein neuer Datentyp der Chrono-Erweiterung in C++20 ist ein Kalenderdatum. C++20 unterstützt verschiedene Möglichkeiten, ein Kalenderdatum zu erstellen und mit ihm zu interagieren. Zuallererst: Wie sieht ein Kalenderdatum aus?

  • Ein Kalenderdatum besteht aus einem Jahr, einem Monat und einem Tag. Deshalb gibt es in C++20 einen speziellen Datentyp std::chrono::year_month_day. C++20 hat noch viel mehr zu bieten. Die folgende Tabelle soll einen Überblick über die Kalendertypen geben, bevor ich verschiedene Anwendungsfälle zeige.

Dank der Cute Syntax kann man std::chrono::operator / verwenden, um gregorianische Kalenderdaten zu erstellen.

Die Datentypen für Kalender unterstützen verschiedene Operationen. Die folgende Tabelle gibt einen Überblick. Aus Gründen der Lesbarkeit ignoriere ich teilweise den Namespace std::chrono.

Die Inkrement- und Dekrement-Operationen ++/-- werden in der Präfix- und Postfix-Version unterstützt. Das Addieren oder Subtrahieren +/- erfordert Objekte des Datentyps std::chrono::duration. Das heißt, wenn man die Differenz von zwei Objekten des Datentyps std::chrono::day bildet, erhältt man ein Objekt vom Typ std::chrono::days. <=> ist der neue Drei-Weg-Vergleichsoperator.

Das folgende Programm verwendet die Operationen für die Kalendertypen:

// calendarOperations.cpp

#include <chrono>
#include <iostream>

int main() {

  std::cout << '\n';

  using std::chrono::Monday;
  using std::chrono::Saturday;

  using std::chrono::March;
  using std::chrono::June;
  using std::chrono::July;

  using std::chrono::days;
  using std::chrono::months;
  using std::chrono::years;

  using std::chrono::last;

  using namespace std::chrono_literals;

  std::cout << std::boolalpha;

  std::cout << "March: " << March << '\n';  
  std::cout << "March + months(3): " 
            << March + months(3) << '\n';                // (1)
  std::cout << "March - months(25): " 
            << March - months(25) << '\n';               // (5)  
  std::cout << "July - June: " <<  July - June 
            << '\n';                                     // (6)
  std::cout << "June < July: " << (June < July) << '\n'; // (7)

  std::cout << '\n';
 
  std::cout << "Saturday: " << Saturday << '\n';
  std::cout << "Saturday + days(3): " 
            << Saturday + days(3) << '\n';                // (2)
  std::cout << "Saturday - days(22): " 
            << Saturday - days(22) << '\n';               // (8)
  std::cout << "Saturday - Monday: " 
            <<  Saturday - Monday << '\n';                // (9)

  std::cout << '\n';

  std::cout << "2021y/March: " << 2021y/March << '\n';    // (3)
  std::cout << "2021y/March + years(3) - months(35): "    // (10)
            << 2021y/March + years(3) - months(35) << '\n';
  std::cout << "2022y/July - 2021y/June: " 
            << 2022y/July - 2021y/June << '\n';           // (11)
  std::cout << "2021y/June > 2021y/July: " 
            << (2021y/June > 2021y/July) << '\n';         // (12)

  std::cout << '\n';

  std::cout << "2021y/March/Saturday[last]: " 
            << 2021y/March/Saturday[last] << '\n';        // (4)
  std::cout << "2021y/March/Saturday[last] + months(13) " +
               "+ years(3): " 
            << 2021y/March/Saturday[last] + 
               months(13) + years(3) << '\n';
  std::cout << "2021y/July/Saturday[last] - months(1) == " + 
               " 2021y/June/Saturday[last]: "
            << (2021y/July/Saturday[last] - months(1) == 
                2021y/June/Saturday[last]) 
            << '\n';

  std::cout << '\n';

}

Das Programm führt Operationen auf std::chrono::month (1), std::chrono::weekday (2), std::chrono::year_month (3) und std::chrono::year_month_weekday_last (4) durch.

Beim Addieren oder Subtrahieren der Zeitdauer std::chrono::months werden automatisch Modulo-Operationen angewendet (5 und 6). Die Subtraktion von zwei std::chrono::month-Objekten ergibt 1 Monat. Ein Monat hat 2629746 Sekunden (7). Dementsprechend kann man eine Zeitdauer std::chrono::days zu den Kalenderdaten std::chrono::day addieren oder von ihnen subtrahieren (8 und 9). Die Subtraktion zweier std::chrono::day-Objekte ergibt ein std::chrono::days-Objekt. std::chrono::year_month ermöglicht die Subtraktion (10), die Differenz (11) und den Vergleich von Zeitpunkten (12). Objekte vom Typ std::chrono::weekday_last ermöglichen die Addition/Subtraktion der Zeitdauern std::chrono::months und std::chrono::years. Außerdem können diese std::chrono::weekday_last-Objekte miteinander verglichen werden.

C++20 unterstützt Konstanten und Literale, um die Verwendung von Datentypen bequemer zu machen. (rme)