mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-17 18:16:42 +00:00
[libc++][chrono] Loads leap-seconds.list in tzdb. (#82113)
This implements the loading of the leap-seconds.list file and store its contents in the tzdb struct. This adds the required `leap_seconds` member. The class leap_seconds is fully implemented including its non-member functions. Implements parts of: - P0355 Extending <chrono> to Calendars and Time Zones - P1614 The Mothership has Landed Implements: - P1981 Rename leap to leap_second - LWG3359 <chrono> leap second support should allow for negative leap seconds - LWG3383 §[time.zone.leap.nonmembers] sys_seconds should be replaced with seconds
This commit is contained in:
parent
72e2e4f7dc
commit
6f2d8cc061
@ -269,7 +269,7 @@
|
||||
"`3355 <https://wg21.link/LWG3355>`__","The memory algorithms should support move-only input iterators introduced by P1207","Prague","|Complete|","15.0","|ranges|"
|
||||
"`3356 <https://wg21.link/LWG3356>`__","``__cpp_lib_nothrow_convertible``\ should be ``__cpp_lib_is_nothrow_convertible``\ ","Prague","|Complete|","12.0"
|
||||
"`3358 <https://wg21.link/LWG3358>`__","|sect|\ [span.cons] is mistaken that ``to_address``\ can throw","Prague","|Complete|","17.0"
|
||||
"`3359 <https://wg21.link/LWG3359>`__","``<chrono>``\ leap second support should allow for negative leap seconds","Prague","","","|chrono|"
|
||||
"`3359 <https://wg21.link/LWG3359>`__","``<chrono>``\ leap second support should allow for negative leap seconds","Prague","|Complete|","19.0","|chrono|"
|
||||
"`3360 <https://wg21.link/LWG3360>`__","``three_way_comparable_with``\ is inconsistent with similar concepts","Prague","|Nothing To Do|","","|spaceship|"
|
||||
"`3362 <https://wg21.link/LWG3362>`__","Strike ``stop_source``\ 's ``operator!=``\ ","Prague","",""
|
||||
"`3363 <https://wg21.link/LWG3363>`__","``drop_while_view``\ should opt-out of ``sized_range``\ ","Prague","|Nothing To Do|","","|ranges|"
|
||||
@ -286,7 +286,7 @@
|
||||
"`3380 <https://wg21.link/LWG3380>`__","``common_type``\ and comparison categories","Prague","|Complete|","15.0","|spaceship|"
|
||||
"`3381 <https://wg21.link/LWG3381>`__","``begin``\ and ``data``\ must agree for ``contiguous_range``\ ","Prague","|Nothing To Do|","","|ranges|"
|
||||
"`3382 <https://wg21.link/LWG3382>`__","NTTP for ``pair``\ and ``array``\ ","Prague","",""
|
||||
"`3383 <https://wg21.link/LWG3383>`__","|sect|\ [time.zone.leap.nonmembers] ``sys_seconds``\ should be replaced with ``seconds``\ ","Prague","","","|chrono|"
|
||||
"`3383 <https://wg21.link/LWG3383>`__","|sect|\ [time.zone.leap.nonmembers] ``sys_seconds``\ should be replaced with ``seconds``\ ","Prague","|Complete|","19.0","|chrono|"
|
||||
"`3384 <https://wg21.link/LWG3384>`__","``transform_view::*sentinel*``\ has an incorrect ``operator-``\ ","Prague","|Complete|","15.0","|ranges|"
|
||||
"`3385 <https://wg21.link/LWG3385>`__","``common_iterator``\ is not sufficiently constrained for non-copyable iterators","Prague","|Complete|","15.0","|ranges|"
|
||||
"`3387 <https://wg21.link/LWG3387>`__","|sect|\ [range.reverse.view] ``reverse_view<V>``\ unintentionally requires ``range<const V>``\ ","Prague","|Complete|","15.0","|ranges|"
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -179,7 +179,7 @@
|
||||
"`P1970R2 <https://wg21.link/P1970R2>`__","LWG","Consistency for size() functions: Add ranges::ssize","Prague","|Complete|","15.0","|ranges|"
|
||||
"`P1973R1 <https://wg21.link/P1973R1>`__","LWG","Rename ""_default_init"" Functions, Rev1","Prague","|Complete|","16.0"
|
||||
"`P1976R2 <https://wg21.link/P1976R2>`__","LWG","Fixed-size span construction from dynamic range","Prague","|Complete|","11.0","|ranges|"
|
||||
"`P1981R0 <https://wg21.link/P1981R0>`__","LWG","Rename leap to leap_second","Prague","* *",""
|
||||
"`P1981R0 <https://wg21.link/P1981R0>`__","LWG","Rename leap to leap_second","Prague","|Complete|","19.0","|chrono|"
|
||||
"`P1982R0 <https://wg21.link/P1982R0>`__","LWG","Rename link to time_zone_link","Prague","|Complete|","19.0","|chrono|"
|
||||
"`P1983R0 <https://wg21.link/P1983R0>`__","LWG","Wording for GB301, US296, US292, US291, and US283","Prague","|Complete|","15.0","|ranges|"
|
||||
"`P1994R1 <https://wg21.link/P1994R1>`__","LWG","elements_view needs its own sentinel","Prague","|Complete|","16.0","|ranges|"
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -173,7 +173,7 @@ Section,Description,Dependencies,Assignee,Complete
|
||||
| `year_month_weekday_last <https://reviews.llvm.org/D152699>`_",None,Hristo Hristov,|Complete|
|
||||
`[time.zone.nonmembers] <https://wg21.link/time.zone.nonmembers>`_,"`chrono::time_zone`",A ``<chrono>`` implementation,Mark de Wever,|Complete|
|
||||
`[time.zone.zonedtime.nonmembers] <https://wg21.link/time.zone.zonedtime.nonmembers>`_,"`chrono::zoned_time`",A ``<chrono>`` implementation,Mark de Wever,|In Progress|
|
||||
`[time.zone.leap.nonmembers] <https://wg21.link/time.zone.leap.nonmembers>`_,"`chrono::time_leap_seconds`",A ``<chrono>`` implementation,Mark de Wever,|In Progress|
|
||||
`[time.zone.leap.nonmembers] <https://wg21.link/time.zone.leap.nonmembers>`_,"`chrono::time_leap_seconds`",A ``<chrono>`` implementation,Mark de Wever,|Complete|
|
||||
`[time.zone.link.nonmembers] <https://wg21.link/time.zone.link.nonmembers>`_,"`chrono::time_zone_link`",A ``<chrono>`` implementation,Mark de Wever,|Complete|
|
||||
- `5.13 Clause 28: Localization library <https://wg21.link/p1614r2#clause-28-localization-library>`_,,,,
|
||||
"| `[locale] <https://wg21.link/locale>`_
|
||||
|
|
@ -282,6 +282,7 @@ set(files
|
||||
__chrono/formatter.h
|
||||
__chrono/hh_mm_ss.h
|
||||
__chrono/high_resolution_clock.h
|
||||
__chrono/leap_second.h
|
||||
__chrono/literals.h
|
||||
__chrono/month.h
|
||||
__chrono/month_weekday.h
|
||||
|
126
libcxx/include/__chrono/leap_second.h
Normal file
126
libcxx/include/__chrono/leap_second.h
Normal file
@ -0,0 +1,126 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html
|
||||
|
||||
#ifndef _LIBCPP___CHRONO_LEAP_SECOND_H
|
||||
#define _LIBCPP___CHRONO_LEAP_SECOND_H
|
||||
|
||||
#include <version>
|
||||
// Enable the contents of the header only when libc++ was built with experimental features enabled.
|
||||
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
|
||||
|
||||
# include <__chrono/duration.h>
|
||||
# include <__chrono/system_clock.h>
|
||||
# include <__chrono/time_point.h>
|
||||
# include <__compare/ordering.h>
|
||||
# include <__compare/three_way_comparable.h>
|
||||
# include <__config>
|
||||
|
||||
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
# endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
# if _LIBCPP_STD_VER >= 20
|
||||
|
||||
namespace chrono {
|
||||
|
||||
class leap_second {
|
||||
public:
|
||||
struct __constructor_tag;
|
||||
[[nodiscard]]
|
||||
_LIBCPP_HIDE_FROM_ABI explicit constexpr leap_second(__constructor_tag&&, sys_seconds __date, seconds __value)
|
||||
: __date_(__date), __value_(__value) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI leap_second(const leap_second&) = default;
|
||||
_LIBCPP_HIDE_FROM_ABI leap_second& operator=(const leap_second&) = default;
|
||||
|
||||
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr sys_seconds date() const noexcept { return __date_; }
|
||||
|
||||
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr seconds value() const noexcept { return __value_; }
|
||||
|
||||
private:
|
||||
sys_seconds __date_;
|
||||
seconds __value_;
|
||||
};
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI inline constexpr bool operator==(const leap_second& __x, const leap_second& __y) {
|
||||
return __x.date() == __y.date();
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI inline constexpr strong_ordering operator<=>(const leap_second& __x, const leap_second& __y) {
|
||||
return __x.date() <=> __y.date();
|
||||
}
|
||||
|
||||
template <class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const leap_second& __x, const sys_time<_Duration>& __y) {
|
||||
return __x.date() == __y;
|
||||
}
|
||||
|
||||
template <class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const leap_second& __x, const sys_time<_Duration>& __y) {
|
||||
return __x.date() < __y;
|
||||
}
|
||||
|
||||
template <class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const sys_time<_Duration>& __x, const leap_second& __y) {
|
||||
return __x < __y.date();
|
||||
}
|
||||
|
||||
template <class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const leap_second& __x, const sys_time<_Duration>& __y) {
|
||||
return __y < __x;
|
||||
}
|
||||
|
||||
template <class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const sys_time<_Duration>& __x, const leap_second& __y) {
|
||||
return __y < __x;
|
||||
}
|
||||
|
||||
template <class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const leap_second& __x, const sys_time<_Duration>& __y) {
|
||||
return !(__y < __x);
|
||||
}
|
||||
|
||||
template <class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const sys_time<_Duration>& __x, const leap_second& __y) {
|
||||
return !(__y < __x);
|
||||
}
|
||||
|
||||
template <class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const leap_second& __x, const sys_time<_Duration>& __y) {
|
||||
return !(__x < __y);
|
||||
}
|
||||
|
||||
template <class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const sys_time<_Duration>& __x, const leap_second& __y) {
|
||||
return !(__x < __y);
|
||||
}
|
||||
|
||||
# ifndef _LIBCPP_COMPILER_GCC
|
||||
// This requirement cause a compilation loop in GCC-13 and running out of memory.
|
||||
// TODO TZDB Test whether GCC-14 fixes this.
|
||||
template <class _Duration>
|
||||
requires three_way_comparable_with<sys_seconds, sys_time<_Duration>>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto operator<=>(const leap_second& __x, const sys_time<_Duration>& __y) {
|
||||
return __x.date() <=> __y;
|
||||
}
|
||||
# endif
|
||||
|
||||
} // namespace chrono
|
||||
|
||||
# endif //_LIBCPP_STD_VER >= 20
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
|
||||
|
||||
#endif // _LIBCPP___CHRONO_LEAP_SECOND_H
|
@ -16,6 +16,7 @@
|
||||
// Enable the contents of the header only when libc++ was built with experimental features enabled.
|
||||
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_TZDB)
|
||||
|
||||
# include <__chrono/leap_second.h>
|
||||
# include <__chrono/time_zone.h>
|
||||
# include <__chrono/time_zone_link.h>
|
||||
# include <__config>
|
||||
@ -40,6 +41,8 @@ struct tzdb {
|
||||
string version;
|
||||
vector<time_zone> zones;
|
||||
vector<time_zone_link> links;
|
||||
|
||||
vector<leap_second> leap_seconds;
|
||||
};
|
||||
|
||||
} // namespace chrono
|
||||
|
@ -688,6 +688,7 @@ struct tzdb {
|
||||
string version;
|
||||
vector<time_zone> zones;
|
||||
vector<time_zone_link> links;
|
||||
vector<leap_second> leap_seconds;
|
||||
};
|
||||
|
||||
class tzdb_list { // C++20
|
||||
@ -731,6 +732,43 @@ class time_zone {
|
||||
bool operator==(const time_zone& x, const time_zone& y) noexcept; // C++20
|
||||
strong_ordering operator<=>(const time_zone& x, const time_zone& y) noexcept; // C++20
|
||||
|
||||
// [time.zone.leap], leap second support
|
||||
class leap_second { // C++20
|
||||
public:
|
||||
leap_second(const leap_second&) = default;
|
||||
leap_second& operator=(const leap_second&) = default;
|
||||
|
||||
// unspecified additional constructors
|
||||
|
||||
constexpr sys_seconds date() const noexcept;
|
||||
constexpr seconds value() const noexcept;
|
||||
};
|
||||
|
||||
constexpr bool operator==(const leap_second& x, const leap_second& y); // C++20
|
||||
constexpr strong_ordering operator<=>(const leap_second& x, const leap_second& y);
|
||||
|
||||
template<class Duration> // C++20
|
||||
constexpr bool operator==(const leap_second& x, const sys_time<Duration>& y);
|
||||
template<class Duration> // C++20
|
||||
constexpr bool operator< (const leap_second& x, const sys_time<Duration>& y);
|
||||
template<class Duration> // C++20
|
||||
constexpr bool operator< (const sys_time<Duration>& x, const leap_second& y);
|
||||
template<class Duration> // C++20
|
||||
constexpr bool operator> (const leap_second& x, const sys_time<Duration>& y);
|
||||
template<class Duration> // C++20
|
||||
constexpr bool operator> (const sys_time<Duration>& x, const leap_second& y);
|
||||
template<class Duration> // C++20
|
||||
constexpr bool operator<=(const leap_second& x, const sys_time<Duration>& y);
|
||||
template<class Duration> // C++20
|
||||
constexpr bool operator<=(const sys_time<Duration>& x, const leap_second& y);
|
||||
template<class Duration> // C++20
|
||||
constexpr bool operator>=(const leap_second& x, const sys_time<Duration>& y);
|
||||
template<class Duration> // C++20
|
||||
constexpr bool operator>=(const sys_time<Duration>& x, const leap_second& y);
|
||||
template<class Duration> // C++20
|
||||
requires three_way_comparable_with<sys_seconds, sys_time<Duration>>
|
||||
constexpr auto operator<=>(const leap_second& x, const sys_time<Duration>& y);
|
||||
|
||||
// [time.zone.link], class time_zone_link
|
||||
class time_zone_link { // C++20
|
||||
public:
|
||||
@ -862,6 +900,7 @@ constexpr chrono::year operator ""y(unsigned lo
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) && \
|
||||
!defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
# include <__chrono/leap_second.h>
|
||||
# include <__chrono/time_zone.h>
|
||||
# include <__chrono/time_zone_link.h>
|
||||
# include <__chrono/tzdb.h>
|
||||
|
@ -279,6 +279,7 @@
|
||||
{ include: [ "<__chrono/formatter.h>", "private", "<chrono>", "public" ] },
|
||||
{ include: [ "<__chrono/hh_mm_ss.h>", "private", "<chrono>", "public" ] },
|
||||
{ include: [ "<__chrono/high_resolution_clock.h>", "private", "<chrono>", "public" ] },
|
||||
{ include: [ "<__chrono/leap_second.h>", "private", "<chrono>", "public" ] },
|
||||
{ include: [ "<__chrono/literals.h>", "private", "<chrono>", "public" ] },
|
||||
{ include: [ "<__chrono/month.h>", "private", "<chrono>", "public" ] },
|
||||
{ include: [ "<__chrono/month_weekday.h>", "private", "<chrono>", "public" ] },
|
||||
|
@ -1145,6 +1145,7 @@ module std_private_chrono_high_resolution_clock [system] {
|
||||
export std_private_chrono_steady_clock
|
||||
export std_private_chrono_system_clock
|
||||
}
|
||||
module std_private_chrono_leap_second [system] { header "__chrono/leap_second.h" }
|
||||
module std_private_chrono_literals [system] { header "__chrono/literals.h" }
|
||||
module std_private_chrono_month [system] { header "__chrono/month.h" }
|
||||
module std_private_chrono_month_weekday [system] { header "__chrono/month_weekday.h" }
|
||||
|
@ -208,10 +208,7 @@ export namespace std {
|
||||
using std::chrono::reload_tzdb;
|
||||
using std::chrono::remote_version;
|
||||
|
||||
# endif // !defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) &&
|
||||
// !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
|
||||
# if 0
|
||||
# if 0
|
||||
// [time.zone.exception], exception classes
|
||||
using std::chrono::ambiguous_local_time;
|
||||
using std::chrono::nonexistent_local_time;
|
||||
@ -221,11 +218,11 @@ export namespace std {
|
||||
|
||||
// [time.zone.timezone], class time_zone
|
||||
using std::chrono::choose;
|
||||
# endif
|
||||
# ifdef _LIBCPP_ENABLE_EXPERIMENTAL
|
||||
# endif // if 0
|
||||
|
||||
using std::chrono::time_zone;
|
||||
# endif
|
||||
# if 0
|
||||
|
||||
# if 0
|
||||
|
||||
// [time.zone.zonedtraits], class template zoned_traits
|
||||
using std::chrono::zoned_traits;
|
||||
@ -234,22 +231,23 @@ export namespace std {
|
||||
using std::chrono::zoned_time;
|
||||
|
||||
using std::chrono::zoned_seconds;
|
||||
# endif // if 0
|
||||
|
||||
// [time.zone.leap], leap second support
|
||||
using std::chrono::leap_second;
|
||||
# endif
|
||||
|
||||
# ifdef _LIBCPP_ENABLE_EXPERIMENTAL
|
||||
// [time.zone.link], class time_zone_link
|
||||
using std::chrono::time_zone_link;
|
||||
# endif
|
||||
|
||||
# if 0
|
||||
# if 0
|
||||
// [time.format], formatting
|
||||
using std::chrono::local_time_format;
|
||||
# endif
|
||||
#endif // _LIBCPP_ENABLE_EXPERIMENTAL
|
||||
} // namespace chrono
|
||||
# endif
|
||||
# endif // _LIBCPP_ENABLE_EXPERIMENTAL
|
||||
#endif // !defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) &&
|
||||
// !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
|
||||
} // namespace chrono
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
|
||||
using std::formatter;
|
||||
|
@ -334,6 +334,7 @@ endif()
|
||||
|
||||
if (LIBCXX_ENABLE_LOCALIZATION AND LIBCXX_ENABLE_FILESYSTEM AND LIBCXX_ENABLE_TIME_ZONE_DATABASE)
|
||||
list(APPEND LIBCXX_EXPERIMENTAL_SOURCES
|
||||
include/tzdb/leap_second_private.h
|
||||
include/tzdb/time_zone_link_private.h
|
||||
include/tzdb/time_zone_private.h
|
||||
include/tzdb/types_private.h
|
||||
|
27
libcxx/src/include/tzdb/leap_second_private.h
Normal file
27
libcxx/src/include/tzdb/leap_second_private.h
Normal file
@ -0,0 +1,27 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html
|
||||
|
||||
#ifndef _LIBCPP_SRC_INCLUDE_TZDB_LEAP_SECOND_PRIVATE_H
|
||||
#define _LIBCPP_SRC_INCLUDE_TZDB_LEAP_SECOND_PRIVATE_H
|
||||
|
||||
#include <chrono>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace chrono {
|
||||
|
||||
struct leap_second::__constructor_tag {};
|
||||
|
||||
} // namespace chrono
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_SRC_INCLUDE_TZDB_LEAP_SECOND_PRIVATE_H
|
@ -15,6 +15,7 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "include/tzdb/leap_second_private.h"
|
||||
#include "include/tzdb/time_zone_link_private.h"
|
||||
#include "include/tzdb/time_zone_private.h"
|
||||
#include "include/tzdb/types_private.h"
|
||||
@ -622,6 +623,36 @@ static void __parse_tzdata(tzdb& __db, __tz::__rules_storage_type& __rules, istr
|
||||
}
|
||||
}
|
||||
|
||||
static void __parse_leap_seconds(vector<leap_second>& __leap_seconds, istream&& __input) {
|
||||
// The file stores dates since 1 January 1900, 00:00:00, we want
|
||||
// seconds since 1 January 1970.
|
||||
constexpr auto __offset = sys_days{1970y / January / 1} - sys_days{1900y / January / 1};
|
||||
|
||||
while (true) {
|
||||
switch (__input.peek()) {
|
||||
case istream::traits_type::eof():
|
||||
return;
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
__input.get();
|
||||
continue;
|
||||
|
||||
case '#':
|
||||
chrono::__skip_line(__input);
|
||||
continue;
|
||||
}
|
||||
|
||||
sys_seconds __date = sys_seconds{seconds{chrono::__parse_integral(__input, false)}} - __offset;
|
||||
chrono::__skip_mandatory_whitespace(__input);
|
||||
seconds __value{chrono::__parse_integral(__input, false)};
|
||||
chrono::__skip_line(__input);
|
||||
|
||||
__leap_seconds.emplace_back(leap_second::__constructor_tag{}, __date, __value);
|
||||
}
|
||||
}
|
||||
|
||||
void __init_tzdb(tzdb& __tzdb, __tz::__rules_storage_type& __rules) {
|
||||
filesystem::path __root = chrono::__libcpp_tzdb_directory();
|
||||
ifstream __tzdata{__root / "tzdata.zi"};
|
||||
@ -631,6 +662,17 @@ void __init_tzdb(tzdb& __tzdb, __tz::__rules_storage_type& __rules) {
|
||||
std::ranges::sort(__tzdb.zones);
|
||||
std::ranges::sort(__tzdb.links);
|
||||
std::ranges::sort(__rules, {}, [](const auto& p) { return p.first; });
|
||||
|
||||
// There are two files with the leap second information
|
||||
// - leapseconds as specified by zic
|
||||
// - leap-seconds.list the source data
|
||||
// The latter is much easier to parse, it seems Howard shares that
|
||||
// opinion.
|
||||
chrono::__parse_leap_seconds(__tzdb.leap_seconds, ifstream{__root / "leap-seconds.list"});
|
||||
// The Standard requires the leap seconds to be sorted. The file
|
||||
// leap-seconds.list usually provides them in sorted order, but that is not
|
||||
// guaranteed so we ensure it here.
|
||||
std::ranges::sort(__tzdb.leap_seconds);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -26,6 +26,7 @@
|
||||
// These types have "private" constructors.
|
||||
extern std::chrono::time_zone tz;
|
||||
extern std::chrono::time_zone_link link;
|
||||
extern std::chrono::leap_second leap;
|
||||
|
||||
void test() {
|
||||
std::chrono::tzdb_list& list = std::chrono::get_tzdb_list();
|
||||
@ -51,4 +52,9 @@ void test() {
|
||||
operator==(link, link);
|
||||
operator<=>(link, link);
|
||||
}
|
||||
|
||||
{
|
||||
leap.date();
|
||||
leap.value();
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
// These types have "private" constructors.
|
||||
extern std::chrono::time_zone tz;
|
||||
extern std::chrono::time_zone_link link;
|
||||
extern std::chrono::leap_second leap;
|
||||
|
||||
void test() {
|
||||
std::chrono::tzdb_list& list = std::chrono::get_tzdb_list();
|
||||
@ -51,4 +52,9 @@ void test() {
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
operator<=>(link, link);
|
||||
}
|
||||
|
||||
{
|
||||
leap.date(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
leap.value(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,119 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||
|
||||
// XFAIL: libcpp-has-no-incomplete-tzdb
|
||||
// XFAIL: availability-tzdb-missing
|
||||
|
||||
// <chrono>
|
||||
|
||||
// Tests the IANA database leap seconds parsing and operations.
|
||||
// This is not part of the public tzdb interface.
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "assert_macros.h"
|
||||
#include "concat_macros.h"
|
||||
#include "filesystem_test_helper.h"
|
||||
#include "test_tzdb.h"
|
||||
|
||||
scoped_test_env env;
|
||||
[[maybe_unused]] const std::filesystem::path dir = env.create_dir("zoneinfo");
|
||||
const std::filesystem::path tzdata = env.create_file("zoneinfo/tzdata.zi");
|
||||
const std::filesystem::path leap_seconds = env.create_file("zoneinfo/leap-seconds.list");
|
||||
|
||||
std::string_view std::chrono::__libcpp_tzdb_directory() {
|
||||
static std::string result = dir.string();
|
||||
return result;
|
||||
}
|
||||
|
||||
void write(std::string_view input) {
|
||||
static int version = 0;
|
||||
|
||||
std::ofstream f{tzdata};
|
||||
f << "# version " << version++ << '\n';
|
||||
std::ofstream{leap_seconds}.write(input.data(), input.size());
|
||||
}
|
||||
|
||||
static const std::chrono::tzdb& parse(std::string_view input) {
|
||||
write(input);
|
||||
return std::chrono::reload_tzdb();
|
||||
}
|
||||
|
||||
static void test_exception(std::string_view input, [[maybe_unused]] std::string_view what) {
|
||||
write(input);
|
||||
|
||||
TEST_VALIDATE_EXCEPTION(
|
||||
std::runtime_error,
|
||||
[&]([[maybe_unused]] const std::runtime_error& e) {
|
||||
TEST_LIBCPP_REQUIRE(
|
||||
e.what() == what,
|
||||
TEST_WRITE_CONCATENATED("\nExpected exception ", what, "\nActual exception ", e.what(), '\n'));
|
||||
},
|
||||
TEST_IGNORE_NODISCARD std::chrono::reload_tzdb());
|
||||
}
|
||||
|
||||
static void test_invalid() {
|
||||
test_exception("0", "corrupt tzdb: expected a non-zero digit");
|
||||
|
||||
test_exception("1", "corrupt tzdb: expected whitespace");
|
||||
|
||||
test_exception("1 ", "corrupt tzdb: expected a non-zero digit");
|
||||
|
||||
test_exception("5764607523034234880 2", "corrupt tzdb: integral too large");
|
||||
}
|
||||
|
||||
static void test_leap_seconds() {
|
||||
using namespace std::chrono;
|
||||
|
||||
// Test whether loading also sorts the entries in the proper order.
|
||||
const tzdb& result = parse(
|
||||
R"(
|
||||
2303683200 12 # 1 Jan 1973
|
||||
2287785600 11 # 1 Jul 1972
|
||||
2272060800 10 # 1 Jan 1972
|
||||
86400 1 # 2 Jan 1900 Dummy entry to test before 1970
|
||||
|
||||
# largest accepted value by the parser
|
||||
5764607523034234879 2
|
||||
)");
|
||||
|
||||
assert(result.leap_seconds.size() == 5);
|
||||
|
||||
assert(result.leap_seconds[0].date() == sys_seconds{sys_days{1900y / January / 2}});
|
||||
assert(result.leap_seconds[0].value() == 1s);
|
||||
|
||||
assert(result.leap_seconds[1].date() == sys_seconds{sys_days{1972y / January / 1}});
|
||||
assert(result.leap_seconds[1].value() == 10s);
|
||||
|
||||
assert(result.leap_seconds[2].date() == sys_seconds{sys_days{1972y / July / 1}});
|
||||
assert(result.leap_seconds[2].value() == 11s);
|
||||
|
||||
assert(result.leap_seconds[3].date() == sys_seconds{sys_days{1973y / January / 1}});
|
||||
assert(result.leap_seconds[3].value() == 12s);
|
||||
|
||||
assert(result.leap_seconds[4].date() ==
|
||||
sys_seconds{5764607523034234879s
|
||||
// The database uses 1900-01-01 as epoch.
|
||||
- std::chrono::duration_cast<std::chrono::seconds>(
|
||||
sys_days{1970y / January / 1} - sys_days{1900y / January / 1})});
|
||||
assert(result.leap_seconds[4].value() == 2s);
|
||||
}
|
||||
|
||||
int main(int, const char**) {
|
||||
test_invalid();
|
||||
test_leap_seconds();
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||
|
||||
// XFAIL: libcpp-has-no-incomplete-tzdb
|
||||
// XFAIL: availability-tzdb-missing
|
||||
|
||||
// <chrono>
|
||||
|
||||
// Tests the loaded leap seconds match
|
||||
// https://eel.is/c++draft/time.zone.leap.overview#2
|
||||
//
|
||||
// At the moment of writing that list is the actual list.
|
||||
// If in the future more leap seconds are added, the returned list may have more
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <ranges>
|
||||
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
// The list of leap seconds matching
|
||||
// https://eel.is/c++draft/time.zone.leap.overview#2
|
||||
// At the moment of writing that list is the actual list in the IANA database.
|
||||
// If in the future more leap seconds can be added.
|
||||
static const std::array leap_seconds = {
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1972y / std::chrono::January / 1}}, 10s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1972y / std::chrono::July / 1}}, 11s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1973y / std::chrono::January / 1}}, 12s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1974y / std::chrono::January / 1}}, 13s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1975y / std::chrono::January / 1}}, 14s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1976y / std::chrono::January / 1}}, 15s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1977y / std::chrono::January / 1}}, 16s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1978y / std::chrono::January / 1}}, 17s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1979y / std::chrono::January / 1}}, 18s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1980y / std::chrono::January / 1}}, 19s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1981y / std::chrono::July / 1}}, 20s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1982y / std::chrono::July / 1}}, 21s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1983y / std::chrono::July / 1}}, 22s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1985y / std::chrono::July / 1}}, 23s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1988y / std::chrono::January / 1}}, 24s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1990y / std::chrono::January / 1}}, 25s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1991y / std::chrono::January / 1}}, 26s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1992y / std::chrono::July / 1}}, 27s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1993y / std::chrono::July / 1}}, 28s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1994y / std::chrono::July / 1}}, 29s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1996y / std::chrono::January / 1}}, 30s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1997y / std::chrono::July / 1}}, 31s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{1999y / std::chrono::January / 1}}, 32s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{2006y / std::chrono::January / 1}}, 33s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{2009y / std::chrono::January / 1}}, 34s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{2012y / std::chrono::July / 1}}, 35s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{2015y / std::chrono::July / 1}}, 36s),
|
||||
std::make_pair(std::chrono::sys_seconds{std::chrono::sys_days{2017y / std::chrono::January / 1}}, 37s)};
|
||||
|
||||
int main(int, const char**) {
|
||||
const std::chrono::tzdb& tzdb = std::chrono::get_tzdb();
|
||||
|
||||
assert(tzdb.leap_seconds.size() >= leap_seconds.size());
|
||||
assert((std::ranges::equal(
|
||||
leap_seconds,
|
||||
tzdb.leap_seconds | std::ranges::views::take(leap_seconds.size()),
|
||||
[](const auto& lhs, const auto& rhs) { return lhs.first == rhs.date() && lhs.second == rhs.value(); })));
|
||||
|
||||
return 0;
|
||||
}
|
@ -35,5 +35,8 @@ int main(int, const char**) {
|
||||
assert(std::ranges::is_sorted(db.links));
|
||||
assert(std::ranges::adjacent_find(db.links) == db.links.end()); // is unique?
|
||||
|
||||
assert(!db.leap_seconds.empty());
|
||||
assert(std::ranges::is_sorted(db.leap_seconds));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -37,11 +37,9 @@ int main(int, const char**) {
|
||||
tzdb.version = "version";
|
||||
assert(tzdb.version == "version");
|
||||
|
||||
[[maybe_unused]] std::vector<std::chrono::time_zone>& zones = tzdb.zones;
|
||||
|
||||
[[maybe_unused]] std::vector<std::chrono::time_zone>& zones = tzdb.zones;
|
||||
[[maybe_unused]] std::vector<std::chrono::time_zone_link>& links = tzdb.links;
|
||||
|
||||
// TODO TZDB add the leap data member
|
||||
[[maybe_unused]] std::vector<std::chrono::leap_second>& leap_seconds = tzdb.leap_seconds;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,71 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||
|
||||
// XFAIL: libcpp-has-no-incomplete-tzdb
|
||||
// XFAIL: availability-tzdb-missing
|
||||
|
||||
// <chrono>
|
||||
|
||||
// class leap_second
|
||||
// {
|
||||
// leap_second& operator=(const leap_second&) = default;
|
||||
//
|
||||
// ...
|
||||
// };
|
||||
|
||||
#include <chrono>
|
||||
#include <concepts>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
// Add the include path required by test_chrono_leap_second.h when using libc++.
|
||||
// ADDITIONAL_COMPILE_FLAGS(stdlib=libc++): -I %{libcxx-dir}/src/include
|
||||
#include "test_chrono_leap_second.h"
|
||||
|
||||
constexpr bool test() {
|
||||
std::chrono::leap_second a =
|
||||
test_leap_second_create(std::chrono::sys_seconds{std::chrono::seconds{0}}, std::chrono::seconds{1});
|
||||
std::chrono::leap_second b =
|
||||
test_leap_second_create(std::chrono::sys_seconds{std::chrono::seconds{10}}, std::chrono::seconds{15});
|
||||
|
||||
// operator== only compares the date member.
|
||||
assert(a.date() != b.date());
|
||||
assert(a.value() != b.value());
|
||||
|
||||
{
|
||||
std::same_as<std::chrono::leap_second&> decltype(auto) result(b = a);
|
||||
assert(std::addressof(result) == std::addressof(b));
|
||||
|
||||
assert(a.date() == b.date());
|
||||
assert(a.value() == b.value());
|
||||
}
|
||||
|
||||
{
|
||||
// Tests an rvalue uses the copy assignment.
|
||||
std::same_as<std::chrono::leap_second&> decltype(auto) result(b = std::move(a));
|
||||
assert(std::addressof(result) == std::addressof(b));
|
||||
|
||||
assert(a.date() == b.date());
|
||||
assert(a.value() == b.value());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, const char**) {
|
||||
static_assert(std::is_copy_assignable_v<std::chrono::leap_second>);
|
||||
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||
|
||||
// XFAIL: libcpp-has-no-incomplete-tzdb
|
||||
// XFAIL: availability-tzdb-missing
|
||||
|
||||
// <chrono>
|
||||
|
||||
// class leap_second
|
||||
// {
|
||||
// leap_second(const leap_second&) = default;
|
||||
//
|
||||
// ...
|
||||
// };
|
||||
|
||||
#include <chrono>
|
||||
#include <concepts>
|
||||
#include <cassert>
|
||||
|
||||
// Add the include path required by test_chrono_leap_second.h when using libc++.
|
||||
// ADDITIONAL_COMPILE_FLAGS(stdlib=libc++): -I %{libcxx-dir}/src/include
|
||||
#include "test_chrono_leap_second.h"
|
||||
|
||||
constexpr bool test() {
|
||||
std::chrono::leap_second a =
|
||||
test_leap_second_create(std::chrono::sys_seconds{std::chrono::seconds{0}}, std::chrono::seconds{1});
|
||||
|
||||
{
|
||||
std::chrono::leap_second b = a;
|
||||
|
||||
// operator== only compares the date member.
|
||||
assert(a.date() == b.date());
|
||||
assert(a.value() == b.value());
|
||||
}
|
||||
|
||||
#ifdef _LIBCPP_VERSION
|
||||
{
|
||||
// Tests an rvalue uses the copy constructor.
|
||||
// Since implementations are allowed to add additional constructors this is
|
||||
// a libc++ specific test.
|
||||
std::chrono::leap_second b = std::move(a);
|
||||
|
||||
// operator== only compares the date member.
|
||||
assert(a.date() == b.date());
|
||||
assert(a.value() == b.value());
|
||||
}
|
||||
// libc++ does not provide a default constructor.
|
||||
static_assert(!std::is_default_constructible_v<std::chrono::leap_second>);
|
||||
#endif // _LIBCPP_VERSION
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, const char**) {
|
||||
static_assert(std::copy_constructible<std::chrono::leap_second>);
|
||||
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||
|
||||
// XFAIL: libcpp-has-no-incomplete-tzdb
|
||||
// XFAIL: availability-tzdb-missing
|
||||
|
||||
// <chrono>
|
||||
|
||||
// class leap_second;
|
||||
|
||||
// constexpr sys_seconds date() const noexcept;
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Add the include path required by test_chrono_leap_second.h when using libc++.
|
||||
// ADDITIONAL_COMPILE_FLAGS(stdlib=libc++): -I %{libcxx-dir}/src/include
|
||||
#include "test_chrono_leap_second.h"
|
||||
|
||||
constexpr void test(const std::chrono::leap_second leap_second, std::chrono::sys_seconds expected) {
|
||||
std::same_as<std::chrono::sys_seconds> auto date = leap_second.date();
|
||||
assert(date == expected);
|
||||
static_assert(noexcept(leap_second.date()));
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
test(test_leap_second_create(std::chrono::sys_seconds{std::chrono::seconds{0}}, std::chrono::seconds{1}),
|
||||
std::chrono::sys_seconds{std::chrono::seconds{0}});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, const char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
// test with the real tzdb
|
||||
const std::chrono::tzdb& tzdb = std::chrono::get_tzdb();
|
||||
assert(!tzdb.leap_seconds.empty());
|
||||
test(tzdb.leap_seconds[0], tzdb.leap_seconds[0].date());
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||
|
||||
// XFAIL: libcpp-has-no-incomplete-tzdb
|
||||
// XFAIL: availability-tzdb-missing
|
||||
|
||||
// <chrono>
|
||||
|
||||
// class leap_second;
|
||||
|
||||
// constexpr seconds value() const noexcept;
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Add the include path required by test_chrono_leap_second.h when using libc++.
|
||||
// ADDITIONAL_COMPILE_FLAGS(stdlib=libc++): -I %{libcxx-dir}/src/include
|
||||
#include "test_chrono_leap_second.h"
|
||||
|
||||
constexpr void test(const std::chrono::leap_second leap_second, std::chrono::seconds expected) {
|
||||
std::same_as<std::chrono::seconds> auto value = leap_second.value();
|
||||
assert(value == expected);
|
||||
static_assert(noexcept(leap_second.value()));
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
test(test_leap_second_create(std::chrono::sys_seconds{std::chrono::seconds{0}}, std::chrono::seconds{1}),
|
||||
std::chrono::seconds{1});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, const char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
// test with the real tzdb
|
||||
const std::chrono::tzdb& tzdb = std::chrono::get_tzdb();
|
||||
assert(!tzdb.leap_seconds.empty());
|
||||
test(tzdb.leap_seconds[0], tzdb.leap_seconds[0].value());
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||
|
||||
// TODO TZDB test whether this can be enabled with gcc 14.
|
||||
// UNSUPPORTED: gcc-13
|
||||
|
||||
// XFAIL: libcpp-has-no-incomplete-tzdb
|
||||
// XFAIL: availability-tzdb-missing
|
||||
|
||||
// <chrono>
|
||||
|
||||
// class leap_second;
|
||||
|
||||
//constexpr bool operator==(const leap_second& x, const leap_second& y); // C++20
|
||||
//constexpr strong_ordering operator<=>(const leap_second& x, const leap_second& y);
|
||||
//
|
||||
//template<class Duration>
|
||||
// constexpr bool operator==(const leap_second& x, const sys_time<Duration>& y);
|
||||
//template<class Duration>
|
||||
// constexpr bool operator< (const leap_second& x, const sys_time<Duration>& y);
|
||||
//template<class Duration>
|
||||
// constexpr bool operator< (const sys_time<Duration>& x, const leap_second& y);
|
||||
//template<class Duration>
|
||||
// constexpr bool operator> (const leap_second& x, const sys_time<Duration>& y);
|
||||
//template<class Duration>
|
||||
// constexpr bool operator> (const sys_time<Duration>& x, const leap_second& y);
|
||||
//template<class Duration>
|
||||
// constexpr bool operator<=(const leap_second& x, const sys_time<Duration>& y);
|
||||
//template<class Duration>
|
||||
// constexpr bool operator<=(const sys_time<Duration>& x, const leap_second& y);
|
||||
//template<class Duration>
|
||||
// constexpr bool operator>=(const leap_second& x, const sys_time<Duration>& y);
|
||||
//template<class Duration>
|
||||
// constexpr bool operator>=(const sys_time<Duration>& x, const leap_second& y);
|
||||
//template<class Duration>
|
||||
// requires three_way_comparable_with<sys_seconds, sys_time<Duration>>
|
||||
// constexpr auto operator<=>(const leap_second& x, const sys_time<Duration>& y);
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_comparisons.h"
|
||||
|
||||
// Add the include path required by test_chrono_leap_second.h when using libc++.
|
||||
// ADDITIONAL_COMPILE_FLAGS(stdlib=libc++): -I %{libcxx-dir}/src/include
|
||||
#include "test_chrono_leap_second.h"
|
||||
|
||||
constexpr void test_comparison(const std::chrono::leap_second lhs, const std::chrono::leap_second rhs) {
|
||||
AssertOrderReturn<std::strong_ordering, std::chrono::leap_second>();
|
||||
assert(testOrder(lhs, rhs, std::strong_ordering::less));
|
||||
|
||||
AssertOrderReturn<std::strong_ordering, std::chrono::leap_second, std::chrono::sys_seconds>();
|
||||
assert(testOrder(lhs, rhs.date(), std::strong_ordering::less));
|
||||
|
||||
AssertOrderReturn<std::strong_ordering, std::chrono::sys_seconds, std::chrono::leap_second>();
|
||||
assert(testOrder(lhs.date(), rhs, std::strong_ordering::less));
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
test_comparison(test_leap_second_create(std::chrono::sys_seconds{std::chrono::seconds{0}}, std::chrono::seconds{1}),
|
||||
test_leap_second_create(std::chrono::sys_seconds{std::chrono::seconds{1}}, std::chrono::seconds{2}));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, const char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
// test with the real tzdb
|
||||
const std::chrono::tzdb& tzdb = std::chrono::get_tzdb();
|
||||
assert(tzdb.leap_seconds.size() > 2);
|
||||
test_comparison(tzdb.leap_seconds[0], tzdb.leap_seconds[1]);
|
||||
|
||||
return 0;
|
||||
}
|
52
libcxx/test/support/test_chrono_leap_second.h
Normal file
52
libcxx/test/support/test_chrono_leap_second.h
Normal file
@ -0,0 +1,52 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SUPPORT_TEST_CHRONO_LEAP_SECOND_HPP
|
||||
#define SUPPORT_TEST_CHRONO_LEAP_SECOND_HPP
|
||||
|
||||
// Contains helper functions to create a std::chrono::leap_second.
|
||||
//
|
||||
// Since the standard doesn't specify how a @ref std::chrono::leap_second is
|
||||
// constructed this is implementation defined. To make the public API tests of
|
||||
// the class generic this header defines helper functions to create the
|
||||
// required object.
|
||||
//
|
||||
// Note This requires every standard library implementation to write their own
|
||||
// helper function. Vendors are encouraged to create a pull request at
|
||||
// https://github.com/llvm/llvm-project so their specific implementation can be
|
||||
// part of this file.
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#if TEST_STD_VER < 20
|
||||
# error "The format header requires at least C++20"
|
||||
#endif
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#ifdef _LIBCPP_VERSION
|
||||
|
||||
// In order to find this include the calling test needs to provide this path in
|
||||
// the search path. Typically this looks like:
|
||||
// ADDITIONAL_COMPILE_FLAGS(stdlib=libc++): -I %{libcxx-dir}/src/include
|
||||
// where the number of `../` sequences depends on the subdirectory level of the
|
||||
// test.
|
||||
# include "tzdb/leap_second_private.h" // Header in the dylib
|
||||
|
||||
inline constexpr std::chrono::leap_second
|
||||
test_leap_second_create(const std::chrono::sys_seconds& date, const std::chrono::seconds& value) {
|
||||
return std::chrono::leap_second{std::chrono::leap_second::__constructor_tag{}, date, value};
|
||||
}
|
||||
|
||||
#else // _LIBCPP_VERSION
|
||||
# error \
|
||||
"Please create a vendor specific version of the test typedef and file a PR at https://github.com/llvm/llvm-project"
|
||||
#endif // _LIBCPP_VERSION
|
||||
|
||||
#endif // SUPPORT_TEST_CHRONO_LEAP_SECOND_HPP
|
Loading…
x
Reference in New Issue
Block a user