Calendar and Time-Zones in C++20: Calendar Dates

Contents[Show]

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.

 

TimelineCpp20CoreLanguage

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 which 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.

calendar1

calendar2

 

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). In order not to overwhelm you, I delay 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 obvious 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} or year_month_day_last(2010_y, month_day_last(month(3))
  • Line (4): the second Thursday of March 2020: {year(2020)/March/Thursday[2]} or year_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 and use them as basic building blocks for fully specified calendar dates, such as the lines (3) to (4).

Before I dive more into the details, here is the output of the program.

calendarDate

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 when you use the cute syntax.

  1. year/month/day
  2. day/month/year
  3. 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 anymore, 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.

cuteSyntaxI 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 easily determine who many days a month has. Consequently, the output shows it that 2012 is a leap year but not 2013.

sysDays

What's next?

Working with calendar dates becomes really powerful when you check if a calendar date is valid or when you add a time duration to it.

 

Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, Marko, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Darshan Mody, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, espkk, Wolfgang Gärtner,  Louis St-Amour, Stephan Roslen, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Avi Kohn, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Neil Wang, Friedrich Huber, Sudhakar Balagurusamy, lennonli, and Pramod Tikare Muralidhara.

 

Thanks in particular to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, and Dendi Suhubdy

 

Seminars

I'm happy to give online-seminars or face-to-face seminars world-wide. Please call me if you have any questions.

Bookable (Online)

Deutsch

English

Standard Seminars 

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.

New

Contact Me

Modernes C++,

RainerGrimmSmall

Tags: time

My Newest E-Books

Course: Modern C++ Concurrency in Practice

Course: C++ Standard Library including C++14 & C++17

Course: Embedded Programming with Modern C++

Course: Generic Programming (Templates)

Course: C++ Fundamentals for Professionals

Subscribe to the newsletter (+ pdf bundle)

Blog archive

Source Code

Visitors

Today 1333

Yesterday 5441

Week 44863

Month 203294

All 5072608

Currently are 113 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments