std::chrono::zoned_time

std::chrono::zoned_time (시간대와 시점의 결합 클래스)

시간대(time zone)와 std::chrono::time_point를 논리적으로 짝지어 나타내는 클래스예요. 특정 시간대에서 그 시점이 어떤 시각인지를 표현해요. C++20의 chrono 시간대 지원의 핵심이에요.

출처: cppreference

본문

<chrono> 헤더에 정의돼 있고, 시간대와 해상도가 Durationstd::chrono::time_point의 논리적 짝을 나타내요.

template<
    class Duration,
    class TimeZonePtr = const std::chrono::time_zone*
> class zoned_time;

using zoned_seconds = std::chrono::zoned_time<std::chrono::seconds>;

zoned_time의 불변식(invariant)은 항상 유효한 시간대를 가리키고, 그 시간대에서 존재하고 모호하지 않은 시점을 나타낸다는 것이에요. 이 불변식과 일관되게 zoned_time은 이동 생성자나 이동 대입 연산자가 없어요. zoned_time을 이동하려 하면 복사가 수행돼요.

Durationstd::chrono::duration의 특수화가 아니면 프로그램은 ill-formed예요.

템플릿 인자 TimeZonePtr 덕분에 사용자가 자신만의 시간대 포인터 타입을 제공하고, std::chrono::zoned_traits를 통해 zoned_time의 동작을 더 커스터마이즈할 수 있어요. 커스텀 시간대 타입은 std::chrono::time_zone이 지원하는 모든 연산을 지원할 필요 없고, 실제로 zoned_time에서 호출되는 함수들이 쓰는 것만 지원하면 돼요.

TimeZonePtr는 MoveConstructible이어야 해요. Move-only TimeZonePtr는 허용되지만 쓰기 어려워요. zoned_time이 이동 불가능해지고 저장된 TimeZonePtr에 접근할 수 없기 때문이에요.

  • 멤버 타입 duration = std::common_type_t<Duration, std::chrono::seconds>.

멤버 함수:

  • 생성자: zoned_time을 만들 수 있어요.
  • operator=: zoned_time에 값을 대입해요.
  • get_time_zone: 시간대 포인터의 복사본을 얻어요.
  • operator local_time, get_local_time: 저장된 시점을 local_time으로 얻어요.
  • operator sys_time, get_sys_time: 저장된 시점을 sys_time으로 얻어요.
  • get_info: 저장된 시점에서 시간대에 대한 정보를 얻어요.

비멤버 함수:

  • operator== (C++20): 두 zoned_time 값을 비교해요.
  • operator<< (C++20): zoned_time을 스트림에 출력해요.

헬퍼 클래스:

  • std::formatter<std::chrono::zoned_time> (C++20): zoned_time 포맷 지원.
  • std::hash<std::chrono::zoned_time> (C++26): 해시 지원.

헬퍼 특수화로 std::enable_nonlocking_formatter_optimization<chrono::zoned_time<Duration, const chrono::time_zone*>> = true (C++23)가 있어요. std::printstd::println에서 chrono::zoned_time 객체를 효율적으로 출력하도록 해요.

예제를 보면 여러 시간대의 현재 시각을 출력할 수 있어요.

#include <chrono>
#include <iomanip>
#include <iostream>
#include <string_view>

int main()
{
    constexpr std::string_view locations[] =
    {
        "Africa/Casablanca", "America/Argentina/Buenos_Aires",
        "America/Barbados",  "America/Indiana/Petersburg",
        "Asia/Tokyo",        "Australia/Darwin",
    };

    for (const auto location : locations)
        try
        {
            // 'location'이 시간대 DB에 없으면 예외를 던질 수 있어요
            const std::chrono::zoned_time zt{location, std::chrono::system_clock::now()};
            std::cout << location << " - Zoned Time: " << zt << '\n';
        }
        catch (std::runtime_error& ex)
        {
            std::cout << "Error: " << ex.what() << '\n';
        }
}

가능한 출력:

Africa/Casablanca - Zoned Time: 2023-06-29 20:58:34.697449319 +01
America/Argentina/Buenos_Aires - Zoned Time: 2023-06-29 16:58:34.709957354 -03
       Asia/Tokyo - Zoned Time: 2023-06-30 04:58:34.710172815 JST

시간대 이름으로 zoned_time을 만들면 해당 시간대에서의 시각(오프셋·약어 포함)을 얻을 수 있어요.

더 알아보기 (Learn more)

cppreference