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.
- Rainer Grimm
Tageszeit
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.
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_s
s-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:
Kalenderdatum
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.
Wie geht's weiter?
C++20 unterstützt Konstanten und Literale, um die Verwendung von Datentypen bequemer zu machen. (rme)