136 lines · c
1// -*- C++ -*-2//===----------------------------------------------------------------------===//3//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-exception7//8//===----------------------------------------------------------------------===//9 10// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html11 12#ifndef _LIBCPP___CHRONO_EXCEPTION_H13#define _LIBCPP___CHRONO_EXCEPTION_H14 15#include <version>16// Enable the contents of the header only when libc++ was built with experimental features enabled.17#if _LIBCPP_HAS_EXPERIMENTAL_TZDB18 19# include <__chrono/calendar.h>20# include <__chrono/local_info.h>21# include <__chrono/time_point.h>22# include <__config>23# include <__configuration/availability.h>24# include <__verbose_abort>25# include <format>26# include <stdexcept>27# include <string>28 29# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)30# pragma GCC system_header31# endif32 33_LIBCPP_BEGIN_NAMESPACE_STD34 35# if _LIBCPP_STD_VER >= 2036 37namespace chrono {38 39class nonexistent_local_time : public runtime_error {40public: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]/245 // 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");49 }50 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;53 54 _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI ~nonexistent_local_time() override; // exported as key function55 56private:57 template <class _Duration>58 _LIBCPP_HIDE_FROM_ABI string __create_message(const local_time<_Duration>& __time, const local_info& __info) {59 return std::format(60 R"({} is in a gap between61{} {} and62{} {} which are both equivalent to63{} UTC)",64 __time,65 local_seconds{__info.first.end.time_since_epoch()} + __info.first.offset,66 __info.first.abbrev,67 local_seconds{__info.second.begin.time_since_epoch()} + __info.second.offset,68 __info.second.abbrev,69 __info.first.end);70 }71};72 73template <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_EXCEPTIONS77 throw nonexistent_local_time(__time, __info);78# else79 _LIBCPP_VERBOSE_ABORT("nonexistent_local_time was thrown in -fno-exceptions mode");80# endif81}82 83class ambiguous_local_time : public runtime_error {84public: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]/289 // 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");93 }94 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;97 98 _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI ~ambiguous_local_time() override; // exported as key function99 100private:101 template <class _Duration>102 _LIBCPP_HIDE_FROM_ABI string __create_message(const local_time<_Duration>& __time, const local_info& __info) {103 return std::format(104 // There are two spaces after the full-stop; this has been verified105 // in the sources of the Standard.106 R"({0} is ambiguous. It could be107{0} {1} == {2} UTC or108{0} {3} == {4} UTC)",109 __time,110 __info.first.abbrev,111 __time - __info.first.offset,112 __info.second.abbrev,113 __time - __info.second.offset);114 }115};116 117template <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_EXCEPTIONS121 throw ambiguous_local_time(__time, __info);122# else123 _LIBCPP_VERBOSE_ABORT("ambiguous_local_time was thrown in -fno-exceptions mode");124# endif125}126 127} // namespace chrono128 129# endif // _LIBCPP_STD_VER >= 20130 131_LIBCPP_END_NAMESPACE_STD132 133#endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB134 135#endif // _LIBCPP___CHRONO_EXCEPTION_H136