xref: /llvm-project/libcxx/include/__chrono/exception.h (revision 24e70e3930724ce499ad05d669bfbc4423c542e0)
177116bd7SMark de Wever // -*- C++ -*-
277116bd7SMark de Wever //===----------------------------------------------------------------------===//
377116bd7SMark de Wever //
477116bd7SMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
577116bd7SMark de Wever // See https://llvm.org/LICENSE.txt for license information.
677116bd7SMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
777116bd7SMark de Wever //
877116bd7SMark de Wever //===----------------------------------------------------------------------===//
977116bd7SMark de Wever 
1077116bd7SMark de Wever // For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html
1177116bd7SMark de Wever 
1277116bd7SMark de Wever #ifndef _LIBCPP___CHRONO_EXCEPTION_H
1377116bd7SMark de Wever #define _LIBCPP___CHRONO_EXCEPTION_H
1477116bd7SMark de Wever 
1577116bd7SMark de Wever #include <version>
1677116bd7SMark de Wever // Enable the contents of the header only when libc++ was built with experimental features enabled.
17*24e70e39SNikolas Klauser #if _LIBCPP_HAS_EXPERIMENTAL_TZDB
1877116bd7SMark de Wever 
1977116bd7SMark de Wever #  include <__chrono/calendar.h>
2077116bd7SMark de Wever #  include <__chrono/local_info.h>
2177116bd7SMark de Wever #  include <__chrono/time_point.h>
2277116bd7SMark de Wever #  include <__config>
2377116bd7SMark de Wever #  include <__configuration/availability.h>
2477116bd7SMark de Wever #  include <__verbose_abort>
2577116bd7SMark de Wever #  include <format>
2677116bd7SMark de Wever #  include <stdexcept>
2777116bd7SMark de Wever #  include <string>
2877116bd7SMark de Wever 
2977116bd7SMark de Wever #  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
3077116bd7SMark de Wever #    pragma GCC system_header
3177116bd7SMark de Wever #  endif
3277116bd7SMark de Wever 
3377116bd7SMark de Wever _LIBCPP_BEGIN_NAMESPACE_STD
3477116bd7SMark de Wever 
3577116bd7SMark de Wever #  if _LIBCPP_STD_VER >= 20
3677116bd7SMark de Wever 
3777116bd7SMark de Wever namespace chrono {
3877116bd7SMark de Wever 
3977116bd7SMark de Wever class nonexistent_local_time : public runtime_error {
4077116bd7SMark de Wever public:
4177116bd7SMark de Wever   template <class _Duration>
4277116bd7SMark de Wever   _LIBCPP_HIDE_FROM_ABI nonexistent_local_time(const local_time<_Duration>& __time, const local_info& __info)
4377116bd7SMark de Wever       : runtime_error{__create_message(__time, __info)} {
4477116bd7SMark de Wever     // [time.zone.exception.nonexist]/2
4577116bd7SMark de Wever     //   Preconditions: i.result == local_info::nonexistent is true.
4677116bd7SMark de Wever     // The value of __info.result is not used.
4777116bd7SMark de Wever     _LIBCPP_ASSERT_PEDANTIC(__info.result == local_info::nonexistent,
4877116bd7SMark de Wever                             "creating an nonexistent_local_time from a local_info that is not non-existent");
4977116bd7SMark de Wever   }
5077116bd7SMark de Wever 
518b9dce33SHaowei   _LIBCPP_HIDE_FROM_ABI nonexistent_local_time(const nonexistent_local_time&)            = default;
528b9dce33SHaowei   _LIBCPP_HIDE_FROM_ABI nonexistent_local_time& operator=(const nonexistent_local_time&) = default;
538b9dce33SHaowei 
5477116bd7SMark de Wever   _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI ~nonexistent_local_time() override; // exported as key function
5577116bd7SMark de Wever 
5677116bd7SMark de Wever private:
5777116bd7SMark de Wever   template <class _Duration>
5877116bd7SMark de Wever   _LIBCPP_HIDE_FROM_ABI string __create_message(const local_time<_Duration>& __time, const local_info& __info) {
5977116bd7SMark de Wever     return std::format(
6077116bd7SMark de Wever         R"({} is in a gap between
6177116bd7SMark de Wever {} {} and
6277116bd7SMark de Wever {} {} which are both equivalent to
6377116bd7SMark de Wever {} UTC)",
6477116bd7SMark de Wever         __time,
6577116bd7SMark de Wever         local_seconds{__info.first.end.time_since_epoch()} + __info.first.offset,
6677116bd7SMark de Wever         __info.first.abbrev,
6777116bd7SMark de Wever         local_seconds{__info.second.begin.time_since_epoch()} + __info.second.offset,
6877116bd7SMark de Wever         __info.second.abbrev,
6977116bd7SMark de Wever         __info.first.end);
7077116bd7SMark de Wever   }
7177116bd7SMark de Wever };
7277116bd7SMark de Wever 
7377116bd7SMark de Wever template <class _Duration>
74748023dcSNikolas Klauser [[noreturn]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI void __throw_nonexistent_local_time(
7577116bd7SMark de Wever     [[maybe_unused]] const local_time<_Duration>& __time, [[maybe_unused]] const local_info& __info) {
76ba87515fSNikolas Klauser #    if _LIBCPP_HAS_EXCEPTIONS
7777116bd7SMark de Wever   throw nonexistent_local_time(__time, __info);
7877116bd7SMark de Wever #    else
7977116bd7SMark de Wever   _LIBCPP_VERBOSE_ABORT("nonexistent_local_time was thrown in -fno-exceptions mode");
8077116bd7SMark de Wever #    endif
8177116bd7SMark de Wever }
8277116bd7SMark de Wever 
8377116bd7SMark de Wever class ambiguous_local_time : public runtime_error {
8477116bd7SMark de Wever public:
8577116bd7SMark de Wever   template <class _Duration>
8677116bd7SMark de Wever   _LIBCPP_HIDE_FROM_ABI ambiguous_local_time(const local_time<_Duration>& __time, const local_info& __info)
8777116bd7SMark de Wever       : runtime_error{__create_message(__time, __info)} {
8877116bd7SMark de Wever     // [time.zone.exception.ambig]/2
8977116bd7SMark de Wever     //   Preconditions: i.result == local_info::ambiguous is true.
9077116bd7SMark de Wever     // The value of __info.result is not used.
9177116bd7SMark de Wever     _LIBCPP_ASSERT_PEDANTIC(__info.result == local_info::ambiguous,
9277116bd7SMark de Wever                             "creating an ambiguous_local_time from a local_info that is not ambiguous");
9377116bd7SMark de Wever   }
9477116bd7SMark de Wever 
958b9dce33SHaowei   _LIBCPP_HIDE_FROM_ABI ambiguous_local_time(const ambiguous_local_time&)            = default;
968b9dce33SHaowei   _LIBCPP_HIDE_FROM_ABI ambiguous_local_time& operator=(const ambiguous_local_time&) = default;
978b9dce33SHaowei 
9877116bd7SMark de Wever   _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI ~ambiguous_local_time() override; // exported as key function
9977116bd7SMark de Wever 
10077116bd7SMark de Wever private:
10177116bd7SMark de Wever   template <class _Duration>
10277116bd7SMark de Wever   _LIBCPP_HIDE_FROM_ABI string __create_message(const local_time<_Duration>& __time, const local_info& __info) {
10377116bd7SMark de Wever     return std::format(
10477116bd7SMark de Wever         // There are two spaces after the full-stop; this has been verified
10577116bd7SMark de Wever         // in the sources of the Standard.
10677116bd7SMark de Wever         R"({0} is ambiguous.  It could be
10777116bd7SMark de Wever {0} {1} == {2} UTC or
10877116bd7SMark de Wever {0} {3} == {4} UTC)",
10977116bd7SMark de Wever         __time,
11077116bd7SMark de Wever         __info.first.abbrev,
11177116bd7SMark de Wever         __time - __info.first.offset,
11277116bd7SMark de Wever         __info.second.abbrev,
11377116bd7SMark de Wever         __time - __info.second.offset);
11477116bd7SMark de Wever   }
11577116bd7SMark de Wever };
11677116bd7SMark de Wever 
11777116bd7SMark de Wever template <class _Duration>
118748023dcSNikolas Klauser [[noreturn]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI void __throw_ambiguous_local_time(
11977116bd7SMark de Wever     [[maybe_unused]] const local_time<_Duration>& __time, [[maybe_unused]] const local_info& __info) {
120ba87515fSNikolas Klauser #    if _LIBCPP_HAS_EXCEPTIONS
12177116bd7SMark de Wever   throw ambiguous_local_time(__time, __info);
12277116bd7SMark de Wever #    else
12377116bd7SMark de Wever   _LIBCPP_VERBOSE_ABORT("ambiguous_local_time was thrown in -fno-exceptions mode");
12477116bd7SMark de Wever #    endif
12577116bd7SMark de Wever }
12677116bd7SMark de Wever 
12777116bd7SMark de Wever } // namespace chrono
12877116bd7SMark de Wever 
12977116bd7SMark de Wever #  endif // _LIBCPP_STD_VER >= 20
13077116bd7SMark de Wever 
13177116bd7SMark de Wever _LIBCPP_END_NAMESPACE_STD
13277116bd7SMark de Wever 
133*24e70e39SNikolas Klauser #endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
13477116bd7SMark de Wever 
13577116bd7SMark de Wever #endif // _LIBCPP___CHRONO_EXCEPTION_H
136