2 //===----------------------------------------------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 // For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html
12 #ifndef _LIBCPP___CHRONO_EXCEPTION_H
13 #define _LIBCPP___CHRONO_EXCEPTION_H
16 // Enable the contents of the header only when libc++ was built with experimental features enabled.
17 #if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB)
19 # include <__chrono/calendar.h>
20 # include <__chrono/local_info.h>
21 # include <__chrono/time_point.h>
23 # include <__configuration/availability.h>
24 # include <__verbose_abort>
29 # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
30 # pragma GCC system_header
33 _LIBCPP_BEGIN_NAMESPACE_STD
35 # if _LIBCPP_STD_VER >= 20
39 class nonexistent_local_time
: public runtime_error
{
41 template <class _Duration
>
42 _LIBCPP_HIDE_FROM_ABI
nonexistent_local_time(const local_time
<_Duration
>& __time
, const local_info
& __info
)
43 : runtime_error
{__create_message(__time
, __info
)} {
44 // [time.zone.exception.nonexist]/2
45 // Preconditions: i.result == local_info::nonexistent is true.
46 // The value of __info.result is not used.
47 _LIBCPP_ASSERT_PEDANTIC(__info
.result
== local_info::nonexistent
,
48 "creating an nonexistent_local_time from a local_info that is not non-existent");
51 _LIBCPP_HIDE_FROM_ABI
nonexistent_local_time(const nonexistent_local_time
&) = default;
52 _LIBCPP_HIDE_FROM_ABI nonexistent_local_time
& operator=(const nonexistent_local_time
&) = default;
54 _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI
~nonexistent_local_time() override
; // exported as key function
57 template <class _Duration
>
58 _LIBCPP_HIDE_FROM_ABI string
__create_message(const local_time
<_Duration
>& __time
, const local_info
& __info
) {
60 R
"({} is in a gap between
62 {} {} which are both equivalent to
65 local_seconds
{__info
.first
.end
.time_since_epoch()} + __info
.first
.offset
,
67 local_seconds
{__info
.second
.begin
.time_since_epoch()} + __info
.second
.offset
,
73 template <class _Duration
>
74 [[noreturn
]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI
void __throw_nonexistent_local_time(
75 [[maybe_unused
]] const local_time
<_Duration
>& __time
, [[maybe_unused
]] const local_info
& __info
) {
76 # if _LIBCPP_HAS_EXCEPTIONS
77 throw nonexistent_local_time(__time
, __info
);
79 _LIBCPP_VERBOSE_ABORT("nonexistent_local_time was thrown in -fno-exceptions mode");
83 class ambiguous_local_time
: public runtime_error
{
85 template <class _Duration
>
86 _LIBCPP_HIDE_FROM_ABI
ambiguous_local_time(const local_time
<_Duration
>& __time
, const local_info
& __info
)
87 : runtime_error
{__create_message(__time
, __info
)} {
88 // [time.zone.exception.ambig]/2
89 // Preconditions: i.result == local_info::ambiguous is true.
90 // The value of __info.result is not used.
91 _LIBCPP_ASSERT_PEDANTIC(__info
.result
== local_info::ambiguous
,
92 "creating an ambiguous_local_time from a local_info that is not ambiguous");
95 _LIBCPP_HIDE_FROM_ABI
ambiguous_local_time(const ambiguous_local_time
&) = default;
96 _LIBCPP_HIDE_FROM_ABI ambiguous_local_time
& operator=(const ambiguous_local_time
&) = default;
98 _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI
~ambiguous_local_time() override
; // exported as key function
101 template <class _Duration
>
102 _LIBCPP_HIDE_FROM_ABI string
__create_message(const local_time
<_Duration
>& __time
, const local_info
& __info
) {
104 // There are two spaces after the full-stop; this has been verified
105 // in the sources of the Standard.
106 R
"({0} is ambiguous. It could be
107 {0} {1} == {2} UTC or
108 {0} {3} == {4} UTC)",
111 __time
- __info
.first
.offset
,
112 __info
.second
.abbrev
,
113 __time
- __info
.second
.offset
);
117 template <class _Duration
>
118 [[noreturn
]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI
void __throw_ambiguous_local_time(
119 [[maybe_unused
]] const local_time
<_Duration
>& __time
, [[maybe_unused
]] const local_info
& __info
) {
120 # if _LIBCPP_HAS_EXCEPTIONS
121 throw ambiguous_local_time(__time
, __info
);
123 _LIBCPP_VERBOSE_ABORT("ambiguous_local_time was thrown in -fno-exceptions mode");
127 } // namespace chrono
129 # endif // _LIBCPP_STD_VER >= 20
131 _LIBCPP_END_NAMESPACE_STD
133 #endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB)
135 #endif // _LIBCPP___CHRONO_EXCEPTION_H