Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:15

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //===----------------------------------------------------------------------===//
0009 
0010 // For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html
0011 
0012 #ifndef _LIBCPP___CHRONO_TIME_ZONE_H
0013 #define _LIBCPP___CHRONO_TIME_ZONE_H
0014 
0015 #include <version>
0016 // Enable the contents of the header only when libc++ was built with experimental features enabled.
0017 #if _LIBCPP_HAS_EXPERIMENTAL_TZDB
0018 
0019 #  include <__chrono/calendar.h>
0020 #  include <__chrono/duration.h>
0021 #  include <__chrono/exception.h>
0022 #  include <__chrono/local_info.h>
0023 #  include <__chrono/sys_info.h>
0024 #  include <__chrono/system_clock.h>
0025 #  include <__compare/strong_order.h>
0026 #  include <__config>
0027 #  include <__memory/unique_ptr.h>
0028 #  include <__type_traits/common_type.h>
0029 #  include <string_view>
0030 
0031 #  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0032 #    pragma GCC system_header
0033 #  endif
0034 
0035 _LIBCPP_PUSH_MACROS
0036 #  include <__undef_macros>
0037 
0038 _LIBCPP_BEGIN_NAMESPACE_STD
0039 
0040 #  if _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
0041 
0042 namespace chrono {
0043 
0044 enum class choose { earliest, latest };
0045 
0046 class _LIBCPP_AVAILABILITY_TZDB time_zone {
0047   _LIBCPP_HIDE_FROM_ABI time_zone() = default;
0048 
0049 public:
0050   class __impl; // public so it can be used by make_unique.
0051 
0052   // The "constructor".
0053   //
0054   // The default constructor is private to avoid the constructor from being
0055   // part of the ABI. Instead use an __ugly_named function as an ABI interface,
0056   // since that gives us the ability to change it in the future.
0057   [[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI static time_zone __create(unique_ptr<__impl>&& __p);
0058 
0059   _LIBCPP_EXPORTED_FROM_ABI ~time_zone();
0060 
0061   _LIBCPP_HIDE_FROM_ABI time_zone(time_zone&&)            = default;
0062   _LIBCPP_HIDE_FROM_ABI time_zone& operator=(time_zone&&) = default;
0063 
0064   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI string_view name() const noexcept { return __name(); }
0065 
0066   template <class _Duration>
0067   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI sys_info get_info(const sys_time<_Duration>& __time) const {
0068     return __get_info(chrono::time_point_cast<seconds>(__time));
0069   }
0070 
0071   template <class _Duration>
0072   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI local_info get_info(const local_time<_Duration>& __time) const {
0073     return __get_info(chrono::time_point_cast<seconds>(__time));
0074   }
0075 
0076   // We don't apply nodiscard here since this function throws on many inputs,
0077   // so it could be used as a validation.
0078   template <class _Duration>
0079   _LIBCPP_HIDE_FROM_ABI sys_time<common_type_t<_Duration, seconds>> to_sys(const local_time<_Duration>& __time) const {
0080     local_info __info = get_info(__time);
0081     switch (__info.result) {
0082     case local_info::unique:
0083       return sys_time<common_type_t<_Duration, seconds>>{__time.time_since_epoch() - __info.first.offset};
0084 
0085     case local_info::nonexistent:
0086       chrono::__throw_nonexistent_local_time(__time, __info);
0087 
0088     case local_info::ambiguous:
0089       chrono::__throw_ambiguous_local_time(__time, __info);
0090     }
0091 
0092     // TODO TZDB The Standard does not specify anything in these cases.
0093     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
0094         __info.result != -1, "cannot convert the local time; it would be before the minimum system clock value");
0095     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
0096         __info.result != -2, "cannot convert the local time; it would be after the maximum system clock value");
0097 
0098     return {};
0099   }
0100 
0101   template <class _Duration>
0102   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI sys_time<common_type_t<_Duration, seconds>>
0103   to_sys(const local_time<_Duration>& __time, choose __z) const {
0104     local_info __info = get_info(__time);
0105     switch (__info.result) {
0106     case local_info::unique: // first and second are the same
0107       return sys_time<common_type_t<_Duration, seconds>>{__time.time_since_epoch() - __info.first.offset};
0108 
0109     case local_info::nonexistent:
0110       // first and second are the same
0111       // All non-existing values are converted to the same time.
0112       return sys_time<common_type_t<_Duration, seconds>>{__info.first.end};
0113 
0114     case local_info::ambiguous:
0115       switch (__z) {
0116       case choose::earliest:
0117         return sys_time<common_type_t<_Duration, seconds>>{__time.time_since_epoch() - __info.first.offset};
0118 
0119       case choose::latest:
0120         return sys_time<common_type_t<_Duration, seconds>>{__time.time_since_epoch() - __info.second.offset};
0121 
0122         // Note a value out of bounds is not specified.
0123       }
0124     }
0125 
0126     // TODO TZDB The standard does not specify anything in these cases.
0127     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
0128         __info.result != -1, "cannot convert the local time; it would be before the minimum system clock value");
0129     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
0130         __info.result != -2, "cannot convert the local time; it would be after the maximum system clock value");
0131 
0132     return {};
0133   }
0134 
0135   template <class _Duration>
0136   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI local_time<common_type_t<_Duration, seconds>>
0137   to_local(const sys_time<_Duration>& __time) const {
0138     using _Dp = common_type_t<_Duration, seconds>;
0139 
0140     sys_info __info = get_info(__time);
0141 
0142     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
0143         __info.offset >= chrono::seconds{0} || __time.time_since_epoch() >= _Dp::min() - __info.offset,
0144         "cannot convert the system time; it would be before the minimum local clock value");
0145 
0146     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
0147         __info.offset <= chrono::seconds{0} || __time.time_since_epoch() <= _Dp::max() - __info.offset,
0148         "cannot convert the system time; it would be after the maximum local clock value");
0149 
0150     return local_time<_Dp>{__time.time_since_epoch() + __info.offset};
0151   }
0152 
0153   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const __impl& __implementation() const noexcept { return *__impl_; }
0154 
0155 private:
0156   [[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI string_view __name() const noexcept;
0157 
0158   [[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI sys_info __get_info(sys_seconds __time) const;
0159   [[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI local_info __get_info(local_seconds __time) const;
0160 
0161   unique_ptr<__impl> __impl_;
0162 };
0163 
0164 [[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline bool
0165 operator==(const time_zone& __x, const time_zone& __y) noexcept {
0166   return __x.name() == __y.name();
0167 }
0168 
0169 [[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI inline strong_ordering
0170 operator<=>(const time_zone& __x, const time_zone& __y) noexcept {
0171   return __x.name() <=> __y.name();
0172 }
0173 
0174 } // namespace chrono
0175 
0176 #  endif // _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM &&
0177          // _LIBCPP_HAS_LOCALIZATION
0178 
0179 _LIBCPP_END_NAMESPACE_STD
0180 
0181 _LIBCPP_POP_MACROS
0182 
0183 #endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
0184 
0185 #endif // _LIBCPP___CHRONO_TIME_ZONE_H