C++ 20 chrono: How to compare time_point with month_day?

Viewed 1074

Is there a modern and elegant way to determine if the month and day in a time_point variable match a given month_day variable?

For example, I want to know if today is Christmas. I have the following code:

#include <chrono>

bool IsTodayChristmas()
{
    using namespace std::chrono;

    constexpr month_day Christmas = {December / 25};
    auto Now = system_clock::now();

    // return Now == Christmas; // How to?
}

Modern and elegant: I mean if possible, I would prefer not to use old C types (something like std::time_t and std::tm) and string comparisons (something like std::put_time).

Any help would be appreciated.

1 Answers

You can convert system_clock::now() to a std::chrono::year_month_day type via a std::chrono::sys_days. In practice this might look something like

#include <chrono>

bool IsTodayChristmas() {
    using namespace std::chrono;

    constexpr month_day Christmas = {December / 25};
    auto Now = year_month_day{floor<days>(system_clock::now())};

    // either
    return Now == Christmas / Now.year();
    // or
    return Now.month() / Now.day() == Christmas;
}

As Howard Hinnant pointed out, this will determine Christmas in UTC. You're more likely to be after Christmas in the local time zone: to do so, we must first transform Now into our local time zone: (Note std::chrono::current_zone is not yet provided by libstdc++ or libc++, as far as I can tell.)

bool IsTodayChristmas() {
    using namespace std::chrono;

    constexpr month_day Christmas = {December / 25};
    auto Now_local = current_zone()->to_local(system_clock::now());
    auto Today = year_month_day{floor<days>(Now_local)};

    return Today == Christmas / Today.year();
}
Related