Calendar and Time-Zones in C++20: Time of Day
With C++20, the chrono library from C++11 receives essential additions. The most prominent ones are calendar and time-zones support. But this is by far not all. C++20 gets new clocks, powerful formatting functionality for time durations, and a time-of-day type.
Before I dive into the extended chrono library, particularly in this post, into the new type std::chrono::time_of_day, I have to make a few remarks. In short, I call all date and time utilities provided by chrono the time library.
The time library in C++11
A basic understanding of the Chrono library is essential to get the most out of this post. C++11 introduced three main components to deal with time:
- A time point is defined by a starting point, the so-called epoch, and additional time duration.
- A time duration is the difference between two time points. It is given by the number of ticks.
- A clock consists of a starting point (epoch) and a tick so that the current time point can be calculated.
Honestly, time is for me a mysterium. On the one hand, each of us has an intuitive idea of time; conversely, defining it formally is exceptionally challenging. For example, the three components, time point, time duration, and clock depend on each other. If you want to know more about the time functionality in C++11, read my previous posts: time.
The chrono
Extensions in C++20
C++20 adds new components to the chrono library:
- The time of day is the duration since midnight, split into hours, minutes, seconds, and fractional seconds.
- Calendar stands for various calendar dates such as a year, a month, a weekday, or the nth day of a week.
- A time zone represents a time specific to a geographic area.
Essentially, the time-zone functionality (C++20) is based on the calendar functionality (C++20), and the calendar functionality (C++20) is based on the original chrono functionality (C++11).
But that is not all. The extension includes new clocks. Thanks to the formatting library in C++20, time durations can be read or written.
Modernes C++ Mentoring
Do you want to stay informed: Subscribe.
The date
Prototype Library
While writing this post, no C++ compiler supports the chrono extensions in C++20 so far. Thanks to the prototype library date from Howard Hinnant, essentially a superset of the extended time functionality in C++20, I can experiment with it. The library is hosted on GitHub. There are various ways to use the date prototype:
- You can try it out on Wandbox. Howard has uploaded the
date.h
header sufficient to play with the new typestd::time_of_day
and the calendar. Here is Howard’s link: Try it out on wandbox! - Copy the header
date.h
into the search path of your C++ compiler. - Download the project and build it. The already mentioned GitHub page date gives you more information.
I made my first steps with the online compiler Wandbox but switched to strategy 2.
Required C++ standard
In general, a C++14 compiler is sufficient to use the date library. There is one exception to this rule which I experienced with the following call:
auto timeOfDay = date::time_of_day(10.h + 98min + 2020s + 0.5s); // C++20 auto timeOfDay = date::hh_mm_ss(10.h + 98min + 2020s + 0.5s); // C++17
I used in my first tries the first call. The first line requires class template argument deduction for alias templates. time_of_day
is an alias for hh_mm_ss: using time_of_day_day = hh_mm_ss<Duration>.
When you now replace the alias with the class template such as in the second line (C++17), you need a C++17. Class template argument deduction is a C++17.
Read more details about class template argument deduction here: C++17: What’s new in the Core Language?
Issue Solved
With C++20 time_of_day
was renamed to hh_mm_ss.
Howard Hinnant, the creator of the date library and designer of the chrono addition, gave me a crucial hint: “Prefer to use hh_mm_ss
in place of time_of_day
. time_of_day
got renamed to hh_mm_ss
during the standardization process for C++20, and so time_of_day
remains strictly as a backwards-compatible shim for current and past users of this lib.“
This is typical Odysses you have when you are an early adopter.
Porting to C++20
When you only use the content of the date prototype that is part of C++20, porting it to C++ 20 is no big deal. Replace the date header files with the header file <chrono>
and the namespace date
with the namespace std::chrono
:
#include "date.h" //#include <chrono> int main() {
using namespace std::chrono_literals; auto am = date::is_am(10h); // auto am = std::chrono::is_am(10h); }
Now, I write about the chrono extensions in C++20.
Time of Day
std::chrono::hh_mm_ss
is the duration since midnight split into hours, minutes, seconds, and fractional seconds. This type is typically used as a formatting tool. First, the following table gives you a concise overview of std::chrono::hh_mm_ss
instance tOfDay.
The following program uses the functions:
// timeOfDay.cpp #include "date.h" #include <iostream> int main() { using namespace date; // (3) using namespace std::chrono_literals; std::cout << std::boolalpha << std::endl; auto timeOfDay = date::hh_mm_ss(10.5h + 98min + 2020s + 0.5s); // (1) std::cout<< "timeOfDay: " << timeOfDay << std::endl; // (2) std::cout << std::endl; std::cout << "timeOfDay.hours(): " << timeOfDay.hours() << std::endl; // (4) std::cout << "timeOfDay.minutes(): " << timeOfDay.minutes() << std::endl; // (4) std::cout << "timeOfDay.seconds(): " << timeOfDay.seconds() << std::endl; // (4) std::cout << "timeOfDay.subseconds(): " << timeOfDay.subseconds() << std::endl; // (4) std::cout << "timeOfDay.to_duration(): " << timeOfDay.to_duration() << std::endl; // (5) std::cout << std::endl; std::cout << "date::hh_mm_ss(45700.5s): " << date::hh_mm_ss(45700.5s) << '\n'; // (6) std::cout << std::endl; std::cout << "date::is_am(5h): " << date::is_am(5h) << std::endl; // (7) std::cout << "date::is_am(15h): " << date::is_am(15h) << std::endl; // (7) std::cout << std::endl; std::cout << "date::make12(5h): " << date::make12(5h) << std::endl; // (7) std::cout << "date::make12(15h): " << date::make12(15h) << std::endl; // (7) }
In line (1), I create a new instance of std::chrono::hh_mm_ss: timeOfDay
. Thanks to the chrono literals from C++14, I can add a few time durations to initialize a time-of-day object. With C++20, you can directly output timeOfDay
(line 2). This is the reason I have to introduce the namespace date
in line 3. The rest should be straightforward to read. Lines (4) display the components of the time since midnight in hours, minutes, seconds, and fractional seconds. Line (5) returns the time duration since midnight in seconds. Line (6) is more interesting: the given seconds correspond to the time displayed in line (2). Line (7) returns if the given hour is a.m. Line (8) finally returns the 12-hour equivalent of the given hour.
Thanks to the date library, here is the output of the program:
What’s next?
My next post presents the next component of the extended chrono library: the calendar.
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, Matt Godbolt, and Honey Sukesan.
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 |
Modernes C++ GmbH
Modernes C++ Mentoring (English)
Rainer Grimm
Yalovastraße 20
72108 Rottenburg
Mail: schulung@ModernesCpp.de
Mentoring: www.ModernesCpp.org
Modernes C++ Mentoring,
Leave a Reply
Want to join the discussion?Feel free to contribute!