Last Update:
7 Practical std::chrono Calendar Examples (C++20)
Table of Contents
This article collects small, self-contained, and practical examples for working with std::chrono calendar types.
The previous blog post - see Exploring C++20 std::chrono - Calendar Types - C++ Stories - focused on the building blocks: calendar types, operators, and arithmetic rules. In this post, we’ll focus on practical examples like:
- What’s the last business day of the month?
- When is the third Friday in June?
- How many days since the start of the year?
- What happens when I add a month to January 31?
- And a few more
Let’s start.
1. Which day of the year is that?
Let’s begin with a simple example of counting how many days a specific date is from the start of the year. In the previous article, we covered basic arithmetic, so now we can apply that knowledge to calculate the difference between a given date and the beginning of the year.
See below:
#include <chrono>
#include <print>
using namespace std::chrono;
constexpr std::string_view ordinal_suffix(const days& d) {
const auto n = d.count();
const auto last_two = n % 100;
if (last_two >= 11 && last_two <= 13)
return "th";
switch (n % 10) {
case 1: return "st";
case 2: return "nd";
case 3: return "rd";
default: return "th";
}
}
void print_day_of_year(year_month_day ymd) {
const sys_days start_of_year{ ymd.year() / January / 1 };
const sys_days current{ ymd };
const days day_index = (current - start_of_year) + days{1};
std::print("{} is the {}{} day of the year\n",
ymd,
day_index.count(),
ordinal_suffix(day_index));
}
int main() {
print_day_of_year(2025y / January / 2);
print_day_of_year(2025y / November / 11);
}
Run here @Compiler Explorer
A few small details worth noticing:
- The arithmetic is done entirely in
sys_days. - The result is one-based (January 1 is day 1), which is usually what people expect.
- Leap years fall out naturally from the
sys_daysconversion.
2. Nth weekday of a month
If you want to check the date of the third Friday in a given month:
#include <chrono>
#include <print>
int main() {
using namespace std::chrono;
using namespace std::literals;
auto thirdFriday = 2026y / June / Friday[3];
std::print("Third Friday of {:%B %Y}: {}\n", thirdFriday,
sys_days{thirdFriday});
}
Run at Compiler Explorer
The type of thirdFriday is year_month_weekday, and if we want to show it as a full date, we can convert it to sys_days.
3. Last day of the month
End-of-month logic sounds simple, but it can be painful to implement. With year_month_day_last it’s now super simple:
#include <chrono>
#include <print>
int main() {
using namespace std::chrono;
year_month_day_last endOfFeb2025 =
year{2025} / February / last;
year_month_day_last endOfFeb2024 =
year{2024} / February / last;
std::print("{}\n", sys_days{endOfFeb2025});
std::print("{}\n", sys_days{endOfFeb2024});
}
See at Compiler Explorer
Output:
2025-02-28
2024-02-29
Again, we need to convert to sys_days to print the date; otherwise, you will see something like 2025/Feb/last.
4. Computing “last” dates for the whole year
We previously computed the n-th weekday, but how can we determine the last weekday of a month? This is useful for payrolls, meetings, and similar purposes.
The nice part is that this is exactly what weekday[last] is for:
#include <chrono>
#include <print>
int main() {
using namespace std::chrono;
const auto y = 2026y;
for (unsigned m = 1; m <= 12; ++m) {
auto lastFriday = y / m / Friday[last];
sys_days date = sys_days{lastFriday};
std::print("{:%B %Y}: last Friday is {:%F}\n", date, date);
}
}
Example output (shape):
January 2026: last Friday is 2026-01-30
February 2026: last Friday is 2026-02-27
...
December 2026: last Friday is 2026-12-25
Warning: The loop for (month m = January; m <= December; ++m) will not work as intended. It creates an infinite loop because ++m uses modulo arithmetic, which wraps it back to January.
5. Adding months
Month arithmetic in <chrono> is field-based, not duration-based. That distinction matters, especially once you involve sys_days.
#include <chrono>
#include <print>
int main() {
using namespace std::chrono;
year_month_day jan31{ year{2025} / January / 31 };
auto feb = jan31 + months{1};
std::print("Jan 31 + 1 month = {}, ok: {}\n",
feb, feb.ok());
}
Output:
Jan 31 + 1 month = 2025-02-31 is not a valid date, ok: false
This is intentional. Adding months to a year_month_day preserves the day field, even if the result is not a valid civil date. The library does not clamp or normalize automatically.
How to clamp the result and get the correct date?
If you first perform calendar arithmetic and then convert to sys_days, overflow is normalized into the following month:
auto normalized = sys_days{ jan31 + months{1} };
std::print("Normalized via sys_days: {}\n",
year_month_day{normalized});
Output:
Normalized via sys_days: 2025-03-03
What happens here:
jan31 + months{1}is2025-02-31(invalid, but allowed)- Converting to
sys_daysforces normalization - February 2025 has 28 days
- February 31 overflows by 3 days so we get March 3
You can also try a different “order”:
auto durationBased = sys_days{jan31} + months{1};
std::print("Duration-based result: {}\n", durationBased);
Typical output (libstdc++):
2025-03-02 10:29:06
Here, months{1} is treated as an average month duration (30 days, 10 hours, 29 minutes, 6 seconds).
6. Next business day
A very common rule in finance is “move to the next business day”. Settlement dates, payment processing, and reporting cutoffs often use this exact logic, at least as a baseline.
For now, we’ll define a business day as Monday to Friday, skipping weekends. Holidays can be layered on later without changing the structure of the code.
#include <chrono>
#include <print>
using namespace std::chrono;
sys_days next_business_day(sys_days d) {
while (true) {
d += days{1};
weekday wd{d};
if (wd != Saturday && wd != Sunday)
return d;
}
}
int main() {
sys_days tradeDate = sys_days{ year{2025}/November/21 };
auto settlement = next_business_day(tradeDate);
std::print("Trade date: {}\n", year_month_day{tradeDate});
std::print("Next business day: {}\n", year_month_day{settlement});
sys_days tuesday = sys_days{ year{2025}/November/18 };
std::print("Next business day after {} is {}\n",
year_month_day{tuesday},
year_month_day{next_business_day(tuesday)});
}
Output:
Trade date: 2025-11-21
Next business day: 2025-11-24
Next business day after 2025-11-18 is 2025-11-19
7. Count Fridays in a month
As a last example, let’s count how many Fridays do we have a in a given month:
#include <chrono>
#include <print>
using namespace std::chrono;
int count_weekday_in_month_simple(year_month ym, weekday target) {
sys_days d = sys_days{ ym / day{1} };
int count = 0;
while (year_month_day{d}.month() == ym.month()) {
if (weekday{d} == target)
++count;
d += days{1};
}
return count;
}
unsigned count_weekday_in_month(year_month ym, weekday wd) {
unsigned count = 0;
for (unsigned i = 1; ; ++i) {
const year_month_weekday ymwd = ym / wd[i];
if (!ymwd.ok())
break;
const year_month_day ymd{ ymwd };
if (ymd.ok())
++count;
}
return count;
}
int main() {
auto ym = year{2025} / May;
int fridays = count_weekday_in_month(ym, Friday);
std::print("Fridays in {}: {}\n", ym, fridays);
int mondays = count_weekday_in_month(ym, Monday);
std::print("Mondays in {}: {}\n", ym, mondays);
}
The code has two versions:
- The simple version iterates day by day and might not be optimal. You can theoretically speed it up by increasing by 7 days…
- But in the second version, we can iterate using weekdays.
Summary
In this article we covered a set of small, practical examples built on top of the C++20 <chrono> calendar types The examples showed how to count days within a year, resolve n-th and last weekdays of a month, handle end-of-month and month-addition edge cases, distinguish between calendar and duration arithmetic, and express simple business rules such as “next business day” or counting specific weekdays in a month.
In most cases, we have the same pattern: calendar types are used to express structure and intent, while sys_days is used when actual day counting, iteration, or normalization is required.
Documents and Resources
- C++ Standard Draft - Time section - N4868 (October 2020 pre-virtual-plenary working draft/C++20 plus editorial changes)
- C++20 - The Complete Guide by Nicolai M. Josuttis @Amazon
- Modern C++ Programming Cookbook: Master C++ core language and standard library features, with over 100 recipes, updated to C++20 2nd ed. Edition @Amazon
- https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes - examples and recipes for Howard Hinnant’s
tz.hlibrary, which is a base for chrono.
Back to you
- Do you use
std::chronofor calendar computations? - What use cases are most important to you for a calendar-type library?
I've prepared a valuable bonus for you!
Learn all major features of recent C++ Standards on my Reference Cards!
Check it out here:
