C++ Calendar & Timezone | year_month_day·zoned_time Complete Guide

C++ Calendar & Timezone | year_month_day·zoned_time Complete Guide

이 글의 핵심

C++20 calendar and timezone: year_month_day, zoned_time, weekday for date arithmetic, timezone conversion, and weekday calculation with practical examples.

Introduction

C++20 provides calendar and timezone in the standard library. With year_month_day, zoned_time, weekday, you can concisely implement date arithmetic, timezone conversion, and weekday calculation.

What You Will Learn

  • Represent and perform arithmetic with year_month_day
  • Convert timezones with zoned_time
  • Calculate weekdays with weekday
  • Learn commonly used date/time patterns in production

Table of Contents

  1. Basic Concepts
  2. Practical Implementation
  3. Advanced Usage
  4. Performance Comparison
  5. Real-World Cases
  6. Troubleshooting
  7. Conclusion

Basic Concepts

Main Types

TypeDescriptionExample
year_month_dayDate (year-month-day)2026y / March / 11
year_month_weekdayDate (year-month-weekday)2026y / March / Monday[1]
year_month_day_lastLast day of month2026y / February / last
zoned_timeTime with timezonezoned_time{"Asia/Seoul", now}
weekdayDay of weekMonday, Tuesday, …

Practical Implementation

1) year_month_day - Date Representation

Basic Usage

#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
    // Create date
    year_month_day ymd1 = 2026y / March / 11;
    year_month_day ymd2{year{2026}, month{3}, day{11}};
    
    std::cout << ymd1 << std::endl;  // 2026-03-11
    
    // Access elements
    auto y = ymd1.year();
    auto m = ymd1.month();
    auto d = ymd1.day();
    
    std::cout << "Year: " << y << std::endl;  // 2026
    std::cout << "Month: " << m << std::endl;  // Mar
    std::cout << "Day: " << d << std::endl;  // 11
    
    return 0;
}

Date Arithmetic

using namespace std::chrono;
int main() {
    year_month_day today = 2026y / March / 11;
    
    // 1 month later
    auto nextMonth = sys_days{today} + months{1};
    std::cout << year_month_day{nextMonth} << std::endl;  // 2026-04-11
    
    // 10 days later
    auto future = sys_days{today} + days{10};
    std::cout << year_month_day{future} << std::endl;  // 2026-03-21
    
    // 1 year ago
    auto past = sys_days{today} - years{1};
    std::cout << year_month_day{past} << std::endl;  // 2025-03-11
    
    // Date difference
    auto diff = sys_days{today} - sys_days{past};
    std::cout << "Difference: " << diff.count() << " days" << std::endl;  // 365
    
    return 0;
}

2) weekday - Weekday Calculation

Basic Usage

using namespace std::chrono;
int main() {
    year_month_day ymd = 2026y / March / 11;
    auto dp = sys_days{ymd};
    auto wd = weekday{dp};
    
    std::cout << "Weekday: " << wd << std::endl;  // Wed
    
    // Check weekday
    if (wd == Wednesday) {
        std::cout << "Wednesday" << std::endl;
    }
    
    // Weekday index (0 = Sunday)
    std::cout << "Index: " << wd.c_encoding() << std::endl;  // 3
    
    return 0;
}

Find Specific Weekday

using namespace std::chrono;
int main() {
    // First Monday of March 2026
    year_month_weekday ymw = 2026y / March / Monday[1];
    year_month_day ymd{sys_days{ymw}};
    std::cout << "First Monday: " << ymd << std::endl;  // 2026-03-02
    
    // Last Friday of March 2026
    year_month_weekday_last ymwl = 2026y / March / Friday[last];
    year_month_day ymd2{sys_days{ymwl}};
    std::cout << "Last Friday: " << ymd2 << std::endl;  // 2026-03-27
    
    return 0;
}

3) zoned_time - Timezone Conversion

Basic Usage

#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
    auto now = system_clock::now();
    
    // Seoul time
    zoned_time seoul{"Asia/Seoul", now};
    std::cout << "Seoul: " << seoul << std::endl;
    
    // New York time
    zoned_time ny{"America/New_York", now};
    std::cout << "New York: " << ny << std::endl;
    
    // UTC
    zoned_time utc{"UTC", now};
    std::cout << "UTC: " << utc << std::endl;
    
    return 0;
}

Timezone Information

using namespace std::chrono;
int main() {
    auto tz = locate_zone("Asia/Seoul");
    std::cout << "Timezone: " << tz->name() << std::endl;  // Asia/Seoul
    
    auto now = system_clock::now();
    auto info = tz->get_info(now);
    std::cout << "Offset: " << info.offset << std::endl;  // +09:00
    std::cout << "Abbreviation: " << info.abbrev << std::endl;  // KST
    
    return 0;
}

4) Validation

using namespace std::chrono;
int main() {
    // Invalid date
    year_month_day ymd1 = 2026y / February / 30;
    
    if (!ymd1.ok()) {
        std::cout << "Invalid date" << std::endl;
    }
    
    // Last day
    year_month_day_last ymdl = 2026y / February / last;
    auto lastDay = year_month_day{ymdl};
    std::cout << "Last day of February: " << lastDay << std::endl;  // 2026-02-28
    
    // Check leap year
    year y = 2024y;
    if (y.is_leap()) {
        std::cout << "2024 is a leap year" << std::endl;
    }
    
    return 0;
}

Advanced Usage

1) Date Calculator

#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
    year_month_day birth = 1990y / January / 1;
    year_month_day today = 2026y / March / 11;
    
    auto days_lived = sys_days{today} - sys_days{birth};
    auto years_lived = days_lived.count() / 365;
    
    std::cout << "Birth: " << birth << std::endl;
    std::cout << "Today: " << today << std::endl;
    std::cout << "Days lived: " << days_lived.count() << " days" << std::endl;
    std::cout << "Age: approximately " << years_lived << " years" << std::endl;
    
    return 0;
}

2) Next Business Day Calculation

using namespace std::chrono;
year_month_day next_business_day(year_month_day date) {
    auto dp = sys_days{date};
    
    do {
        dp += days{1};
        auto wd = weekday{dp};
        
        if (wd != Saturday && wd != Sunday) {
            return year_month_day{dp};
        }
    } while (true);
}
int main() {
    year_month_day friday = 2026y / March / 13;  // Friday
    year_month_day next = next_business_day(friday);
    
    std::cout << "Friday: " << friday << std::endl;
    std::cout << "Next business day: " << next << std::endl;  // 2026-03-16 (Monday)
    
    return 0;
}

3) Meeting Time Conversion

using namespace std::chrono;
int main() {
    // Seoul time 2026-03-11 14:00
    auto seoul_tz = locate_zone("Asia/Seoul");
    auto local_time = local_days{2026y / March / 11} + hours{14};
    zoned_time seoul{seoul_tz, local_time};
    
    std::cout << "Seoul: " << seoul << std::endl;
    
    // Convert to New York time
    zoned_time ny{"America/New_York", seoul.get_sys_time()};
    std::cout << "New York: " << ny << std::endl;
    
    // Convert to London time
    zoned_time london{"Europe/London", seoul.get_sys_time()};
    std::cout << "London: " << london << std::endl;
    
    return 0;
}

Performance Comparison

C++20 chrono vs External Libraries

LibraryTimezone DBCompile TimeRuntime Performance
C++20 chronoSystemFastFast
date.h (Howard Hinnant)Built-inMediumFast
Boost.DateTimeBuilt-inSlowMedium
Conclusion: C++20 chrono is standard and performs excellently

Real-World Cases

Case 1: Reservation System - Timezone Conversion

#include <chrono>
#include <iostream>
#include <string>
using namespace std::chrono;
struct Reservation {
    std::string customer;
    zoned_time<std::chrono::seconds> time;
};
int main() {
    // Seoul customer reserves at 2026-03-11 14:00
    auto seoul_tz = locate_zone("Asia/Seoul");
    auto local_time = local_days{2026y / March / 11} + hours{14};
    zoned_time seoul{seoul_tz, local_time};
    
    Reservation res{"Kim", seoul};
    
    std::cout << "Reservation time (Seoul): " << res.time << std::endl;
    
    // Check from New York office
    zoned_time ny{"America/New_York", res.time.get_sys_time()};
    std::cout << "Reservation time (New York): " << ny << std::endl;
    
    return 0;
}

