Zeit in C++20: Kalendertermine darstellen und prüfen
![](https://heise.cloudimg.io/width/700/q75.png-lossy-75.webp-lossy-75.foil1/_www-heise-de_/imgs/18/4/5/7/2/3/3/9/shutterstock_1551975515-bad99eee7a7c63ef.jpeg)
(Bild: Kwangmoozaa/Shutterstock.com)
C++20 bietet neben den Funktionen zum Erstellen und Berechnen von Kalenderdaten auch Methoden, um die Daten anzuzeigen und zu überprüfen.
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 [1]
- Zeit in C++20: Einführung in die Chrono-Terminologie mit Zeitdauer und Zeitpunkt [2]
- Zeit in C++20: Neue Datentypen für die Tageszeit und das Kalenderdatum [3]
- Zeit in C++20: Kalendertermine erstellen [4]
![](https://heise.cloudimg.io/width/696/q85.png-lossy-85.webp-lossy-85.foil1/_www-heise-de_/imgs/18/4/5/7/2/3/3/9/TimelineCpp20CoreLanguage-1529a6191e572b4f.png)
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.
![](https://heise.cloudimg.io/width/696/q85.png-lossy-85.webp-lossy-85.foil1/_www-heise-de_/imgs/18/4/5/7/2/3/3/9/sysDays-7aa09a79969cc49a.png)
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.
![](https://heise.cloudimg.io/width/696/q85.png-lossy-85.webp-lossy-85.foil1/_www-heise-de_/imgs/18/4/5/7/2/3/3/9/leapYear-3cc3eb153acf5fdd.png)
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 [5]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 [6])
URL dieses Artikels:
https://www.heise.de/-9684590
Links in diesem Artikel:
[1] https://www.grimm-jaud.de/administrator/index.php?option=com_content&task=article.edit&id=608
[2] https://www.heise.de/blog/Zeit-in-C-20-Grundlegende-Chrono-Terminologie-mit-Zeitdauer-und-Zeitpunkt-9651792.html
[3] https://heise.de/-9664010
[4] https://www.heise.de/blog/Zeit-in-C-20-Kalendertermine-erstellen-9671530.html
[5] https://en.wikipedia.org/wiki/Gregorian_calendar
[6] mailto:rme@ix.de
Copyright © 2024 Heise Medien