Zeit in C++20: Kalendertermine darstellen und prĂĽfen
C++20 bietet neben den Funktionen zum Erstellen und Berechnen von Kalenderdaten auch Methoden, um die Daten anzuzeigen und zu ĂĽberprĂĽfen.

(Bild: Kwangmoozaa/Shutterstock.com)
- Rainer Grimm
In meinem letzten Artikel, "Zeit in C++20: Kalendertermine erstellen", habe ich Kalenderdaten erstellt, die ich heute anzeigen und ĂĽberprĂĽfen werde.
Dieser Artikel ist der fĂĽnfte Beitrag meiner ausfĂĽhrlichen Reise durch die Chrono-Erweiterung in C++20:
- Zeit in C++20: EinfĂĽhrung in die Chrono-Terminologie
- Zeit in C++20: EinfĂĽhrung in die Chrono-Terminologie mit Zeitdauer und Zeitpunkt
- Zeit in C++20: Neue Datentypen fĂĽr die Tageszeit und das Kalenderdatum
- Zeit in C++20: Kalendertermine erstellen
Anzeige von Kalenderdaten
Dank std::chrono::local_days
oder std::chrono::sys_days
kann man Kalenderdaten in einen lokalen oder einen System-std::chrono::time_point
umwandeln. Ich verwende std::chrono::sys_days
in meinem Beispiel. std::chrono::sys_days
basiert auf std::chrono::system_clock
.
// sysDays.cpp
#include <chrono>
#include <iostream>
int main() {
std::cout << '\n';
using std::chrono::last;
using std::chrono::year;
using std::chrono::sys_days;
using std::chrono::March;
using std::chrono::February;
using std::chrono::Monday;
using std::chrono::Thursday;
constexpr auto yearMonthDayLast{year(2010)/March/last}; // (1)
std::cout << "sys_days(yearMonthDayLast): "
<< sys_days(yearMonthDayLast) << '\n';
constexpr auto yearMonthWeekday{year(2020)/March/Thursday[2]};
std::cout << "sys_days(yearMonthWeekday): "
<< sys_days(yearMonthWeekday) << '\n';
constexpr
auto yearMonthWeekdayLast{year(2010)/March/Monday[last]};
std::cout << "sys_days(yearMonthWeekdayLast): "
<< sys_days(yearMonthWeekdayLast) << '\n';
std::cout << '\n';
constexpr auto leapDate{year(2012)/February/last};
std::cout << "sys_days(leapDate): "
<< sys_days(leapDate) << '\n'; // (2)
constexpr auto noLeapDate{year(2013)/February/last};
std::cout << "sys_day(noLeapDate): "
<< sys_days(noLeapDate) << '\n'; // (3)
std::cout << '\n';
}
Mit der Konstante std::chrono::last
(1) kann ich schnell feststellen, wie viele Tage ein Monat hat. Die Ausgabe zeigt, dass 2012 ein Schaltjahr ist (2), aber 2013 keins.
FĂĽr ein Kalenderdatum wie year(2100)/2/29
könnte die erste Frage lauten: Ist dieses Datum gültig?
PrĂĽfen, ob ein Datum gĂĽltig ist
Die verschiedenen Kalendertypen in C++20 haben die Funktion ok
. Diese Funktion gibt true
zurĂĽck, wenn das Datum gĂĽltig ist.
// leapYear.cpp
#include <chrono>
#include <iostream>
int main() {
std::cout << std::boolalpha << '\n';
std::cout << "Valid days" << '\n'; // (1)
std::chrono::day day31(31);
std::chrono::day day32 = day31 + std::chrono::days(1);
std::cout << " day31: " << day31 << "; ";
std::cout << "day31.ok(): " << day31.ok() << '\n';
std::cout << " day32: " << day32 << "; ";
std::cout << "day32.ok(): " << day32.ok() << '\n';
std::cout << '\n';
std::cout << "Valid months" << '\n'; // (2)
std::chrono::month month1(1);
std::chrono::month month0(0);
std::cout << " month1: " << month1 << "; ";
std::cout << "month1.ok(): " << month1.ok() << '\n';
std::cout << " month0: " << month0 << "; ";
std::cout << "month0.ok(): " << month0.ok() << '\n';
std::cout << '\n';
std::cout << "Valid years" << '\n'; // (3)
std::chrono::year year2020(2020);
std::chrono::year year32768(-32768);
std::cout << " year2020: " << year2020 << "; ";
std::cout << "year2020.ok(): " << year2020.ok() << '\n';
std::cout << " year32768: " << year32768 << "; ";
std::cout << "year32768.ok(): " << year32768.ok() << '\n';
std::cout << '\n';
std::cout << "Leap Years" << '\n';
constexpr auto leapYear2016{std::chrono::year(2016)/2/29};
constexpr auto leapYear2020{std::chrono::year(2020)/2/29};
constexpr auto leapYear2024{std::chrono::year(2024)/2/29};
std::cout << " leapYear2016.ok(): "
<< leapYear2016.ok() << '\n';
std::cout << " leapYear2020.ok(): "
<< leapYear2020.ok() << '\n';
std::cout << " leapYear2024.ok(): "
<< leapYear2024.ok() << '\n';
std::cout << '\n';
std::cout << "No Leap Years" << '\n';
constexpr auto leapYear2100{std::chrono::year(2100)/2/29};
constexpr auto leapYear2200{std::chrono::year(2200)/2/29};
constexpr auto leapYear2300{std::chrono::year(2300)/2/29};
std::cout << " leapYear2100.ok(): "
<< leapYear2100.ok() << '\n';
std::cout << " leapYear2200.ok(): "
<< leapYear2200.ok() << '\n';
std::cout << " leapYear2300.ok(): "
<< leapYear2300.ok() << '\n';
std::cout << '\n';
std::cout << "Leap Years" << '\n';
constexpr auto leapYear2000{std::chrono::year(2000)/2/29};
constexpr auto leapYear2400{std::chrono::year(2400)/2/29};
constexpr auto leapYear2800{std::chrono::year(2800)/2/29};
std::cout << " leapYear2000.ok(): "
<< leapYear2000.ok() << '\n';
std::cout << " leapYear2400.ok(): "
<< leapYear2400.ok() << '\n';
std::cout << " leapYear2800.ok(): "
<< leapYear2800.ok() << '\n';
std::cout << '\n';
}
Ich prĂĽfe in dem Programm, ob ein bestimmter Tag (1), ein bestimmter Monat (2) oder ein bestimmtes Jahr (3) gĂĽltig ist. Der Bereich fĂĽr einen Tag ist [1, 31], fĂĽr einen Monat [1, 12] und fĂĽr ein Jahr [ -32767, 32767]. Folglich geben die ok()
-Aufrufe fĂĽr die entsprechenden Werte false
zurück. Zwei Fakten sind interessant, wenn ich verschiedene Werte anzeige. Erstens: Wenn der Wert ungültig ist, zeigt die Ausgabe an: “is not a valid day”, “is not a valid month”, “is not a valid year”. Zweitens werden die Werte als String angezeigt.
Der ok
-Aufruf lässt sich auf ein Kalenderdatum anwenden. Jetzt ist es ziemlich einfach zu prüfen, ob ein bestimmtes Kalenderdatum ein Schalttag und das entsprechende Jahr ein Schaltjahr ist. Im weltweit verwendeten Gregorianischen Kalender gelten die folgenden Regeln:
Jedes Jahr, das genau durch 4 teilbar ist, ist ein Schaltjahr.
- Mit Ausnahme der Jahre, die genau durch 100 teilbar sind. Sie sind keine Schaltjahre.
- FĂĽr die Ausnahme gilt wiederum die Ausnahme, dass die Jahre, die genau durch 400 teilbar sind, doch Schaltjahre sind.
Zu kompliziert? Das Programm leapYears.cpp
veranschaulicht diese Regel.
Wie geht's weiter?
Die erweiterte Chrono-Bibliothek macht es relativ einfach, die Zeitdauer zwischen Kalenderdaten abzufragen. (rme)