Calendar and Time-Zones in C++20: Calendar Dates
A new type of the chrono extension in C++20 is a calendar date. C++20 offers various ways to create a calendar date and interact with them.
It took me a while to understand the almost twenty calendar-related data types. For that reason, I start with a calendar date. As in my last post, “Calendar and Time-Zones in C++20: Time of Day “, I use the date library from Howard Hinnant as the prototype of the new chrono extension.
Calendar Date
A calendar date is a date that consists of a year, a month, and a day. Consequently, C++20 has a specific data type std::chrono::year_month_day
. C++20 has way more to offer. Both tables present the first overview.
Modernes C++ Mentoring
Do you want to stay informed: Subscribe.
Let’s start simple. The following program createCalendar.cpp
shows various ways to create calendar-related dates.
// createCalendar.cpp #include <iostream> #include "date.h" int main() { std::cout << std::endl; using namespace date; constexpr auto yearMonthDay{year(1940)/month(6)/day(26)}; // (1) std::cout << yearMonthDay << " "; std::cout << date::year_month_day(1940_y, June, 26_d) << std::endl; // (2) std::cout << std::endl; constexpr auto yearMonthDayLast{year(2010)/March/last}; // (3) std::cout << yearMonthDayLast << " "; std::cout << date::year_month_day_last(2010_y, month_day_last(month(3))) << std::endl; constexpr auto yearMonthWeekday{year(2020)/March/Thursday[2]}; // (4) std::cout << yearMonthWeekday << " "; std::cout << date::year_month_weekday(2020_y, month(March), Thursday[2]) << std::endl; constexpr auto yearMonthWeekdayLast{year(2010)/March/Monday[last]}; // (5) std::cout << yearMonthWeekdayLast << " "; std::cout << date::year_month_weekday_last(2010_y, month(March), weekday_last(Monday)) << std::endl; std::cout << std::endl; constexpr auto day_{day(19)}; // (5) std::cout << day_ << " "; std::cout << date::day(19) << std::endl; constexpr auto month_{month(1)}; // (6) std::cout << month_ << " "; std::cout << date::month(1) << std::endl; constexpr auto year_{year(1988)}; // (7) std::cout << year_ << " "; std::cout << date::year(1988) << std::endl; constexpr auto weekday_{weekday(5)}; std::cout << weekday_ << " "; std::cout << date::weekday(5) << std::endl; constexpr auto yearMonth{year(1988)/1}; std::cout << yearMonth << " "; std::cout << date::year_month(year(1988), January) << std::endl; constexpr auto monthDay{10/day(22)}; std::cout << monthDay << " "; std::cout << date::month_day(October, day(22)) << std::endl; constexpr auto monthDayLast{June/last}; std::cout << monthDayLast << " "; std::cout << date::month_day_last(month(6)) << std::endl; constexpr auto monthWeekday{2/Monday[3]}; std::cout << monthWeekday << " "; std::cout << date::month_weekday(February, Monday[3]) << std::endl; constexpr auto monthWeekDayLast{June/Sunday[last]}; std::cout << monthWeekDayLast << " "; std::cout << date::month_weekday_last(June, weekday_last(Sunday)) << std::endl; std::cout << std::endl; }
There are essentially two ways to create a calendar date. You can use the so-called cute syntax yearMonthDay{year(1940)/month(6)/day(26)}
(line 1), or you can use the explicit type date::year_month_day(1940_y, June, 26_d)
(line 2). To not overwhelm you, I am delaying my explanation of the cute syntax to the next section of this post. The explicit type is quite interesting because it uses the date time literals 1940_y, 26_d, and the predefined constant June
. With C++20, the date literals 1940_y
and 26_d
are written without an underscore: 1940y
and 26d
. This was the prominent part.
Line (3), line (4), and line (5) offer convenient ways to create calendar dates.
- Line (3): the last day of March 2010:
{year(2010)/March/last}
oryear_month_day_last(2010_y, month_day_last(month(3))
- Line (4): the second Thursday of March 2020:
{year(2020)/March/Thursday[2]}
oryear_month_weekday(2020_y, month(March), Thursday[2])
- Line (5): the last Monday of March 2010: {year(2010)/March/Monday[last]} or
year_month_weekday_last(2010_y, month(March), weekday_last(Monday))
The remaining calendar types stand for a day (line 6), a month (line 7), or a year (line 8). You can combine them as basic building blocks for fully specified calendar dates, such as lines (3) to (4).
Before I dive more into the details, here is the program’s output.
As promised, let me write about the cute syntax.
Cute Syntax
The cute syntax consists of overloaded division operators to specify a calendar date. The overloaded operators support time literals (e.g.: 2020_y, 31_d
) and constants (January, February, March, April, May, June, July, August, September, October, November, December
).
The following three combinations of year, month, and day are possible using the cute syntax.
- year/month/day
- day/month/year
- month/day/year
These combinations are not arbitrarily chosen because they are the used ones worldwide. Each other combination is not allowed
Consequently, when you choose the type year, month, or day for the first argument, the type for the remaining two arguments is no longer necessary, and an integral would do the job.
// cuteSyntax.cpp #include <iostream> #include "date.h" int main() { std::cout << std::endl; using namespace date; constexpr auto yearMonthDay{year(1966)/6/26}; std::cout << yearMonthDay << std::endl; constexpr auto dayMonthYear{day(26)/6/1966}; std::cout << dayMonthYear << std::endl; constexpr auto monthDayYear{month(6)/26/1966}; std::cout << monthDayYear << std::endl; constexpr auto yearDayMonth{year(1966)/month(26)/6}; //(1) std::cout << yearDayMonth << std::endl; std::cout << std::endl; }
The combination year/day/month (line 1) is not allowed and causes a run-time message.
I assume you want to display a calendar date {year(2010)/March/last}
in a readable form, such as 2020-03-31. This is a job for the local_days
or sys_days
operator.
Displaying Calendar Dates
Thanks to std::chrono::local_days
or std::chrono::sys_days
, you can convert calendar dates to a std::chrono::time_point
representing the same date as this year_month_day.
I use std::chrono::sys_days
in my example. std::chrono::sys_days
is based on std::chrono::system_clock
. Let me convert the calendar dates (line (3) – line (5) from the previous program createCalendar.cpp.
// sysDays.cpp #include <iostream> #include "date.h" int main() { std::cout << std::endl; using namespace date; constexpr auto yearMonthDayLast{year(2010)/March/last}; std::cout << "sys_days(yearMonthDayLast): " << sys_days(yearMonthDayLast) << std::endl; constexpr auto yearMonthWeekday{year(2020)/March/Thursday[2]}; std::cout << "sys_days(yearMonthWeekday): " << sys_days(yearMonthWeekday) << std::endl; constexpr auto yearMonthWeekdayLast{year(2010)/March/Monday[last]}; std::cout << "sys_days(yearMonthWeekdayLast): " << sys_days(yearMonthWeekdayLast) << std::endl; std::cout << std::endl; constexpr auto leapDate{year(2012)/February/last}; // (1) std::cout << "sys_days(leapDate): " << sys_days(leapDate) << std::endl; constexpr auto noLeapDate{year(2013)/February/last}; // (2) std::cout << "sys_day(noLeapDate): " << sys_days(noLeapDate) << std::endl; std::cout << std::endl; }
The std::chrono::last
constant let me quickly determine how many days a month has. Consequently, the output shows that 2012 is a leap year but not 2013.
What’s next?
Working with calendar dates becomes powerful when you check if a calendar date is valid or when you add a time duration.
Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Stephen Kelley, Kyle Dean, Tusar Palauri, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, Ann Shatoff, Rob North, Bhavith C Achar, Marco Parri Empoli, Philipp Lenk, Charles-Jianye Chen, Keith Jeffery,and Matt Godbolt.
Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, Slavko Radman, and David Poole.
My special thanks to Embarcadero | |
My special thanks to PVS-Studio | |
My special thanks to Tipi.build | |
My special thanks to Take Up Code | |
My special thanks to SHAVEDYAKS |
Seminars
I’m happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.
Standard Seminars (English/German)
Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.
- C++ – The Core Language
- C++ – The Standard Library
- C++ – Compact
- C++11 and C++14
- Concurrency with Modern C++
- Design Pattern and Architectural Pattern with C++
- Embedded Programming with Modern C++
- Generic Programming (Templates) with C++
- Clean Code with Modern C++
- C++20
Contact Me
- Mobil: +49 176 5506 5086
- Mail: schulung@ModernesCpp.de
- German Seminar Page: www.ModernesCpp.de
- Mentoring Page: www.ModernesCpp.org
Modernes C++ Mentoring,
Leave a Reply
Want to join the discussion?Feel free to contribute!