Welcome to a fascinating journey through time with C++20's std::chrono library! In this lesson, we'll learn how to create a calendar using std::chrono that will help you work with dates and times in your C++ projects.
std::chrono is a powerful library introduced in C++11, which allows you to work with time values directly in your code. In C++20, it has been further enhanced to make it even more versatile.
This lesson will focus on the calendar functionality of std::chrono, which allows you to work with dates and times in a more user-friendly manner.
Before we dive into the calendar, let's quickly review two fundamental concepts in std::chrono: Time Points and Durations.
Time Points represent an instant in time. They are instances that can be added or subtracted from other Time Points to calculate the duration between them.
#include <iostream>
#include <chrono>
int main() {
// Create a Time Point representing Jan 1, 2000
auto jan1_2000 = std::chrono::system_clock::from_time_t(std::time_t(946684800));
std::cout << "Time Point: " << jan1_2000 << '\n';
return 0;
}In the code above, we use std::chrono::system_clock::from_time_t() to convert a std::time_t value (which represents a UNIX timestamp) into a Time Point. The UNIX timestamp for Jan 1, 2000 is 946684800.
Durations represent the difference between two Time Points, or the amount of time elapsed between two points in time.
#include <iostream>
#include <chrono>
int main() {
// Create Time Points representing Jan 1, 2000 and Jan 15, 2000
auto jan1_2000 = std::chrono::system_clock::from_time_t(std::time_t(946684800));
auto jan15_2000 = jan1_2000 + std::chrono::days(14);
// Calculate the duration between the two dates
auto duration = jan15_2000 - jan1_2000;
// Print the duration
std::cout << "Duration: " << duration.days() << " days, "
<< duration.seconds() << " seconds\n";
return 0;
}In this example, we create two Time Points for Jan 1 and Jan 15, 2000, and calculate the duration between them.
Now that we understand Time Points and Durations, let's explore how to use them to create a simple calendar.
To create a Date, we'll use the std::chrono::year_t, std::chrono::month_t, std::chrono::day_t, std::chrono::hour_t, std::chrono::minute_t, and std::chrono::second_t types.
#include <iostream>
#include <chrono>
int main() {
// Define the date components
std::chrono::year_t year = 2023;
std::chrono::month_t month = 2;
std::chrono::day_t day = 14;
std::chrono::hour_t hour = 12;
std::chrono::minute_t min = 0;
std::chrono::second_t sec = 0;
// Create a Time Point for the date and time
auto date_time = std::chrono::make_time_t({year, month, day, hour, min, sec});
std::cout << "Date and Time: " << std::ctime(&date_time);
return 0;
}In the example above, we create a Date using the std::chrono::make_time_t() function, which takes a tm-like structure as its argument. We set the year, month, day, hour, minute, and second components of the tm structure.
To calculate the number of days in a month, we can create a helper function that uses the Gregorian calendar formula.
#include <iostream>
#include <chrono>
std::chrono::days days_in_month(std::chrono::year_t year, std::chrono::month_t month) {
std::chrono::month_t months[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (month == 2 && is_leap_year(year)) {
months[1] = 29;
}
return months[month - 1];
}
bool is_leap_year(std::chrono::year_t year) {
return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}In the code above, we define two helper functions, days_in_month() and is_leap_year(). The days_in_month() function returns the number of days in the specified month, taking into account whether the year is a leap year or not. The is_leap_year() function checks whether the given year is a leap year according to the Gregorian calendar rules.
Now let's put everything together to create a simple calendar.
#include <iostream>
#include <chrono>
#include <vector>
#include <string>
std::chrono::days days_in_month(std::chrono::year_t year, std::chrono::month_t month);
bool is_leap_year(std::chrono::year_t year);
int main() {
// Define the date components
std::chrono::year_t year = 2023;
std::chrono::month_t month = 2;
// Get the number of days in the month
std::chrono::days days_in_month_val = days_in_month(year, month);
std::chrono::days days_in_month = std::chrono::duration_cast<std::chrono::days>(days_in_month_val);
// Create a Time Point for the first day of the month
auto first_day = std::chrono::system_clock::from_time_t(std::time_t(std::mktime({year, month - 1, 1, 0, 0, 0})));
// Calculate the duration between the first day and the last day of the month
auto last_day = first_day + days_in_month;
// Print the header of the calendar
std::cout << "Month: " << month << "/" << year << '\n';
std::cout << "-------------------------------\n";
// Print the days of the week
std::vector<std::string> days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
for (auto day : days) {
std::cout << day << " ";
}
std::cout << '\n';
// Print the days of the month
auto day_of_week = std::chrono::weekday(first_day);
for (std::chrono::days day(first_day); day <= last_day; ++day) {
std::cout << std::setw(2) << std::chrono::duration_cast<std::chrono::days>(day - first_day).count() << " ";
if (std::chrono::weekday(day) != day_of_week) {
std::cout << "\n";
day_of_week = std::chrono::weekday(day);
}
}
std::cout << '\n';
return 0;
}In this example, we create a simple calendar for the specified month and year. The calendar displays the days of the week and the days of the month, with the first day of the week aligned properly.
What type represents an instant in time in `std::chrono`?
That's it for our introduction to C++20's std::chrono calendar! With these concepts, you can now work with dates and times in your C++ projects in a flexible and efficient manner. Happy coding! š