Calendars and Time Zones
Overview
C++20 significantly expands <chrono>, adding calendar types (year, month, day, and their combinations) and time zone support (time_zone, zoned_time). Types are type-safe and integrate seamlessly with existing time_point / duration.
Calendar Types
cpp
#include <chrono>
using namespace std::chrono;
year y{2024};
month m{6};
day d{15};
day{32}.ok(); // false
year next_y = y + years{1}; // 2025
month next_m = m + months{3}; // September
day tomorrow = d + days{1}; // 16year_month_day
cpp
using namespace std::chrono;
year_month_day ymd{year{2024}, month{6}, day{15}};
ymd.ok(); // true
ymd.year(); // 2024
ymd.month(); // June
ymd.day(); // 15
year_month_day bad{year{2024}, month{2}, day{30}};
bad.ok(); // falseOther Calendar Types
cpp
using namespace std::chrono;
year{2024} / month{2} / last; // Feb 29
year{2024} / month{6} / weekday{0}[2]; // 2nd Sunday
(year{2024} / February / last).day(); // 29sys_days Conversion
sys_days is a day-precision time_point connecting calendars and time points.
cpp
using namespace std::chrono;
year_month_day ymd{year{2024}, month{1}, day{1}};
sys_days sd = ymd; // calendar → time_point
year_month_day back{sd}; // time_point → calendar
days diff = sys_days{year{2024}/12/25} - sys_days{year{2024}/1/1};
// diff.count() == 359
weekday wd = weekday{sys_days{ymd}}; // day of the week/ Operator for Date Construction
cpp
using namespace std::chrono;
auto d1 = year{2024} / 6 / 15; // year_month_day
auto d2 = 2024y / June / 15d; // same as above
auto d3 = 2024y / February / last; // last day of February
auto d4 = June / 15d; // month_dayTime Zone Support
Getting Time Zones
cpp
#include <chrono>
using namespace std::chrono;
const time_zone* tz = current_zone(); // e.g., "Asia/Shanghai"
const time_zone* sh = locate_zone("Asia/Shanghai");
const time_zone* ny = locate_zone("America/New_York");zoned_time and make_zoned
cpp
using namespace std::chrono;
auto now = system_clock::now();
zoned_time sh_t{locate_zone("Asia/Shanghai"), now};
zoned_time ny_t{locate_zone("America/New_York"), now};
// Create from date-time
auto zt = make_zoned("Europe/London",
local_days{2024y / July / 4} + hours{15} + minutes{30});
// Time zone conversion
auto eastern = make_zoned("America/New_York", zt);Conversion Example
cpp
using namespace std::chrono;
// Beijing 9 AM → New York time
auto bj9 = make_zoned("Asia/Shanghai",
local_days{2024y / 1 / 15} + hours{9});
auto nyc = make_zoned("America/New_York", bj9);
// Beijing 09:00 = New York previous day 20:00 (winter time, UTC-5)Leap Second Support
cpp
using namespace std::chrono;
auto lsi = get_leap_second_info(system_clock::now());
lsi.elapsed; // accumulated leap seconds
lsi.is_leap_second; // whether the current second is a leap secondFormatting
cpp
#include <chrono>
#include <format>
using namespace std::chrono;
auto dp = floor<days>(system_clock::now());
year_month_day ymd{dp};
hh_mm_ss hms{floor<seconds>(system_clock::now() - dp)};
std::format("{}/{}/{:02d} {:02d}:{:02d}:{:02d}",
int(ymd.year()), unsigned(ymd.month()), unsigned(ymd.day()),
hms.hours().count(), hms.minutes().count(), hms.seconds().count());Migrating from Legacy APIs
cpp
// C++17
std::time_t t = std::time(nullptr);
int year = std::localtime(&t)->tm_year + 1900;
// C++20
using namespace std::chrono;
year_month_day ymd{floor<days>(system_clock::now())};
auto y = int(ymd.year());
auto m = unsigned(ymd.month()); // directly 1-12Common Pitfalls
cpp
// Invalid dates are not automatically corrected
year{2023} / month{2} / day{29}; // ok() == false (not a leap year)
// locate_zone throws on failure
try { locate_zone("Invalid/Zone"); }
catch (const std::runtime_error&) { }
// Leap year check
year{2024}.is_leap(); // trueSummary
- Type-safe calendars:
year,month,day, and their combinations. sys_daysis the bridge between calendars andtime_point.zoned_time+time_zoneprovide full time zone support.- The
/operator simplifies date construction;make_zonedsimplifies time zone creation.