TimelineCpp20CoreLanguage

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.

 

Rainer D 6 P2 500x500Modernes C++ Mentoring

  • "Fundamentals for C++ Professionals" (open)
  • "Design Patterns and Architectural Patterns with C++" (open)
  • "C++20: Get the Details" (open)
  • "Concurrency with Modern C++" (open)
  • "Embedded Programming with Modern C++": January 2025
  • "Generic Programming (Templates) with C++": February 2025
  • "Clean Code: Best Practices for Modern C++": May 2025
  • 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:

    1. You can try it out on Wandbox. Howard has uploaded the date.h header sufficient to play with the new type std::time_of_day and the calendar. Here is Howard’s link: Try it out on wandbox!
    2. Copy the header date.h into the search path of your C++ compiler.
    3. 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.

    timeOfDayTable2

     

    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:

    timeOfDay2

    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)

    Do you want to stay informed about my mentoring programs? Subscribe Here

    Rainer Grimm
    Yalovastraße 20
    72108 Rottenburg

    Mobil: +49 176 5506 5086
    Mail: schulung@ModernesCpp.de
    Mentoring: www.ModernesCpp.org

    Modernes C++ Mentoring,

     

     

    0 replies

    Leave a Reply

    Want to join the discussion?
    Feel free to contribute!

    Leave a Reply

    Your email address will not be published. Required fields are marked *