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_days conversion.

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());
}

See @Compiler Explorer

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

See @Compiler Explorer

What happens here:

  • jan31 + months{1} is 2025-02-31 (invalid, but allowed)
  • Converting to sys_days forces 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

See @Compiler Explorer

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

See @Compiler Explorer

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);
}

See @Compiler Explorer

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  

Back to you

  • Do you use std::chrono for calendar computations?
  • What use cases are most important to you for a calendar-type library?