Troubleshooting

Problem 1: sys_days Conversion

Symptom: Compilation error when converting year_month_day to sys_days

using namespace std::chrono;
// ❌ Direct arithmetic
year_month_day ymd = 2026y / March / 11;
auto future = ymd + days{10};  // Error
// ✅ Convert to sys_days
auto future = sys_days{ymd} + days{10};
auto result = year_month_day{future};

Problem 2: Timezone Name

Symptom: runtime_error with incorrect timezone name

// ❌ Incorrect timezone name
try {
    auto tz = locate_zone("Seoul");  // Wrong
} catch (const std::runtime_error& e) {
    std::cout << "Error: " << e.what() << std::endl;
}
// ✅ Correct timezone name
auto tz = locate_zone("Asia/Seoul");
// Check timezone list
auto& db = get_tzdb();
for (const auto& zone : db.zones) {
    std::cout << zone.name() << std::endl;
}

Problem 3: End of Month Handling

Symptom: January 31 + 1 month = February 31 (invalid)

using namespace std::chrono;
year_month_day jan31 = 2026y / January / 31;
// ❌ Simple addition
auto feb31 = sys_days{jan31} + months{1};
auto ymd = year_month_day{feb31};
std::cout << ymd << std::endl;  // 2026-03-03 (overflow)
// ✅ End of month handling
year_month_day_last ymdl = jan31.year() / (jan31.month() + months{1}) / last;
auto feb_last = year_month_day{ymdl};
std::cout << feb_last << std::endl;  // 2026-02-28

Problem 4: DST (Daylight Saving Time) Handling

Symptom: 1-hour difference during timezone conversion

using namespace std::chrono;
int main() {
    // US DST starts: Second Sunday of March 02:00
    auto ny_tz = locate_zone("America/New_York");
    
    // Before DST
    auto before_dst = local_days{2026y / March / 8} + hours{1};
    zoned_time ny_before{ny_tz, before_dst};
    std::cout << "Before DST: " << ny_before << std::endl;
    
    // After DST
    auto after_dst = local_days{2026y / March / 9} + hours{1};
    zoned_time ny_after{ny_tz, after_dst};
    std::cout << "After DST: " << ny_after << std::endl;
    
    // Offset difference
    auto info_before = ny_tz->get_info(ny_before.get_sys_time());
    auto info_after = ny_tz->get_info(ny_after.get_sys_time());
    
    std::cout << "Offset before: " << info_before.offset << std::endl;  // -05:00
    std::cout << "Offset after: " << info_after.offset << std::endl;   // -04:00
    
    return 0;
}

Conclusion

C++20 calendar and timezone enable concise date/time handling in the standard library.

Key Summary

  1. year_month_day
    • Date representation and arithmetic
    • 2026y / March / 11
  2. weekday
    • Weekday calculation
    • weekday{sys_days{ymd}}
  3. zoned_time
    • Timezone conversion
    • zoned_time{"Asia/Seoul", now}
  4. Validation
    • ok() method
    • year_month_day_last

Selection Guide

SituationType
Date representationyear_month_day
Weekday calculationweekday
Timezone conversionzoned_time
End of monthyear_month_day_last
Find specific weekdayyear_month_weekday

Code Example Cheatsheet

// Create date
year_month_day ymd = 2026y / March / 11;
// Date arithmetic
auto future = sys_days{ymd} + days{10};
auto diff = sys_days{ymd1} - sys_days{ymd2};
// Weekday calculation
auto wd = weekday{sys_days{ymd}};
// Timezone conversion
zoned_time seoul{"Asia/Seoul", now};
zoned_time ny{"America/New_York", seoul.get_sys_time()};
// Validation
if (!ymd.ok()) { /* ....*/ }
// End of month
year_month_day_last ymdl = 2026y / February / last;

Next Steps

References