Path: blob/main/contrib/llvm-project/libcxx/include/__chrono/zoned_time.h
35262 views
// -*- C++ -*-1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//89// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html1011#ifndef _LIBCPP___CHRONO_ZONED_TIME_H12#define _LIBCPP___CHRONO_ZONED_TIME_H1314#include <version>15// Enable the contents of the header only when libc++ was built with experimental features enabled.16#if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB)1718# include <__chrono/calendar.h>19# include <__chrono/duration.h>20# include <__chrono/sys_info.h>21# include <__chrono/system_clock.h>22# include <__chrono/time_zone.h>23# include <__chrono/tzdb_list.h>24# include <__config>25# include <__fwd/string_view.h>26# include <__type_traits/common_type.h>27# include <__type_traits/conditional.h>28# include <__type_traits/remove_cvref.h>29# include <__utility/move.h>3031# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)32# pragma GCC system_header33# endif3435_LIBCPP_PUSH_MACROS36# include <__undef_macros>3738_LIBCPP_BEGIN_NAMESPACE_STD3940# if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) && \41!defined(_LIBCPP_HAS_NO_LOCALIZATION)4243namespace chrono {4445template <class>46struct zoned_traits {};4748template <>49struct zoned_traits<const time_zone*> {50[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static const time_zone* default_zone() { return chrono::locate_zone("UTC"); }51[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static const time_zone* locate_zone(string_view __name) {52return chrono::locate_zone(__name);53}54};5556template <class _Duration, class _TimeZonePtr = const time_zone*>57class zoned_time {58// [time.zone.zonedtime.ctor]/259static_assert(__is_duration<_Duration>::value,60"the program is ill-formed since _Duration is not a specialization of std::chrono::duration");6162// The wording uses the constraints like63// constructible_from<zoned_time, decltype(__traits::locate_zone(string_view{}))>64// Using these constraints in the code causes the compiler to give an65// error that the constraint depends on itself. To avoid that issue use66// the fact it is possible to create this object from a _TimeZonePtr.67using __traits = zoned_traits<_TimeZonePtr>;6869public:70using duration = common_type_t<_Duration, seconds>;7172_LIBCPP_HIDE_FROM_ABI zoned_time()73requires requires { __traits::default_zone(); }74: __zone_{__traits::default_zone()}, __tp_{} {}7576_LIBCPP_HIDE_FROM_ABI zoned_time(const zoned_time&) = default;77_LIBCPP_HIDE_FROM_ABI zoned_time& operator=(const zoned_time&) = default;7879_LIBCPP_HIDE_FROM_ABI zoned_time(const sys_time<_Duration>& __tp)80requires requires { __traits::default_zone(); }81: __zone_{__traits::default_zone()}, __tp_{__tp} {}8283_LIBCPP_HIDE_FROM_ABI explicit zoned_time(_TimeZonePtr __zone) : __zone_{std::move(__zone)}, __tp_{} {}8485_LIBCPP_HIDE_FROM_ABI explicit zoned_time(string_view __name)86requires(requires { __traits::locate_zone(string_view{}); } &&87constructible_from<_TimeZonePtr, decltype(__traits::locate_zone(string_view{}))>)88: __zone_{__traits::locate_zone(__name)}, __tp_{} {}8990template <class _Duration2>91_LIBCPP_HIDE_FROM_ABI zoned_time(const zoned_time<_Duration2, _TimeZonePtr>& __zt)92requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>93: __zone_{__zt.get_time_zone()}, __tp_{__zt.get_sys_time()} {}9495_LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const sys_time<_Duration>& __tp)96: __zone_{std::move(__zone)}, __tp_{__tp} {}9798_LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const sys_time<_Duration>& __tp)99requires requires { _TimeZonePtr{__traits::locate_zone(string_view{})}; }100: zoned_time{__traits::locate_zone(__name), __tp} {}101102_LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const local_time<_Duration>& __tp)103requires(is_convertible_v<decltype(std::declval<_TimeZonePtr&>() -> to_sys(local_time<_Duration>{})),104sys_time<duration>>)105: __zone_{std::move(__zone)}, __tp_{__zone_->to_sys(__tp)} {}106107_LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const local_time<_Duration>& __tp)108requires(requires {109_TimeZonePtr{__traits::locate_zone(string_view{})};110} && is_convertible_v<decltype(std::declval<_TimeZonePtr&>() -> to_sys(local_time<_Duration>{})),111sys_time<duration>>)112: zoned_time{__traits::locate_zone(__name), __tp} {}113114_LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const local_time<_Duration>& __tp, choose __c)115requires(is_convertible_v<116decltype(std::declval<_TimeZonePtr&>() -> to_sys(local_time<_Duration>{}, choose::earliest)),117sys_time<duration>>)118: __zone_{std::move(__zone)}, __tp_{__zone_->to_sys(__tp, __c)} {}119120_LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const local_time<_Duration>& __tp, choose __c)121requires(requires {122_TimeZonePtr{__traits::locate_zone(string_view{})};123} && is_convertible_v<decltype(std::declval<_TimeZonePtr&>() -> to_sys(local_time<_Duration>{}, choose::earliest)),124sys_time<duration>>)125: zoned_time{__traits::locate_zone(__name), __tp, __c} {}126127template <class _Duration2, class _TimeZonePtr2>128_LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const zoned_time<_Duration2, _TimeZonePtr2>& __zt)129requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>130: __zone_{std::move(__zone)}, __tp_{__zt.get_sys_time()} {}131132// per wording choose has no effect133template <class _Duration2, class _TimeZonePtr2>134_LIBCPP_HIDE_FROM_ABI zoned_time(_TimeZonePtr __zone, const zoned_time<_Duration2, _TimeZonePtr2>& __zt, choose)135requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>136: __zone_{std::move(__zone)}, __tp_{__zt.get_sys_time()} {}137138template <class _Duration2, class _TimeZonePtr2>139_LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const zoned_time<_Duration2, _TimeZonePtr2>& __zt)140requires(requires {141_TimeZonePtr{__traits::locate_zone(string_view{})};142} && is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>)143: zoned_time{__traits::locate_zone(__name), __zt} {}144145template <class _Duration2, class _TimeZonePtr2>146_LIBCPP_HIDE_FROM_ABI zoned_time(string_view __name, const zoned_time<_Duration2, _TimeZonePtr2>& __zt, choose __c)147requires(requires {148_TimeZonePtr{__traits::locate_zone(string_view{})};149} && is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>)150: zoned_time{__traits::locate_zone(__name), __zt, __c} {}151152_LIBCPP_HIDE_FROM_ABI zoned_time& operator=(const sys_time<_Duration>& __tp) {153__tp_ = __tp;154return *this;155}156157_LIBCPP_HIDE_FROM_ABI zoned_time& operator=(const local_time<_Duration>& __tp) {158// TODO TZDB This seems wrong.159// Assigning a non-existent or ambiguous time will throw and not satisfy160// the post condition. This seems quite odd; I constructed an object with161// choose::earliest and that choice is not respected.162// what did LEWG do with this.163// MSVC STL and libstdc++ behave the same164__tp_ = __zone_->to_sys(__tp);165return *this;166}167168[[nodiscard]] _LIBCPP_HIDE_FROM_ABI operator sys_time<duration>() const { return get_sys_time(); }169[[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit operator local_time<duration>() const { return get_local_time(); }170171[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _TimeZonePtr get_time_zone() const { return __zone_; }172[[nodiscard]] _LIBCPP_HIDE_FROM_ABI local_time<duration> get_local_time() const { return __zone_->to_local(__tp_); }173[[nodiscard]] _LIBCPP_HIDE_FROM_ABI sys_time<duration> get_sys_time() const { return __tp_; }174[[nodiscard]] _LIBCPP_HIDE_FROM_ABI sys_info get_info() const { return __zone_->get_info(__tp_); }175176private:177_TimeZonePtr __zone_;178sys_time<duration> __tp_;179};180181zoned_time() -> zoned_time<seconds>;182183template <class _Duration>184zoned_time(sys_time<_Duration>) -> zoned_time<common_type_t<_Duration, seconds>>;185186template <class _TimeZonePtrOrName>187using __time_zone_representation =188conditional_t<is_convertible_v<_TimeZonePtrOrName, string_view>,189const time_zone*,190remove_cvref_t<_TimeZonePtrOrName>>;191192template <class _TimeZonePtrOrName>193zoned_time(_TimeZonePtrOrName&&) -> zoned_time<seconds, __time_zone_representation<_TimeZonePtrOrName>>;194195template <class _TimeZonePtrOrName, class _Duration>196zoned_time(_TimeZonePtrOrName&&, sys_time<_Duration>)197-> zoned_time<common_type_t<_Duration, seconds>, __time_zone_representation<_TimeZonePtrOrName>>;198199template <class _TimeZonePtrOrName, class _Duration>200zoned_time(_TimeZonePtrOrName&&, local_time<_Duration>, choose = choose::earliest)201-> zoned_time<common_type_t<_Duration, seconds>, __time_zone_representation<_TimeZonePtrOrName>>;202203template <class _Duration, class _TimeZonePtrOrName, class TimeZonePtr2>204zoned_time(_TimeZonePtrOrName&&, zoned_time<_Duration, TimeZonePtr2>, choose = choose::earliest)205-> zoned_time<common_type_t<_Duration, seconds>, __time_zone_representation<_TimeZonePtrOrName>>;206207using zoned_seconds = zoned_time<seconds>;208209template <class _Duration1, class _Duration2, class _TimeZonePtr>210_LIBCPP_HIDE_FROM_ABI bool211operator==(const zoned_time<_Duration1, _TimeZonePtr>& __lhs, const zoned_time<_Duration2, _TimeZonePtr>& __rhs) {212return __lhs.get_time_zone() == __rhs.get_time_zone() && __lhs.get_sys_time() == __rhs.get_sys_time();213}214215} // namespace chrono216217# endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) && !defined(_LIBCPP_HAS_NO_FILESYSTEM)218// && !defined(_LIBCPP_HAS_NO_LOCALIZATION)219220_LIBCPP_END_NAMESPACE_STD221222_LIBCPP_POP_MACROS223224#endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB)225226#endif // _LIBCPP___CHRONO_ZONED_TIME_H227228229