1*0fca6ea1SDimitry Andric // -*- C++ -*- 2*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 3*0fca6ea1SDimitry Andric // 4*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*0fca6ea1SDimitry Andric // 8*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 9*0fca6ea1SDimitry Andric 10*0fca6ea1SDimitry Andric // For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html 11*0fca6ea1SDimitry Andric 12*0fca6ea1SDimitry Andric #ifndef _LIBCPP___CHRONO_EXCEPTION_H 13*0fca6ea1SDimitry Andric #define _LIBCPP___CHRONO_EXCEPTION_H 14*0fca6ea1SDimitry Andric 15*0fca6ea1SDimitry Andric #include <version> 16*0fca6ea1SDimitry Andric // Enable the contents of the header only when libc++ was built with experimental features enabled. 17*0fca6ea1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) 18*0fca6ea1SDimitry Andric 19*0fca6ea1SDimitry Andric # include <__chrono/calendar.h> 20*0fca6ea1SDimitry Andric # include <__chrono/local_info.h> 21*0fca6ea1SDimitry Andric # include <__chrono/time_point.h> 22*0fca6ea1SDimitry Andric # include <__config> 23*0fca6ea1SDimitry Andric # include <__configuration/availability.h> 24*0fca6ea1SDimitry Andric # include <__verbose_abort> 25*0fca6ea1SDimitry Andric # include <format> 26*0fca6ea1SDimitry Andric # include <stdexcept> 27*0fca6ea1SDimitry Andric # include <string> 28*0fca6ea1SDimitry Andric 29*0fca6ea1SDimitry Andric # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 30*0fca6ea1SDimitry Andric # pragma GCC system_header 31*0fca6ea1SDimitry Andric # endif 32*0fca6ea1SDimitry Andric 33*0fca6ea1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 34*0fca6ea1SDimitry Andric 35*0fca6ea1SDimitry Andric # if _LIBCPP_STD_VER >= 20 36*0fca6ea1SDimitry Andric 37*0fca6ea1SDimitry Andric namespace chrono { 38*0fca6ea1SDimitry Andric 39*0fca6ea1SDimitry Andric class nonexistent_local_time : public runtime_error { 40*0fca6ea1SDimitry Andric public: 41*0fca6ea1SDimitry Andric template <class _Duration> 42*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI nonexistent_local_time(const local_time<_Duration>& __time, const local_info& __info) 43*0fca6ea1SDimitry Andric : runtime_error{__create_message(__time, __info)} { 44*0fca6ea1SDimitry Andric // [time.zone.exception.nonexist]/2 45*0fca6ea1SDimitry Andric // Preconditions: i.result == local_info::nonexistent is true. 46*0fca6ea1SDimitry Andric // The value of __info.result is not used. 47*0fca6ea1SDimitry Andric _LIBCPP_ASSERT_PEDANTIC(__info.result == local_info::nonexistent, 48*0fca6ea1SDimitry Andric "creating an nonexistent_local_time from a local_info that is not non-existent"); 49*0fca6ea1SDimitry Andric } 50*0fca6ea1SDimitry Andric 51*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI nonexistent_local_time(const nonexistent_local_time&) = default; 52*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI nonexistent_local_time& operator=(const nonexistent_local_time&) = default; 53*0fca6ea1SDimitry Andric 54*0fca6ea1SDimitry Andric _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI ~nonexistent_local_time() override; // exported as key function 55*0fca6ea1SDimitry Andric 56*0fca6ea1SDimitry Andric private: 57*0fca6ea1SDimitry Andric template <class _Duration> 58*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI string __create_message(const local_time<_Duration>& __time, const local_info& __info) { 59*0fca6ea1SDimitry Andric return std::format( 60*0fca6ea1SDimitry Andric R"({} is in a gap between 61*0fca6ea1SDimitry Andric {} {} and 62*0fca6ea1SDimitry Andric {} {} which are both equivalent to 63*0fca6ea1SDimitry Andric {} UTC)", 64*0fca6ea1SDimitry Andric __time, 65*0fca6ea1SDimitry Andric local_seconds{__info.first.end.time_since_epoch()} + __info.first.offset, 66*0fca6ea1SDimitry Andric __info.first.abbrev, 67*0fca6ea1SDimitry Andric local_seconds{__info.second.begin.time_since_epoch()} + __info.second.offset, 68*0fca6ea1SDimitry Andric __info.second.abbrev, 69*0fca6ea1SDimitry Andric __info.first.end); 70*0fca6ea1SDimitry Andric } 71*0fca6ea1SDimitry Andric }; 72*0fca6ea1SDimitry Andric 73*0fca6ea1SDimitry Andric template <class _Duration> 74*0fca6ea1SDimitry Andric _LIBCPP_NORETURN _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI void __throw_nonexistent_local_time( 75*0fca6ea1SDimitry Andric [[maybe_unused]] const local_time<_Duration>& __time, [[maybe_unused]] const local_info& __info) { 76*0fca6ea1SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 77*0fca6ea1SDimitry Andric throw nonexistent_local_time(__time, __info); 78*0fca6ea1SDimitry Andric # else 79*0fca6ea1SDimitry Andric _LIBCPP_VERBOSE_ABORT("nonexistent_local_time was thrown in -fno-exceptions mode"); 80*0fca6ea1SDimitry Andric # endif 81*0fca6ea1SDimitry Andric } 82*0fca6ea1SDimitry Andric 83*0fca6ea1SDimitry Andric class ambiguous_local_time : public runtime_error { 84*0fca6ea1SDimitry Andric public: 85*0fca6ea1SDimitry Andric template <class _Duration> 86*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI ambiguous_local_time(const local_time<_Duration>& __time, const local_info& __info) 87*0fca6ea1SDimitry Andric : runtime_error{__create_message(__time, __info)} { 88*0fca6ea1SDimitry Andric // [time.zone.exception.ambig]/2 89*0fca6ea1SDimitry Andric // Preconditions: i.result == local_info::ambiguous is true. 90*0fca6ea1SDimitry Andric // The value of __info.result is not used. 91*0fca6ea1SDimitry Andric _LIBCPP_ASSERT_PEDANTIC(__info.result == local_info::ambiguous, 92*0fca6ea1SDimitry Andric "creating an ambiguous_local_time from a local_info that is not ambiguous"); 93*0fca6ea1SDimitry Andric } 94*0fca6ea1SDimitry Andric 95*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI ambiguous_local_time(const ambiguous_local_time&) = default; 96*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI ambiguous_local_time& operator=(const ambiguous_local_time&) = default; 97*0fca6ea1SDimitry Andric 98*0fca6ea1SDimitry Andric _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI ~ambiguous_local_time() override; // exported as key function 99*0fca6ea1SDimitry Andric 100*0fca6ea1SDimitry Andric private: 101*0fca6ea1SDimitry Andric template <class _Duration> 102*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI string __create_message(const local_time<_Duration>& __time, const local_info& __info) { 103*0fca6ea1SDimitry Andric return std::format( 104*0fca6ea1SDimitry Andric // There are two spaces after the full-stop; this has been verified 105*0fca6ea1SDimitry Andric // in the sources of the Standard. 106*0fca6ea1SDimitry Andric R"({0} is ambiguous. It could be 107*0fca6ea1SDimitry Andric {0} {1} == {2} UTC or 108*0fca6ea1SDimitry Andric {0} {3} == {4} UTC)", 109*0fca6ea1SDimitry Andric __time, 110*0fca6ea1SDimitry Andric __info.first.abbrev, 111*0fca6ea1SDimitry Andric __time - __info.first.offset, 112*0fca6ea1SDimitry Andric __info.second.abbrev, 113*0fca6ea1SDimitry Andric __time - __info.second.offset); 114*0fca6ea1SDimitry Andric } 115*0fca6ea1SDimitry Andric }; 116*0fca6ea1SDimitry Andric 117*0fca6ea1SDimitry Andric template <class _Duration> 118*0fca6ea1SDimitry Andric _LIBCPP_NORETURN _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI void __throw_ambiguous_local_time( 119*0fca6ea1SDimitry Andric [[maybe_unused]] const local_time<_Duration>& __time, [[maybe_unused]] const local_info& __info) { 120*0fca6ea1SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 121*0fca6ea1SDimitry Andric throw ambiguous_local_time(__time, __info); 122*0fca6ea1SDimitry Andric # else 123*0fca6ea1SDimitry Andric _LIBCPP_VERBOSE_ABORT("ambiguous_local_time was thrown in -fno-exceptions mode"); 124*0fca6ea1SDimitry Andric # endif 125*0fca6ea1SDimitry Andric } 126*0fca6ea1SDimitry Andric 127*0fca6ea1SDimitry Andric } // namespace chrono 128*0fca6ea1SDimitry Andric 129*0fca6ea1SDimitry Andric # endif // _LIBCPP_STD_VER >= 20 130*0fca6ea1SDimitry Andric 131*0fca6ea1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 132*0fca6ea1SDimitry Andric 133*0fca6ea1SDimitry Andric #endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) 134*0fca6ea1SDimitry Andric 135*0fca6ea1SDimitry Andric #endif // _LIBCPP___CHRONO_EXCEPTION_H 136