[libc++][chrono] implements GPS clock. (#125921)
Completes: - LWG3359 <chrono> leap second support should allow for negative leap seconds - P1361R2 Integration of chrono with text formatting Implements parts of: - P0355 Extending <chrono> to Calendars and Time Zones Fixes: #100432 Fixes: #100014
This commit is contained in:
parent
5a7ee431fd
commit
cf50936b23
@ -39,6 +39,7 @@ Implemented Papers
|
|||||||
------------------
|
------------------
|
||||||
|
|
||||||
- N4258: Cleaning-up noexcept in the Library (`Github <https://github.com/llvm/llvm-project/issues/99937>`__)
|
- N4258: Cleaning-up noexcept in the Library (`Github <https://github.com/llvm/llvm-project/issues/99937>`__)
|
||||||
|
- P1361R2: Integration of chrono with text formatting (`Github <https://github.com/llvm/llvm-project/issues/100014>`__)
|
||||||
|
|
||||||
Improvements and New Features
|
Improvements and New Features
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
@ -269,7 +269,7 @@
|
|||||||
"`LWG3355 <https://wg21.link/LWG3355>`__","The memory algorithms should support move-only input iterators introduced by P1207","2020-02 (Prague)","|Complete|","15",""
|
"`LWG3355 <https://wg21.link/LWG3355>`__","The memory algorithms should support move-only input iterators introduced by P1207","2020-02 (Prague)","|Complete|","15",""
|
||||||
"`LWG3356 <https://wg21.link/LWG3356>`__","``__cpp_lib_nothrow_convertible``\ should be ``__cpp_lib_is_nothrow_convertible``\ ","2020-02 (Prague)","|Complete|","12",""
|
"`LWG3356 <https://wg21.link/LWG3356>`__","``__cpp_lib_nothrow_convertible``\ should be ``__cpp_lib_is_nothrow_convertible``\ ","2020-02 (Prague)","|Complete|","12",""
|
||||||
"`LWG3358 <https://wg21.link/LWG3358>`__","|sect|\ [span.cons] is mistaken that ``to_address``\ can throw","2020-02 (Prague)","|Complete|","17",""
|
"`LWG3358 <https://wg21.link/LWG3358>`__","|sect|\ [span.cons] is mistaken that ``to_address``\ can throw","2020-02 (Prague)","|Complete|","17",""
|
||||||
"`LWG3359 <https://wg21.link/LWG3359>`__","``<chrono>``\ leap second support should allow for negative leap seconds","2020-02 (Prague)","|In Progress|","",""
|
"`LWG3359 <https://wg21.link/LWG3359>`__","``<chrono>``\ leap second support should allow for negative leap seconds","2020-02 (Prague)","|Complete|","21",""
|
||||||
"`LWG3360 <https://wg21.link/LWG3360>`__","``three_way_comparable_with``\ is inconsistent with similar concepts","2020-02 (Prague)","|Nothing To Do|","",""
|
"`LWG3360 <https://wg21.link/LWG3360>`__","``three_way_comparable_with``\ is inconsistent with similar concepts","2020-02 (Prague)","|Nothing To Do|","",""
|
||||||
"`LWG3362 <https://wg21.link/LWG3362>`__","Strike ``stop_source``\ 's ``operator!=``\ ","2020-02 (Prague)","|Complete|","17",""
|
"`LWG3362 <https://wg21.link/LWG3362>`__","Strike ``stop_source``\ 's ``operator!=``\ ","2020-02 (Prague)","|Complete|","17",""
|
||||||
"`LWG3363 <https://wg21.link/LWG3363>`__","``drop_while_view``\ should opt-out of ``sized_range``\ ","2020-02 (Prague)","|Nothing To Do|","",""
|
"`LWG3363 <https://wg21.link/LWG3363>`__","``drop_while_view``\ should opt-out of ``sized_range``\ ","2020-02 (Prague)","|Nothing To Do|","",""
|
||||||
|
|
@ -115,7 +115,7 @@
|
|||||||
"`P1207R4 <https://wg21.link/P1207R4>`__","Movability of Single-pass Iterators","2019-07 (Cologne)","|Complete|","15",""
|
"`P1207R4 <https://wg21.link/P1207R4>`__","Movability of Single-pass Iterators","2019-07 (Cologne)","|Complete|","15",""
|
||||||
"`P1208R6 <https://wg21.link/P1208R6>`__","Adopt source_location for C++20","2019-07 (Cologne)","|Complete|","16",""
|
"`P1208R6 <https://wg21.link/P1208R6>`__","Adopt source_location for C++20","2019-07 (Cologne)","|Complete|","16",""
|
||||||
"`P1355R2 <https://wg21.link/P1355R2>`__","Exposing a narrow contract for ceil2","2019-07 (Cologne)","|Complete|","9",""
|
"`P1355R2 <https://wg21.link/P1355R2>`__","Exposing a narrow contract for ceil2","2019-07 (Cologne)","|Complete|","9",""
|
||||||
"`P1361R2 <https://wg21.link/P1361R2>`__","Integration of chrono with text formatting","2019-07 (Cologne)","|Partial|","",""
|
"`P1361R2 <https://wg21.link/P1361R2>`__","Integration of chrono with text formatting","2019-07 (Cologne)","|Complete|","21",""
|
||||||
"`P1423R3 <https://wg21.link/P1423R3>`__","char8_t backward compatibility remediation","2019-07 (Cologne)","|Complete|","15",""
|
"`P1423R3 <https://wg21.link/P1423R3>`__","char8_t backward compatibility remediation","2019-07 (Cologne)","|Complete|","15",""
|
||||||
"`P1424R1 <https://wg21.link/P1424R1>`__","'constexpr' feature macro concerns","2019-07 (Cologne)","|Nothing To Do|","","Superseded by `P1902 <https://wg21.link/P1902>`__"
|
"`P1424R1 <https://wg21.link/P1424R1>`__","'constexpr' feature macro concerns","2019-07 (Cologne)","|Nothing To Do|","","Superseded by `P1902 <https://wg21.link/P1902>`__"
|
||||||
"`P1466R3 <https://wg21.link/P1466R3>`__","Miscellaneous minor fixes for chrono","2019-07 (Cologne)","|Partial|","",""
|
"`P1466R3 <https://wg21.link/P1466R3>`__","Miscellaneous minor fixes for chrono","2019-07 (Cologne)","|Partial|","",""
|
||||||
|
|
@ -4,7 +4,7 @@ Section,Description,Dependencies,Assignee,Status,First released version
|
|||||||
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::sys_time<Duration>``",,Mark de Wever,|Complete|,17
|
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::sys_time<Duration>``",,Mark de Wever,|Complete|,17
|
||||||
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::utc_time<Duration>``",,Mark de Wever,|Complete|,20
|
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::utc_time<Duration>``",,Mark de Wever,|Complete|,20
|
||||||
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::tai_time<Duration>``",,Mark de Wever,|Complete|,21
|
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::tai_time<Duration>``",,Mark de Wever,|Complete|,21
|
||||||
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::gps_time<Duration>``",A ``<chrono>`` implementation,Mark de Wever,,,
|
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::gps_time<Duration>``",,Mark de Wever,|Complete|,21
|
||||||
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::file_time<Duration>``",,Mark de Wever,|Complete|,17
|
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::file_time<Duration>``",,Mark de Wever,|Complete|,17
|
||||||
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::local_time<Duration>``",,Mark de Wever,|Complete|,17
|
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::local_time<Duration>``",,Mark de Wever,|Complete|,17
|
||||||
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::local-time-format-t<Duration>``",,,|Nothing To Do|,
|
`[time.syn] <https://wg21.link/time.syn>`_,"Formatter ``chrono::local-time-format-t<Duration>``",,,|Nothing To Do|,
|
||||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -256,6 +256,7 @@ set(files
|
|||||||
__chrono/exception.h
|
__chrono/exception.h
|
||||||
__chrono/file_clock.h
|
__chrono/file_clock.h
|
||||||
__chrono/formatter.h
|
__chrono/formatter.h
|
||||||
|
__chrono/gps_clock.h
|
||||||
__chrono/hh_mm_ss.h
|
__chrono/hh_mm_ss.h
|
||||||
__chrono/high_resolution_clock.h
|
__chrono/high_resolution_clock.h
|
||||||
__chrono/leap_second.h
|
__chrono/leap_second.h
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <__chrono/day.h>
|
#include <__chrono/day.h>
|
||||||
#include <__chrono/duration.h>
|
#include <__chrono/duration.h>
|
||||||
#include <__chrono/file_clock.h>
|
#include <__chrono/file_clock.h>
|
||||||
|
#include <__chrono/gps_clock.h>
|
||||||
#include <__chrono/hh_mm_ss.h>
|
#include <__chrono/hh_mm_ss.h>
|
||||||
#include <__chrono/local_info.h>
|
#include <__chrono/local_info.h>
|
||||||
#include <__chrono/month.h>
|
#include <__chrono/month.h>
|
||||||
@ -124,6 +125,11 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(chrono::tai_time<_Duration> __tp) {
|
|||||||
return std::__convert_to_tm<_Tm>(chrono::sys_time<_Rp>{__tp.time_since_epoch() - __offset});
|
return std::__convert_to_tm<_Tm>(chrono::sys_time<_Rp>{__tp.time_since_epoch() - __offset});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class _Tm, class _Duration>
|
||||||
|
_LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(chrono::gps_time<_Duration> __tp) {
|
||||||
|
return std::__convert_to_tm<_Tm>(chrono::utc_clock::to_sys(chrono::gps_clock::to_utc(__tp)));
|
||||||
|
}
|
||||||
|
|
||||||
# endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
# endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
||||||
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
|
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
# include <__chrono/day.h>
|
# include <__chrono/day.h>
|
||||||
# include <__chrono/duration.h>
|
# include <__chrono/duration.h>
|
||||||
# include <__chrono/file_clock.h>
|
# include <__chrono/file_clock.h>
|
||||||
|
# include <__chrono/gps_clock.h>
|
||||||
# include <__chrono/hh_mm_ss.h>
|
# include <__chrono/hh_mm_ss.h>
|
||||||
# include <__chrono/local_info.h>
|
# include <__chrono/local_info.h>
|
||||||
# include <__chrono/month.h>
|
# include <__chrono/month.h>
|
||||||
@ -235,6 +236,8 @@ _LIBCPP_HIDE_FROM_ABI __time_zone __convert_to_time_zone([[maybe_unused]] const
|
|||||||
# if _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
|
# if _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
|
||||||
else if constexpr (__is_time_point<_Tp> && requires { requires same_as<typename _Tp::clock, chrono::tai_clock>; })
|
else if constexpr (__is_time_point<_Tp> && requires { requires same_as<typename _Tp::clock, chrono::tai_clock>; })
|
||||||
return {"TAI", chrono::seconds{0}};
|
return {"TAI", chrono::seconds{0}};
|
||||||
|
else if constexpr (__is_time_point<_Tp> && requires { requires same_as<typename _Tp::clock, chrono::gps_clock>; })
|
||||||
|
return {"GPS", chrono::seconds{0}};
|
||||||
else if constexpr (__is_specialization_v<_Tp, chrono::zoned_time>)
|
else if constexpr (__is_specialization_v<_Tp, chrono::zoned_time>)
|
||||||
return __formatter::__convert_to_time_zone(__value.get_info());
|
return __formatter::__convert_to_time_zone(__value.get_info());
|
||||||
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
|
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
|
||||||
@ -748,6 +751,17 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class _Duration, __fmt_char_type _CharT>
|
||||||
|
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::gps_time<_Duration>, _CharT> : public __formatter_chrono<_CharT> {
|
||||||
|
public:
|
||||||
|
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||||
|
|
||||||
|
template <class _ParseContext>
|
||||||
|
_LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) {
|
||||||
|
return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__clock);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
# endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
# endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
||||||
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
|
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
|
||||||
|
|
||||||
|
90
libcxx/include/__chrono/gps_clock.h
Normal file
90
libcxx/include/__chrono/gps_clock.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// -*- 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 _LIBCPP___CHRONO_GPS_CLOCK_H
|
||||||
|
#define _LIBCPP___CHRONO_GPS_CLOCK_H
|
||||||
|
|
||||||
|
#include <version>
|
||||||
|
// Enable the contents of the header only when libc++ was built with experimental features enabled.
|
||||||
|
#if _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
||||||
|
|
||||||
|
# include <__assert>
|
||||||
|
# include <__chrono/duration.h>
|
||||||
|
# include <__chrono/time_point.h>
|
||||||
|
# include <__chrono/utc_clock.h>
|
||||||
|
# include <__config>
|
||||||
|
# include <__type_traits/common_type.h>
|
||||||
|
|
||||||
|
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||||
|
# pragma GCC system_header
|
||||||
|
# endif
|
||||||
|
|
||||||
|
_LIBCPP_PUSH_MACROS
|
||||||
|
# include <__undef_macros>
|
||||||
|
|
||||||
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||||
|
|
||||||
|
# if _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
|
||||||
|
|
||||||
|
namespace chrono {
|
||||||
|
|
||||||
|
class gps_clock;
|
||||||
|
|
||||||
|
template <class _Duration>
|
||||||
|
using gps_time = time_point<gps_clock, _Duration>;
|
||||||
|
using gps_seconds = gps_time<seconds>;
|
||||||
|
|
||||||
|
class gps_clock {
|
||||||
|
public:
|
||||||
|
using rep = utc_clock::rep;
|
||||||
|
using period = utc_clock::period;
|
||||||
|
using duration = chrono::duration<rep, period>;
|
||||||
|
using time_point = chrono::time_point<gps_clock>;
|
||||||
|
static constexpr bool is_steady = false; // The utc_clock is not steady.
|
||||||
|
|
||||||
|
// The static difference between UTC and GPS time as specified in the Standard.
|
||||||
|
static constexpr chrono::seconds __offset{315964809};
|
||||||
|
|
||||||
|
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static time_point now() { return from_utc(utc_clock::now()); }
|
||||||
|
|
||||||
|
template <class _Duration>
|
||||||
|
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static utc_time<common_type_t<_Duration, seconds>>
|
||||||
|
to_utc(const gps_time<_Duration>& __time) noexcept {
|
||||||
|
using _Rp = common_type_t<_Duration, seconds>;
|
||||||
|
_Duration __time_since_epoch = __time.time_since_epoch();
|
||||||
|
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__time_since_epoch >= utc_time<_Rp>::min().time_since_epoch() + __offset,
|
||||||
|
"the GPS to UTC conversion would underflow");
|
||||||
|
|
||||||
|
return utc_time<_Rp>{__time_since_epoch + __offset};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class _Duration>
|
||||||
|
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static gps_time<common_type_t<_Duration, seconds>>
|
||||||
|
from_utc(const utc_time<_Duration>& __time) noexcept {
|
||||||
|
using _Rp = common_type_t<_Duration, seconds>;
|
||||||
|
_Duration __time_since_epoch = __time.time_since_epoch();
|
||||||
|
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__time_since_epoch <= utc_time<_Rp>::max().time_since_epoch() - __offset,
|
||||||
|
"the UTC to GPS conversion would overflow");
|
||||||
|
|
||||||
|
return gps_time<_Rp>{__time_since_epoch - __offset};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chrono
|
||||||
|
|
||||||
|
# endif // _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM &&
|
||||||
|
// _LIBCPP_HAS_LOCALIZATION
|
||||||
|
|
||||||
|
_LIBCPP_END_NAMESPACE_STD
|
||||||
|
|
||||||
|
_LIBCPP_POP_MACROS
|
||||||
|
|
||||||
|
#endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
||||||
|
|
||||||
|
#endif // _LIBCPP___CHRONO_GPS_CLOCK_H
|
@ -18,6 +18,7 @@
|
|||||||
# include <__chrono/day.h>
|
# include <__chrono/day.h>
|
||||||
# include <__chrono/duration.h>
|
# include <__chrono/duration.h>
|
||||||
# include <__chrono/file_clock.h>
|
# include <__chrono/file_clock.h>
|
||||||
|
# include <__chrono/gps_clock.h>
|
||||||
# include <__chrono/hh_mm_ss.h>
|
# include <__chrono/hh_mm_ss.h>
|
||||||
# include <__chrono/local_info.h>
|
# include <__chrono/local_info.h>
|
||||||
# include <__chrono/month.h>
|
# include <__chrono/month.h>
|
||||||
@ -78,6 +79,12 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const tai_time<_Duration>& __tp
|
|||||||
return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp);
|
return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class _CharT, class _Traits, class _Duration>
|
||||||
|
_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
|
||||||
|
operator<<(basic_ostream<_CharT, _Traits>& __os, const gps_time<_Duration>& __tp) {
|
||||||
|
return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp);
|
||||||
|
}
|
||||||
|
|
||||||
# endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
# endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
||||||
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
|
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
|
||||||
|
|
||||||
|
@ -363,6 +363,33 @@ template<class charT, class traits, class Duration> // C++20
|
|||||||
basic_ostream<charT, traits>&
|
basic_ostream<charT, traits>&
|
||||||
operator<<(basic_ostream<charT, traits>& os, const tai_time<Duration>& t);
|
operator<<(basic_ostream<charT, traits>& os, const tai_time<Duration>& t);
|
||||||
|
|
||||||
|
// [time.clock.gps], class gps_clock
|
||||||
|
class gps_clock { // C++20
|
||||||
|
public:
|
||||||
|
using rep = a signed arithmetic type;
|
||||||
|
using period = ratio<unspecified, unspecified>;
|
||||||
|
using duration = chrono::duration<rep, period>;
|
||||||
|
using time_point = chrono::time_point<gps_clock>;
|
||||||
|
static constexpr bool is_steady = unspecified;
|
||||||
|
|
||||||
|
static time_point now();
|
||||||
|
|
||||||
|
template<class Duration>
|
||||||
|
static utc_time<common_type_t<Duration, seconds>>
|
||||||
|
to_utc(const gps_time<Duration>& t);
|
||||||
|
template<class Duration>
|
||||||
|
static gps_time<common_type_t<Duration, seconds>>
|
||||||
|
from_utc(const utc_time<Duration>& t);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Duration>
|
||||||
|
using gps_time = time_point<gps_clock, Duration>; // C++20
|
||||||
|
using gps_seconds = gps_time<seconds>; // C++20
|
||||||
|
|
||||||
|
template<class charT, class traits, class Duration> // C++20
|
||||||
|
basic_ostream<charT, traits>&
|
||||||
|
operator<<(basic_ostream<charT, traits>& os, const gps_time<Duration>& t);
|
||||||
|
|
||||||
class file_clock // C++20
|
class file_clock // C++20
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -930,6 +957,8 @@ namespace std {
|
|||||||
struct formatter<chrono::utc_time<Duration>, charT>; // C++20
|
struct formatter<chrono::utc_time<Duration>, charT>; // C++20
|
||||||
template<class Duration, class charT>
|
template<class Duration, class charT>
|
||||||
struct formatter<chrono::tai_time<Duration>, charT>; // C++20
|
struct formatter<chrono::tai_time<Duration>, charT>; // C++20
|
||||||
|
template<class Duration, class charT>
|
||||||
|
struct formatter<chrono::gps_time<Duration>, charT>; // C++20
|
||||||
template<class Duration, class charT>
|
template<class Duration, class charT>
|
||||||
struct formatter<chrono::file_time<Duration>, charT>; // C++20
|
struct formatter<chrono::file_time<Duration>, charT>; // C++20
|
||||||
template<class Duration, class charT>
|
template<class Duration, class charT>
|
||||||
|
@ -935,6 +935,10 @@ module std [system] {
|
|||||||
module exception { header "__chrono/exception.h" }
|
module exception { header "__chrono/exception.h" }
|
||||||
module file_clock { header "__chrono/file_clock.h" }
|
module file_clock { header "__chrono/file_clock.h" }
|
||||||
module formatter { header "__chrono/formatter.h" }
|
module formatter { header "__chrono/formatter.h" }
|
||||||
|
module gps_clock {
|
||||||
|
header "__chrono/gps_clock.h"
|
||||||
|
export std.chrono.time_point
|
||||||
|
}
|
||||||
module hh_mm_ss { header "__chrono/hh_mm_ss.h" }
|
module hh_mm_ss { header "__chrono/hh_mm_ss.h" }
|
||||||
module high_resolution_clock {
|
module high_resolution_clock {
|
||||||
header "__chrono/high_resolution_clock.h"
|
header "__chrono/high_resolution_clock.h"
|
||||||
|
@ -103,13 +103,11 @@ export namespace std {
|
|||||||
using std::chrono::tai_seconds;
|
using std::chrono::tai_seconds;
|
||||||
using std::chrono::tai_time;
|
using std::chrono::tai_time;
|
||||||
|
|
||||||
# if 0
|
|
||||||
// [time.clock.gps], class gps_clock
|
// [time.clock.gps], class gps_clock
|
||||||
using std::chrono::gps_clock;
|
using std::chrono::gps_clock;
|
||||||
|
|
||||||
using std::chrono::gps_seconds;
|
using std::chrono::gps_seconds;
|
||||||
using std::chrono::gps_time;
|
using std::chrono::gps_time;
|
||||||
# endif
|
|
||||||
# endif // _LIBCPP_ENABLE_EXPERIMENTAL
|
# endif // _LIBCPP_ENABLE_EXPERIMENTAL
|
||||||
#endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
|
#endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
|
||||||
|
|
||||||
|
@ -113,4 +113,15 @@ void test(std::chrono::time_zone tz, std::chrono::time_zone_link link, std::chro
|
|||||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||||
std::chrono::tai_clock::from_utc(std::chrono::utc_seconds{});
|
std::chrono::tai_clock::from_utc(std::chrono::utc_seconds{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ // [time.clock.gps]
|
||||||
|
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||||
|
std::chrono::gps_clock::now();
|
||||||
|
|
||||||
|
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||||
|
std::chrono::gps_clock::to_utc(std::chrono::gps_seconds{});
|
||||||
|
|
||||||
|
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||||
|
std::chrono::gps_clock::from_utc(std::chrono::utc_seconds{});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// REQUIRES: std-at-least-c++20
|
||||||
|
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||||
|
|
||||||
|
// XFAIL: libcpp-has-no-experimental-tzdb
|
||||||
|
// XFAIL: availability-tzdb-missing
|
||||||
|
|
||||||
|
// REQUIRES: libcpp-hardening-mode={{extensive|debug}}
|
||||||
|
// REQUIRES: has-unix-headers
|
||||||
|
// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
|
||||||
|
|
||||||
|
// <chrono>
|
||||||
|
//
|
||||||
|
// class gps_clock;
|
||||||
|
|
||||||
|
// static gps_time<common_type_t<_Duration, seconds>>
|
||||||
|
// from_utc(const utc_time<_Duration>& t) noexcept;
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#include "check_assertion.h"
|
||||||
|
|
||||||
|
// The function is specified as
|
||||||
|
// gps_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} + 378691210s
|
||||||
|
// When t == t.max() there will be a signed integral overflow (other values too).
|
||||||
|
int main(int, char**) {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
constexpr std::chrono::seconds offset{315964809};
|
||||||
|
|
||||||
|
(void)std::chrono::gps_clock::from_utc(std::chrono::utc_time<std::chrono::nanoseconds>::max() - offset);
|
||||||
|
TEST_LIBCPP_ASSERT_FAILURE(
|
||||||
|
std::chrono::gps_clock::from_utc(std::chrono::utc_time<std::chrono::nanoseconds>::max() - offset + 1ns),
|
||||||
|
"the UTC to GPS conversion would overflow");
|
||||||
|
|
||||||
|
(void)std::chrono::gps_clock::from_utc(std::chrono::utc_time<std::chrono::microseconds>::max() - offset);
|
||||||
|
TEST_LIBCPP_ASSERT_FAILURE(
|
||||||
|
std::chrono::gps_clock::from_utc(std::chrono::utc_time<std::chrono::microseconds>::max() - offset + 1us),
|
||||||
|
"the UTC to GPS conversion would overflow");
|
||||||
|
|
||||||
|
(void)std::chrono::gps_clock::from_utc(std::chrono::utc_time<std::chrono::milliseconds>::max() - offset);
|
||||||
|
TEST_LIBCPP_ASSERT_FAILURE(
|
||||||
|
std::chrono::gps_clock::from_utc(std::chrono::utc_time<std::chrono::milliseconds>::max() - offset + 1ms),
|
||||||
|
"the UTC to GPS conversion would overflow");
|
||||||
|
|
||||||
|
(void)std::chrono::gps_clock::from_utc(std::chrono::utc_seconds::max() - offset);
|
||||||
|
TEST_LIBCPP_ASSERT_FAILURE(std::chrono::gps_clock::from_utc(std::chrono::utc_seconds::max() - offset + 1s),
|
||||||
|
"the UTC to GPS conversion would overflow");
|
||||||
|
|
||||||
|
// The conversion uses `common_type_t<Duration, seconds>` so types "larger"
|
||||||
|
// than seconds are converted to seconds. Types "larger" than seconds are
|
||||||
|
// stored in "smaller" intergral and the overflow can never occur.
|
||||||
|
|
||||||
|
// Validate the types can never overflow on all current (and future) supported platforms.
|
||||||
|
static_assert(std::chrono::utc_time<std::chrono::days>::max() <= std::chrono::utc_seconds::max() - offset);
|
||||||
|
static_assert(std::chrono::utc_time<std::chrono::weeks>::max() <= std::chrono::utc_seconds::max() - offset);
|
||||||
|
static_assert(std::chrono::utc_time<std::chrono::months>::max() <= std::chrono::utc_seconds::max() - offset);
|
||||||
|
static_assert(std::chrono::utc_time<std::chrono::years>::max() <= std::chrono::utc_seconds::max() - offset);
|
||||||
|
|
||||||
|
// Validate the run-time conversion works.
|
||||||
|
(void)std::chrono::gps_clock::from_utc(std::chrono::utc_time<std::chrono::days>::max());
|
||||||
|
(void)std::chrono::gps_clock::from_utc(std::chrono::utc_time<std::chrono::weeks>::max());
|
||||||
|
(void)std::chrono::gps_clock::from_utc(std::chrono::utc_time<std::chrono::months>::max());
|
||||||
|
(void)std::chrono::gps_clock::from_utc(std::chrono::utc_time<std::chrono::years>::max());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// REQUIRES: std-at-least-c++20
|
||||||
|
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||||
|
|
||||||
|
// XFAIL: libcpp-has-no-experimental-tzdb
|
||||||
|
// XFAIL: availability-tzdb-missing
|
||||||
|
|
||||||
|
// REQUIRES: libcpp-hardening-mode={{extensive|debug}}
|
||||||
|
// REQUIRES: has-unix-headers
|
||||||
|
// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
|
||||||
|
|
||||||
|
// <chrono>
|
||||||
|
//
|
||||||
|
// class gps_clock;
|
||||||
|
|
||||||
|
// static utc_time<common_type_t<_Duration, seconds>>
|
||||||
|
// to_utc(const gps_time<_Duration>& t) noexcept;
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#include "check_assertion.h"
|
||||||
|
|
||||||
|
// The function is specified as
|
||||||
|
// utc_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} - 378691210s
|
||||||
|
// When t == t.min() there will be a signed integral underlow (other values too).
|
||||||
|
int main(int, char**) {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
constexpr std::chrono::seconds offset{315964809};
|
||||||
|
|
||||||
|
(void)std::chrono::gps_clock::to_utc(std::chrono::gps_time<std::chrono::nanoseconds>::min() + offset);
|
||||||
|
TEST_LIBCPP_ASSERT_FAILURE(
|
||||||
|
std::chrono::gps_clock::to_utc(std::chrono::gps_time<std::chrono::nanoseconds>::min() + offset - 1ns),
|
||||||
|
"the GPS to UTC conversion would underflow");
|
||||||
|
|
||||||
|
(void)std::chrono::gps_clock::to_utc(std::chrono::gps_time<std::chrono::microseconds>::min() + offset);
|
||||||
|
TEST_LIBCPP_ASSERT_FAILURE(
|
||||||
|
std::chrono::gps_clock::to_utc(std::chrono::gps_time<std::chrono::microseconds>::min() + offset - 1us),
|
||||||
|
"the GPS to UTC conversion would underflow");
|
||||||
|
|
||||||
|
(void)std::chrono::gps_clock::to_utc(std::chrono::gps_time<std::chrono::milliseconds>::min() + offset);
|
||||||
|
TEST_LIBCPP_ASSERT_FAILURE(
|
||||||
|
std::chrono::gps_clock::to_utc(std::chrono::gps_time<std::chrono::milliseconds>::min() + offset - 1ms),
|
||||||
|
"the GPS to UTC conversion would underflow");
|
||||||
|
|
||||||
|
(void)std::chrono::gps_clock::to_utc(std::chrono::gps_seconds::min() + offset);
|
||||||
|
TEST_LIBCPP_ASSERT_FAILURE(std::chrono::gps_clock::to_utc(std::chrono::gps_seconds::min() + offset - 1s),
|
||||||
|
"the GPS to UTC conversion would underflow");
|
||||||
|
|
||||||
|
// The conversion uses `common_type_t<Duration, seconds>` so types "larger"
|
||||||
|
// than seconds are converted to seconds. Types "larger" than seconds are
|
||||||
|
// stored in "smaller" intergral and the underflow can never occur.
|
||||||
|
|
||||||
|
// Validate the types can never underflow on all current (and future) supported platforms.
|
||||||
|
static_assert(std::chrono::gps_time<std::chrono::days>::min() >= std::chrono::gps_seconds::min() + offset);
|
||||||
|
static_assert(std::chrono::gps_time<std::chrono::weeks>::min() >= std::chrono::gps_seconds::min() + offset);
|
||||||
|
static_assert(std::chrono::gps_time<std::chrono::months>::min() >= std::chrono::gps_seconds::min() + offset);
|
||||||
|
static_assert(std::chrono::gps_time<std::chrono::years>::min() >= std::chrono::gps_seconds::min() + offset);
|
||||||
|
|
||||||
|
// Validate the run-time conversion works.
|
||||||
|
(void)std::chrono::gps_clock::to_utc(std::chrono::gps_time<std::chrono::days>::min());
|
||||||
|
(void)std::chrono::gps_clock::to_utc(std::chrono::gps_time<std::chrono::weeks>::min());
|
||||||
|
(void)std::chrono::gps_clock::to_utc(std::chrono::gps_time<std::chrono::months>::min());
|
||||||
|
(void)std::chrono::gps_clock::to_utc(std::chrono::gps_time<std::chrono::years>::min());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,164 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// REQUIRES: std-at-least-c++20
|
||||||
|
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||||
|
// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
|
||||||
|
|
||||||
|
// TODO FMT This test should not require std::to_chars(floating-point)
|
||||||
|
// XFAIL: availability-fp_to_chars-missing
|
||||||
|
|
||||||
|
// XFAIL: libcpp-has-no-experimental-tzdb
|
||||||
|
// XFAIL: availability-tzdb-missing
|
||||||
|
|
||||||
|
// REQUIRES: locale.fr_FR.UTF-8
|
||||||
|
// REQUIRES: locale.ja_JP.UTF-8
|
||||||
|
|
||||||
|
// <chrono>
|
||||||
|
|
||||||
|
// class gps_clock;
|
||||||
|
|
||||||
|
// template<class charT, class traits, class Duration>
|
||||||
|
// basic_ostream<charT, traits>&
|
||||||
|
// operator<<(basic_ostream<charT, traits>& os, const gps_time<Duration>& tp);
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <cassert>
|
||||||
|
#include <ratio>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "make_string.h"
|
||||||
|
#include "platform_support.h" // locale name macros
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
#define SV(S) MAKE_STRING_VIEW(CharT, S)
|
||||||
|
|
||||||
|
template <class CharT, class Duration>
|
||||||
|
static std::basic_string<CharT> stream_c_locale(std::chrono::gps_time<Duration> time_point) {
|
||||||
|
std::basic_stringstream<CharT> sstr;
|
||||||
|
sstr << std::fixed << time_point;
|
||||||
|
return sstr.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT, class Duration>
|
||||||
|
static std::basic_string<CharT> stream_fr_FR_locale(std::chrono::gps_time<Duration> time_point) {
|
||||||
|
std::basic_stringstream<CharT> sstr;
|
||||||
|
const std::locale locale(LOCALE_fr_FR_UTF_8);
|
||||||
|
sstr.imbue(locale);
|
||||||
|
sstr << std::fixed << time_point;
|
||||||
|
return sstr.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT, class Duration>
|
||||||
|
static std::basic_string<CharT> stream_ja_JP_locale(std::chrono::gps_time<Duration> time_point) {
|
||||||
|
std::basic_stringstream<CharT> sstr;
|
||||||
|
const std::locale locale(LOCALE_ja_JP_UTF_8);
|
||||||
|
sstr.imbue(locale);
|
||||||
|
sstr << std::fixed << time_point;
|
||||||
|
return sstr.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_c() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
assert(stream_c_locale<CharT>(cr::gps_time<cr::nanoseconds>{946'688'523'123'456'789ns}) ==
|
||||||
|
SV("2010-01-05 01:01:48.123456789"));
|
||||||
|
assert(stream_c_locale<CharT>(cr::gps_time<cr::microseconds>{946'688'523'123'456us}) ==
|
||||||
|
SV("2010-01-05 01:01:48.123456"));
|
||||||
|
|
||||||
|
assert(stream_c_locale<CharT>(cr::gps_time<cr::milliseconds>{946'684'822'123ms}) == SV("2010-01-05 00:00:07.123"));
|
||||||
|
assert(stream_c_locale<CharT>(cr::gps_seconds{1'234'567'890s}) == SV("2019-02-18 23:31:12"));
|
||||||
|
assert(stream_c_locale<CharT>(cr::gps_time<cr::minutes>{20'576'131min}) == SV("2019-02-18 23:30:42"));
|
||||||
|
assert(stream_c_locale<CharT>(cr::gps_time<cr::hours>{342'935h}) == SV("2019-02-18 22:59:42"));
|
||||||
|
|
||||||
|
assert(stream_c_locale<CharT>(cr::gps_time<cr::duration<signed char, std::ratio<2, 1>>>{
|
||||||
|
cr::duration<signed char, std::ratio<2, 1>>{60}}) == SV("1980-01-06 00:02:00"));
|
||||||
|
assert(stream_c_locale<CharT>(cr::gps_time<cr::duration<short, std::ratio<1, 2>>>{
|
||||||
|
cr::duration<short, std::ratio<1, 2>>{3600}}) == SV("1980-01-06 00:30:00.0"));
|
||||||
|
assert(stream_c_locale<CharT>(cr::gps_time<cr::duration<int, std::ratio<1, 4>>>{
|
||||||
|
cr::duration<int, std::ratio<1, 4>>{3600}}) == SV("1980-01-06 00:15:00.00"));
|
||||||
|
assert(stream_c_locale<CharT>(cr::gps_time<cr::duration<long, std::ratio<1, 10>>>{
|
||||||
|
cr::duration<long, std::ratio<1, 10>>{36611}}) == SV("1980-01-06 01:01:01.1"));
|
||||||
|
assert(stream_c_locale<CharT>(cr::gps_time<cr::duration<long long, std::ratio<1, 100>>>{
|
||||||
|
cr::duration<long long, std::ratio<1, 100>>{123'456'789'010}}) == SV("2019-02-18 23:31:12.10"));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_fr_FR() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
assert(stream_fr_FR_locale<CharT>(cr::gps_time<cr::nanoseconds>{946'688'523'123'456'789ns}) ==
|
||||||
|
SV("2010-01-05 01:01:48,123456789"));
|
||||||
|
assert(stream_fr_FR_locale<CharT>(cr::gps_time<cr::microseconds>{946'688'523'123'456us}) ==
|
||||||
|
SV("2010-01-05 01:01:48,123456"));
|
||||||
|
|
||||||
|
assert(stream_fr_FR_locale<CharT>(cr::gps_time<cr::milliseconds>{946'684'822'123ms}) ==
|
||||||
|
SV("2010-01-05 00:00:07,123"));
|
||||||
|
assert(stream_fr_FR_locale<CharT>(cr::gps_seconds{1'234'567'890s}) == SV("2019-02-18 23:31:12"));
|
||||||
|
assert(stream_fr_FR_locale<CharT>(cr::gps_time<cr::minutes>{20'576'131min}) == SV("2019-02-18 23:30:42"));
|
||||||
|
assert(stream_fr_FR_locale<CharT>(cr::gps_time<cr::hours>{342'935h}) == SV("2019-02-18 22:59:42"));
|
||||||
|
|
||||||
|
assert(stream_fr_FR_locale<CharT>(cr::gps_time<cr::duration<signed char, std::ratio<2, 1>>>{
|
||||||
|
cr::duration<signed char, std::ratio<2, 1>>{60}}) == SV("1980-01-06 00:02:00"));
|
||||||
|
assert(stream_fr_FR_locale<CharT>(cr::gps_time<cr::duration<short, std::ratio<1, 2>>>{
|
||||||
|
cr::duration<short, std::ratio<1, 2>>{3600}}) == SV("1980-01-06 00:30:00,0"));
|
||||||
|
assert(stream_fr_FR_locale<CharT>(cr::gps_time<cr::duration<int, std::ratio<1, 4>>>{
|
||||||
|
cr::duration<int, std::ratio<1, 4>>{3600}}) == SV("1980-01-06 00:15:00,00"));
|
||||||
|
assert(stream_fr_FR_locale<CharT>(cr::gps_time<cr::duration<long, std::ratio<1, 10>>>{
|
||||||
|
cr::duration<long, std::ratio<1, 10>>{36611}}) == SV("1980-01-06 01:01:01,1"));
|
||||||
|
assert(stream_fr_FR_locale<CharT>(cr::gps_time<cr::duration<long long, std::ratio<1, 100>>>{
|
||||||
|
cr::duration<long long, std::ratio<1, 100>>{123'456'789'010}}) == SV("2019-02-18 23:31:12,10"));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_ja_JP() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
assert(stream_ja_JP_locale<CharT>(cr::gps_time<cr::nanoseconds>{946'688'523'123'456'789ns}) ==
|
||||||
|
SV("2010-01-05 01:01:48.123456789"));
|
||||||
|
assert(stream_ja_JP_locale<CharT>(cr::gps_time<cr::microseconds>{946'688'523'123'456us}) ==
|
||||||
|
SV("2010-01-05 01:01:48.123456"));
|
||||||
|
|
||||||
|
assert(stream_ja_JP_locale<CharT>(cr::gps_time<cr::milliseconds>{946'684'822'123ms}) ==
|
||||||
|
SV("2010-01-05 00:00:07.123"));
|
||||||
|
assert(stream_ja_JP_locale<CharT>(cr::gps_seconds{1'234'567'890s}) == SV("2019-02-18 23:31:12"));
|
||||||
|
assert(stream_ja_JP_locale<CharT>(cr::gps_time<cr::minutes>{20'576'131min}) == SV("2019-02-18 23:30:42"));
|
||||||
|
assert(stream_ja_JP_locale<CharT>(cr::gps_time<cr::hours>{342'935h}) == SV("2019-02-18 22:59:42"));
|
||||||
|
|
||||||
|
assert(stream_ja_JP_locale<CharT>(cr::gps_time<cr::duration<signed char, std::ratio<2, 1>>>{
|
||||||
|
cr::duration<signed char, std::ratio<2, 1>>{60}}) == SV("1980-01-06 00:02:00"));
|
||||||
|
assert(stream_ja_JP_locale<CharT>(cr::gps_time<cr::duration<short, std::ratio<1, 2>>>{
|
||||||
|
cr::duration<short, std::ratio<1, 2>>{3600}}) == SV("1980-01-06 00:30:00.0"));
|
||||||
|
assert(stream_ja_JP_locale<CharT>(cr::gps_time<cr::duration<int, std::ratio<1, 4>>>{
|
||||||
|
cr::duration<int, std::ratio<1, 4>>{3600}}) == SV("1980-01-06 00:15:00.00"));
|
||||||
|
assert(stream_ja_JP_locale<CharT>(cr::gps_time<cr::duration<long, std::ratio<1, 10>>>{
|
||||||
|
cr::duration<long, std::ratio<1, 10>>{36611}}) == SV("1980-01-06 01:01:01.1"));
|
||||||
|
assert(stream_ja_JP_locale<CharT>(cr::gps_time<cr::duration<long long, std::ratio<1, 100>>>{
|
||||||
|
cr::duration<long long, std::ratio<1, 100>>{123'456'789'010}}) == SV("2019-02-18 23:31:12.10"));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test() {
|
||||||
|
test_c<CharT>();
|
||||||
|
test_fr_FR<CharT>();
|
||||||
|
test_ja_JP<CharT>();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,158 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// REQUIRES: std-at-least-c++20
|
||||||
|
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||||
|
|
||||||
|
// XFAIL: libcpp-has-no-experimental-tzdb
|
||||||
|
// XFAIL: availability-tzdb-missing
|
||||||
|
|
||||||
|
// <chrono>
|
||||||
|
//
|
||||||
|
// class gps_clock;
|
||||||
|
|
||||||
|
// static gps_time<common_type_t<_Duration, seconds>>
|
||||||
|
// from_utc(const utc<_Duration>& __time) noexcept;
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <cassert>
|
||||||
|
#include <source_location>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "assert_macros.h"
|
||||||
|
#include "concat_macros.h"
|
||||||
|
|
||||||
|
static void test_known_values() {
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
|
||||||
|
// [time.clock.gps.overview]/1
|
||||||
|
// The clock gps_clock measures seconds since the first Sunday of January,
|
||||||
|
// 1980 00:00:00 UTC.
|
||||||
|
// The first Sunday is 1980-1-6 (so January sixth)
|
||||||
|
// ... 1980-01-06 00:00:00 GPS is equivalent to 1980-01-06 00:00:00 UTC
|
||||||
|
|
||||||
|
assert(cr::gps_clock::from_utc(cr::utc_clock::from_sys(cr::sys_days{cr::January / 6 / 1980})) == cr::gps_seconds{0s});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Duration>
|
||||||
|
static void test_leap_seconds(std::chrono::utc_time<Duration> utc,
|
||||||
|
std::chrono::gps_time<Duration> expected,
|
||||||
|
std::source_location loc = std::source_location::current()) {
|
||||||
|
auto gps = std::chrono::gps_clock::from_utc(utc);
|
||||||
|
TEST_REQUIRE(gps == expected,
|
||||||
|
TEST_WRITE_CONCATENATED(loc, "\nExpected output ", expected, "\nActual output ", gps, '\n'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests set if existing database entries at the time of writing.
|
||||||
|
static void test_transitions() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
// "sys" is the time of the transition to the next leap second.
|
||||||
|
// "elapsed" is the number of leap seconds before the transition.
|
||||||
|
auto test_transition = [](cr::sys_days sys, cr::seconds elapsed) {
|
||||||
|
constexpr auto unix_to_gps_epoch_offset =
|
||||||
|
cr::sys_days{cr::January / 1 / 1970} - cr::sys_days{cr::January / 6 / 1980};
|
||||||
|
cr::gps_seconds gps{sys.time_since_epoch() + unix_to_gps_epoch_offset + elapsed};
|
||||||
|
|
||||||
|
test_leap_seconds(cr::utc_clock::from_sys(sys - 1ns), gps - 1ns);
|
||||||
|
test_leap_seconds(cr::utc_clock::from_sys(sys), gps + 1s);
|
||||||
|
test_leap_seconds(cr::utc_clock::from_sys(sys) + 1ns, gps + 1s + 1ns);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Transitions from the start of UTC.
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1972}, -9s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1973}, -8s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1974}, -7s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1975}, -6s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1976}, -5s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1977}, -4s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1978}, -3s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1979}, -2s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1980}, -1s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1981}, 0s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1982}, 1s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1983}, 2s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1985}, 3s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1988}, 4s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1990}, 5s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1991}, 6s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1992}, 7s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1993}, 8s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1994}, 9s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1996}, 10s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1997}, 11s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1999}, 12s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 2006}, 13s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 2009}, 14s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 2012}, 15s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 2015}, 16s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 2017}, 17s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests whether the return type is the expected type.
|
||||||
|
static void test_return_type() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::gps_time<cr::nanoseconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::from_utc(cr::utc_time<cr::nanoseconds>{0ns});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::gps_time<cr::microseconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::from_utc(cr::utc_time<cr::microseconds>{0us});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::gps_time<cr::milliseconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::from_utc(cr::utc_time<cr::milliseconds>{0ms});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::gps_time<cr::seconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::from_utc(cr::utc_time<cr::seconds>{cr::seconds{0}});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::gps_time<cr::seconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::from_utc(cr::utc_time<cr::minutes>{cr::minutes{0}});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::gps_time<cr::seconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::from_utc(cr::utc_time<cr::hours>{cr::hours{0}});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::gps_time<cr::seconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::from_utc(cr::utc_time<cr::days>{cr::days{0}});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::gps_time<cr::seconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::from_utc(cr::utc_time<cr::weeks>{cr::weeks{0}});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::gps_time<cr::seconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::from_utc(cr::utc_time<cr::months>{cr::months{0}});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::gps_time<cr::seconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::from_utc(cr::utc_time<cr::years>{cr::years{0}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, const char**) {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
std::chrono::utc_seconds time = std::chrono::utc_seconds{0s};
|
||||||
|
static_assert(noexcept(std::chrono::gps_clock::from_utc(time)));
|
||||||
|
|
||||||
|
test_known_values();
|
||||||
|
test_transitions();
|
||||||
|
test_return_type();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// REQUIRES: std-at-least-c++20
|
||||||
|
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||||
|
|
||||||
|
// XFAIL: libcpp-has-no-experimental-tzdb
|
||||||
|
// XFAIL: availability-tzdb-missing
|
||||||
|
|
||||||
|
// <chrono>
|
||||||
|
//
|
||||||
|
// class gps_clock;
|
||||||
|
|
||||||
|
// static time_point now();
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <concepts>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int main(int, const char**) {
|
||||||
|
using clock = std::chrono::gps_clock;
|
||||||
|
std::same_as<clock::time_point> decltype(auto) t = clock::now();
|
||||||
|
|
||||||
|
assert(t >= clock::time_point::min());
|
||||||
|
assert(t <= clock::time_point::max());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,153 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// REQUIRES: std-at-least-c++20
|
||||||
|
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||||
|
|
||||||
|
// XFAIL: libcpp-has-no-experimental-tzdb
|
||||||
|
// XFAIL: availability-tzdb-missing
|
||||||
|
|
||||||
|
// <chrono>
|
||||||
|
//
|
||||||
|
// class gps_clock;
|
||||||
|
|
||||||
|
// static utc_time<common_type_t<_Duration, seconds>>
|
||||||
|
// to_utc(const gps_time<_Duration>& __time) noexcept;
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <cassert>
|
||||||
|
#include <source_location>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "assert_macros.h"
|
||||||
|
#include "concat_macros.h"
|
||||||
|
|
||||||
|
static void test_known_values() {
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
|
||||||
|
assert(cr::gps_clock::to_utc(cr::gps_seconds{0s}) == cr::utc_clock::from_sys(cr::sys_days{cr::January / 6 / 1980}));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Duration>
|
||||||
|
static void test_leap_seconds(std::chrono::gps_time<Duration> gps,
|
||||||
|
std::chrono::utc_time<Duration> expected,
|
||||||
|
std::source_location loc = std::source_location::current()) {
|
||||||
|
auto utc = std::chrono::gps_clock::to_utc(gps);
|
||||||
|
TEST_REQUIRE(utc == expected,
|
||||||
|
TEST_WRITE_CONCATENATED(loc, "\nExpected output ", expected, "\nActual output ", utc, '\n'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests set if existing database entries at the time of writing.
|
||||||
|
static void test_transitions() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
// "sys" is the time of the transition to the next leap second.
|
||||||
|
// "elapsed" is the number of leap seconds before the transition.
|
||||||
|
auto test_transition = [](cr::sys_days sys, cr::seconds elapsed) {
|
||||||
|
constexpr auto unix_to_gps_epoch_offset =
|
||||||
|
cr::sys_days{cr::January / 1 / 1970} - cr::sys_days{cr::January / 6 / 1980};
|
||||||
|
cr::gps_seconds gps{sys.time_since_epoch() + unix_to_gps_epoch_offset + elapsed};
|
||||||
|
|
||||||
|
test_leap_seconds(gps - 1ns, cr::utc_clock::from_sys(sys - 1ns));
|
||||||
|
test_leap_seconds(gps + 1s, cr::utc_clock::from_sys(sys));
|
||||||
|
test_leap_seconds(gps + 1s + 1ns, cr::utc_clock::from_sys(sys + 1ns));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Transitions from the start of UTC.
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1972}, -9s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1973}, -8s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1974}, -7s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1975}, -6s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1976}, -5s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1977}, -4s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1978}, -3s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1979}, -2s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1980}, -1s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1981}, 0s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1982}, 1s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1983}, 2s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1985}, 3s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1988}, 4s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1990}, 5s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1991}, 6s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1992}, 7s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1993}, 8s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1994}, 9s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1996}, 10s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 1997}, 11s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 1999}, 12s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 2006}, 13s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 2009}, 14s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 2012}, 15s);
|
||||||
|
test_transition(cr::sys_days{cr::July / 1 / 2015}, 16s);
|
||||||
|
test_transition(cr::sys_days{cr::January / 1 / 2017}, 17s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests whether the return type is the expected type.
|
||||||
|
static void test_return_type() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::utc_time<cr::nanoseconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::to_utc(cr::gps_time<cr::nanoseconds>{0ns});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::utc_time<cr::microseconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::to_utc(cr::gps_time<cr::microseconds>{0us});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::utc_time<cr::milliseconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::to_utc(cr::gps_time<cr::milliseconds>{0ms});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::utc_time<cr::seconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::to_utc(cr::gps_time<cr::seconds>{cr::seconds{0}});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::utc_time<cr::seconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::to_utc(cr::gps_time<cr::minutes>{cr::minutes{0}});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::utc_time<cr::seconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::to_utc(cr::gps_time<cr::hours>{cr::hours{0}});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::utc_time<cr::seconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::to_utc(cr::gps_time<cr::days>{cr::days{0}});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::utc_time<cr::seconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::to_utc(cr::gps_time<cr::weeks>{cr::weeks{0}});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::utc_time<cr::seconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::to_utc(cr::gps_time<cr::months>{cr::months{0}});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[[maybe_unused]] std::same_as<cr::utc_time<cr::seconds>> decltype(auto) _ =
|
||||||
|
cr::gps_clock::to_utc(cr::gps_time<cr::years>{cr::years{0}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, const char**) {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
|
||||||
|
std::chrono::gps_seconds time = std::chrono::gps_seconds{0s};
|
||||||
|
static_assert(noexcept(std::chrono::gps_clock::to_utc(time)));
|
||||||
|
|
||||||
|
test_known_values();
|
||||||
|
test_transitions();
|
||||||
|
test_return_type();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// REQUIRES: std-at-least-c++20
|
||||||
|
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||||
|
|
||||||
|
// XFAIL: libcpp-has-no-experimental-tzdb
|
||||||
|
// XFAIL: availability-tzdb-missing
|
||||||
|
|
||||||
|
// <chrono>
|
||||||
|
|
||||||
|
// class gps_clock {
|
||||||
|
// public:
|
||||||
|
// using rep = a signed arithmetic type;
|
||||||
|
// using period = ratio<unspecified, unspecified>;
|
||||||
|
// using duration = chrono::duration<rep, period>;
|
||||||
|
// using time_point = chrono::time_point<gps_clock>;
|
||||||
|
// static constexpr bool is_steady = unspecified;
|
||||||
|
//
|
||||||
|
// ...
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template<class Duration>
|
||||||
|
// using gps_time = time_point<gps_clock, Duration>;
|
||||||
|
// using gps_seconds = gps_time<seconds>;
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <concepts>
|
||||||
|
#include <ratio>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
// class gps_clock
|
||||||
|
using rep = std::chrono::gps_clock::rep;
|
||||||
|
using period = std::chrono::gps_clock::period;
|
||||||
|
using duration = std::chrono::gps_clock::duration;
|
||||||
|
using time_point = std::chrono::gps_clock::time_point;
|
||||||
|
constexpr bool is_steady = std::chrono::gps_clock::is_steady;
|
||||||
|
|
||||||
|
// Tests the values. part of them are implementation defined.
|
||||||
|
LIBCPP_STATIC_ASSERT(std::same_as<rep, std::chrono::utc_clock::rep>);
|
||||||
|
static_assert(std::is_arithmetic_v<rep>);
|
||||||
|
static_assert(std::is_signed_v<rep>);
|
||||||
|
|
||||||
|
LIBCPP_STATIC_ASSERT(std::same_as<period, std::chrono::utc_clock::period>);
|
||||||
|
static_assert(std::same_as<period, std::ratio<period::num, period::den>>);
|
||||||
|
|
||||||
|
static_assert(std::same_as<duration, std::chrono::duration<rep, period>>);
|
||||||
|
static_assert(std::same_as<time_point, std::chrono::time_point<std::chrono::gps_clock>>);
|
||||||
|
LIBCPP_STATIC_ASSERT(is_steady == false);
|
||||||
|
|
||||||
|
// typedefs
|
||||||
|
static_assert(std::same_as<std::chrono::gps_time<int>, std::chrono::time_point<std::chrono::gps_clock, int>>);
|
||||||
|
static_assert(std::same_as<std::chrono::gps_time<long>, std::chrono::time_point<std::chrono::gps_clock, long>>);
|
||||||
|
static_assert(std::same_as<std::chrono::gps_seconds, std::chrono::gps_time<std::chrono::seconds>>);
|
990
libcxx/test/std/time/time.syn/formatter.gps_time.pass.cpp
Normal file
990
libcxx/test/std/time/time.syn/formatter.gps_time.pass.cpp
Normal file
@ -0,0 +1,990 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// REQUIRES: std-at-least-c++20
|
||||||
|
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
|
||||||
|
// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
|
||||||
|
|
||||||
|
// TODO FMT This test should not require std::to_chars(floating-point)
|
||||||
|
// XFAIL: availability-fp_to_chars-missing
|
||||||
|
|
||||||
|
// XFAIL: libcpp-has-no-experimental-tzdb
|
||||||
|
// XFAIL: availability-tzdb-missing
|
||||||
|
|
||||||
|
// REQUIRES: locale.fr_FR.UTF-8
|
||||||
|
// REQUIRES: locale.ja_JP.UTF-8
|
||||||
|
|
||||||
|
// <chrono>
|
||||||
|
|
||||||
|
// template<class Duration, class charT>
|
||||||
|
// struct formatter<chrono::gps_time<Duration>, charT>;
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <format>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <concepts>
|
||||||
|
#include <locale>
|
||||||
|
#include <iostream>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "formatter_tests.h"
|
||||||
|
#include "make_string.h"
|
||||||
|
#include "platform_support.h" // locale name macros
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_no_chrono_specs() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||||
|
|
||||||
|
// Non localized output
|
||||||
|
|
||||||
|
// [time.syn]
|
||||||
|
// using nanoseconds = duration<signed integer type of at least 64 bits, nano>;
|
||||||
|
// using microseconds = duration<signed integer type of at least 55 bits, micro>;
|
||||||
|
// using milliseconds = duration<signed integer type of at least 45 bits, milli>;
|
||||||
|
// using seconds = duration<signed integer type of at least 35 bits>;
|
||||||
|
// using minutes = duration<signed integer type of at least 29 bits, ratio< 60>>;
|
||||||
|
// using hours = duration<signed integer type of at least 23 bits, ratio<3600>>;
|
||||||
|
check(SV("1435-08-09 22:07:05"), SV("{}"), cr::gps_seconds(-17'179'869'184s)); // Minimum value for 35 bits.
|
||||||
|
check(SV("1911-12-18 20:46:01"), SV("{}"), cr::gps_seconds(-2'147'483'648s));
|
||||||
|
|
||||||
|
check(SV("1980-01-05 00:00:00"), SV("{}"), cr::gps_seconds(-24h));
|
||||||
|
check(SV("1980-01-05 06:00:00"), SV("{}"), cr::gps_seconds(-18h));
|
||||||
|
check(SV("1980-01-05 12:00:00"), SV("{}"), cr::gps_seconds(-12h));
|
||||||
|
check(SV("1980-01-05 18:00:00"), SV("{}"), cr::gps_seconds(-6h));
|
||||||
|
check(SV("1980-01-05 23:59:59"), SV("{}"), cr::gps_seconds(-1s));
|
||||||
|
|
||||||
|
check(SV("1980-01-06 00:00:00"), SV("{}"), cr::gps_seconds(0s));
|
||||||
|
check(SV("2010-01-04 23:59:45"), SV("{}"), cr::gps_seconds(946'684'800s));
|
||||||
|
check(SV("2010-01-05 01:01:48"), SV("{}"), cr::gps_seconds(946'688'523s));
|
||||||
|
|
||||||
|
check(SV("2048-01-24 03:13:49"), SV("{}"), cr::gps_seconds(2'147'483'647s));
|
||||||
|
check(SV("2524-06-03 01:52:45"), SV("{}"), cr::gps_seconds(17'179'869'183s)); // Maximum value for 35 bits.
|
||||||
|
|
||||||
|
check(SV("2010-01-05 01:01:48.123"), SV("{}"), cr::gps_time<cr::milliseconds>(946'688'523'123ms));
|
||||||
|
|
||||||
|
std::locale::global(std::locale::classic());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_valid_values_year() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
constexpr std::basic_string_view<CharT> fmt =
|
||||||
|
SV("{:%%C='%C'%t%%EC='%EC'%t%%y='%y'%t%%Oy='%Oy'%t%%Ey='%Ey'%t%%Y='%Y'%t%%EY='%EY'%n}");
|
||||||
|
constexpr std::basic_string_view<CharT> lfmt =
|
||||||
|
SV("{:L%%C='%C'%t%%EC='%EC'%t%%y='%y'%t%%Oy='%Oy'%t%%Ey='%Ey'%t%%Y='%Y'%t%%EY='%EY'%n}");
|
||||||
|
|
||||||
|
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||||
|
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||||
|
|
||||||
|
// Non localized output using C-locale
|
||||||
|
check(SV("%C='19'\t%EC='19'\t%y='80'\t%Oy='80'\t%Ey='80'\t%Y='1980'\t%EY='1980'\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
|
||||||
|
// Use the global locale (fr_FR)
|
||||||
|
check(SV("%C='19'\t%EC='19'\t%y='80'\t%Oy='80'\t%Ey='80'\t%Y='1980'\t%EY='1980'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
|
||||||
|
// Use supplied locale (ja_JP). This locale has a different alternate.
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%C='19'\t%EC='19'\t%y='80'\t%Oy='80'\t%Ey='80'\t%Y='1980'\t%EY='1980'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)||defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%C='19'\t%EC='昭和'\t%y='80'\t%Oy='八十'\t%Ey='55'\t%Y='1980'\t%EY='昭和55年'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%C='20'\t%EC='平成'\t%y='09'\t%Oy='九'\t%Ey='21'\t%Y='2009'\t%EY='平成21年'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)||defined(__FreeBSD__)
|
||||||
|
|
||||||
|
std::locale::global(std::locale::classic());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_valid_values_month() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
constexpr std::basic_string_view<CharT> fmt = SV("{:%%b='%b'%t%%h='%h'%t%%B='%B'%t%%m='%m'%t%%Om='%Om'%n}");
|
||||||
|
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%b='%b'%t%%h='%h'%t%%B='%B'%t%%m='%m'%t%%Om='%Om'%n}");
|
||||||
|
|
||||||
|
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||||
|
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||||
|
|
||||||
|
// Non localized output using C-locale
|
||||||
|
check(SV("%b='Jan'\t%h='Jan'\t%B='January'\t%m='01'\t%Om='01'\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%b='May'\t%h='May'\t%B='May'\t%m='05'\t%Om='05'\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS on Wednesday, 18 May 2033
|
||||||
|
|
||||||
|
// Use the global locale (fr_FR)
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
check(SV("%b='jan'\t%h='jan'\t%B='janvier'\t%m='01'\t%Om='01'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
#else
|
||||||
|
check(SV("%b='janv.'\t%h='janv.'\t%B='janvier'\t%m='01'\t%Om='01'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
#endif
|
||||||
|
|
||||||
|
check(SV("%b='mai'\t%h='mai'\t%B='mai'\t%m='05'\t%Om='05'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS on Wednesday, 18 May 2033
|
||||||
|
|
||||||
|
// Use supplied locale (ja_JP). This locale has a different alternate.
|
||||||
|
#ifdef _WIN32
|
||||||
|
check(loc,
|
||||||
|
SV("%b='1'\t%h='1'\t%B='1月'\t%m='01'\t%Om='01'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%b='5'\t%h='5'\t%B='5月'\t%m='05'\t%Om='05'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
|
||||||
|
#elif defined(_AIX) // _WIN32
|
||||||
|
check(loc,
|
||||||
|
SV("%b='1月'\t%h='1月'\t%B='1月'\t%m='01'\t%Om='01'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%b='5月'\t%h='5月'\t%B='5月'\t%m='05'\t%Om='05'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
|
||||||
|
#elif defined(__APPLE__) // _WIN32
|
||||||
|
check(loc,
|
||||||
|
SV("%b=' 1'\t%h=' 1'\t%B='1月'\t%m='01'\t%Om='01'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%b=' 5'\t%h=' 5'\t%B='5月'\t%m='05'\t%Om='05'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
|
||||||
|
#elif defined(__FreeBSD__) // _WIN32
|
||||||
|
check(loc,
|
||||||
|
SV("%b=' 1月'\t%h=' 1月'\t%B='1月'\t%m='01'\t%Om='01'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%b=' 5月'\t%h=' 5月'\t%B='5月'\t%m='05'\t%Om='05'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
|
||||||
|
#else // _WIN32
|
||||||
|
check(loc,
|
||||||
|
SV("%b=' 1月'\t%h=' 1月'\t%B='1月'\t%m='01'\t%Om='一'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%b=' 5月'\t%h=' 5月'\t%B='5月'\t%m='05'\t%Om='五'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
std::locale::global(std::locale::classic());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_valid_values_day() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
constexpr std::basic_string_view<CharT> fmt = SV("{:%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}");
|
||||||
|
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}");
|
||||||
|
|
||||||
|
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||||
|
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||||
|
|
||||||
|
// Non localized output using C-locale
|
||||||
|
check(SV("%d='06'\t%Od='06'\t%e=' 6'\t%Oe=' 6'\n"), fmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
|
||||||
|
// Use the global locale (fr_FR)
|
||||||
|
check(SV("%d='06'\t%Od='06'\t%e=' 6'\t%Oe=' 6'\n"), lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
|
||||||
|
// Use the global locale (fr_FR)
|
||||||
|
check(SV("%d='06'\t%Od='06'\t%e=' 6'\t%Oe=' 6'\n"), lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
// Use supplied locale (ja_JP). This locale has a different alternate.
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%d='06'\t%Od='06'\t%e=' 6'\t%Oe=' 6'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
|
||||||
|
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%d='06'\t%Od='六'\t%e=' 6'\t%Oe='六'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%d='13'\t%Od='十三'\t%e='13'\t%Oe='十三'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
|
||||||
|
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
|
||||||
|
std::locale::global(std::locale::classic());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_valid_values_weekday() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
constexpr std::basic_string_view<CharT> fmt =
|
||||||
|
SV("{:%%a='%a'%t%%A='%A'%t%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");
|
||||||
|
constexpr std::basic_string_view<CharT> lfmt =
|
||||||
|
SV("{:L%%a='%a'%t%%A='%A'%t%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");
|
||||||
|
|
||||||
|
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||||
|
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||||
|
|
||||||
|
// Non localized output using C-locale
|
||||||
|
check(SV("%a='Sun'\t%A='Sunday'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%a='Sun'\t%A='Sunday'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_seconds(3'979'002'513s)); // 06:28:15 GPS on Sunday, 7 February 2106
|
||||||
|
|
||||||
|
// Use the global locale (fr_FR)
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
check(SV("%a='Dim'\t%A='Dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%a='Dim'\t%A='Dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(3'979'002'513s)); // 06:28:15 GPS on Sunday, 7 February 2106
|
||||||
|
#else
|
||||||
|
check(SV("%a='dim.'\t%A='dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%a='dim.'\t%A='dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(3'979'002'513s)); // 06:28:15 GPS on Sunday, 7 February 2106
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Use supplied locale (ja_JP).
|
||||||
|
// This locale has a different alternate, but not on all platforms
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(3'979'002'513s)); // 06:28:15 GPS on Sunday, 7 February 2106
|
||||||
|
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='七'\t%w='0'\t%Ow='〇'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(3'979'002'513s)); // 06:28:15 GPS on Sunday, 7 February 2106
|
||||||
|
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
|
||||||
|
std::locale::global(std::locale::classic());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_valid_values_day_of_year() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
constexpr std::basic_string_view<CharT> fmt = SV("{:%%j='%j'%n}");
|
||||||
|
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%j='%j'%n}");
|
||||||
|
|
||||||
|
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||||
|
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||||
|
|
||||||
|
// Non localized output using C-locale
|
||||||
|
check(SV("%j='006'\n"), fmt, cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
check(SV("%j='138'\n"), fmt, cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
|
||||||
|
|
||||||
|
// Use the global locale (fr_FR)
|
||||||
|
check(SV("%j='006'\n"), lfmt, cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
check(SV("%j='138'\n"), lfmt, cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
|
||||||
|
|
||||||
|
// Use supplied locale (ja_JP). This locale has a different alternate.
|
||||||
|
check(loc, SV("%j='006'\n"), lfmt, cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
check(loc, SV("%j='138'\n"), lfmt, cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
|
||||||
|
|
||||||
|
std::locale::global(std::locale::classic());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_valid_values_week() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
constexpr std::basic_string_view<CharT> fmt = SV("{:%%U='%U'%t%%OU='%OU'%t%%W='%W'%t%%OW='%OW'%n}");
|
||||||
|
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%U='%U'%t%%OU='%OU'%t%%W='%W'%t%%OW='%OW'%n}");
|
||||||
|
|
||||||
|
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||||
|
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||||
|
|
||||||
|
// Non localized output using C-locale
|
||||||
|
check(SV("%U='01'\t%OU='01'\t%W='00'\t%OW='00'\n"), fmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
|
||||||
|
|
||||||
|
// Use the global locale (fr_FR)
|
||||||
|
check(SV("%U='01'\t%OU='01'\t%W='00'\t%OW='00'\n"), lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
|
||||||
|
|
||||||
|
// Use supplied locale (ja_JP). This locale has a different alternate.
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%U='01'\t%OU='001\t%W='00'\t%OW='00'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
|
||||||
|
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%U='01'\t%OU='一'\t%W='00'\t%OW='〇'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%U='20'\t%OU='二十'\t%W='20'\t%OW='二十'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
|
||||||
|
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
std::locale::global(std::locale::classic());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_valid_values_iso_8601_week() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
constexpr std::basic_string_view<CharT> fmt = SV("{:%%g='%g'%t%%G='%G'%t%%V='%V'%t%%OV='%OV'%n}");
|
||||||
|
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%g='%g'%t%%G='%G'%t%%V='%V'%t%%OV='%OV'%n}");
|
||||||
|
|
||||||
|
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||||
|
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||||
|
|
||||||
|
// Non localized output using C-locale
|
||||||
|
check(SV("%g='80'\t%G='1980'\t%V='01'\t%OV='01'\n"), fmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
|
||||||
|
// Use the global locale (fr_FR)
|
||||||
|
check(SV("%g='80'\t%G='1980'\t%V='01'\t%OV='01'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
|
||||||
|
// Use supplied locale (ja_JP). This locale has a different alternate.
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%g='80'\t%G='1980'\t%V='01'\t%OV='01'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%g='80'\t%G='1980'\t%V='01'\t%OV='一'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%g='09'\t%G='2009'\t%V='07'\t%OV='七'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
|
||||||
|
std::locale::global(std::locale::classic());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_valid_values_date() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
constexpr std::basic_string_view<CharT> fmt = SV("{:%%D='%D'%t%%F='%F'%t%%x='%x'%t%%Ex='%Ex'%n}");
|
||||||
|
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%D='%D'%t%%F='%F'%t%%x='%x'%t%%Ex='%Ex'%n}");
|
||||||
|
|
||||||
|
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||||
|
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||||
|
|
||||||
|
// Non localized output using C-locale
|
||||||
|
check(SV("%D='01/06/80'\t%F='1980-01-06'\t%x='01/06/80'\t%Ex='01/06/80'\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='02/13/09'\t%Ex='02/13/09'\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
|
||||||
|
// Use the global locale (fr_FR)
|
||||||
|
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||||
|
check(SV("%D='01/06/80'\t%F='1980-01-01'\t%x='06.01.1980'\t%Ex='06.01.1980'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='13.02.2009'\t%Ex='13.02.2009'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
#else
|
||||||
|
check(SV("%D='01/06/80'\t%F='1980-01-06'\t%x='06/01/1980'\t%Ex='06/01/1980'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='13/02/2009'\t%Ex='13/02/2009'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Use supplied locale (ja_JP). This locale has a different alternate.
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%D='01/06/80'\t%F='1980-01-06'\t%x='1980/01/06'\t%Ex='1980/01/06'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%D='02/13/09'\t%F='2009-02-13'\t%x='2009/02/13'\t%Ex='2009/02/13'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%D='01/06/80'\t%F='1980-01-06'\t%x='1980年01月06日'\t%Ex='昭和55年01月06日'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%D='02/13/09'\t%F='2009-02-13'\t%x='2009年02月13日'\t%Ex='平成21年02月13日'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
|
||||||
|
|
||||||
|
std::locale::global(std::locale::classic());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_valid_values_time() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
constexpr std::basic_string_view<CharT> fmt = SV(
|
||||||
|
"{:"
|
||||||
|
"%%H='%H'%t"
|
||||||
|
"%%OH='%OH'%t"
|
||||||
|
"%%I='%I'%t"
|
||||||
|
"%%OI='%OI'%t"
|
||||||
|
"%%M='%M'%t"
|
||||||
|
"%%OM='%OM'%t"
|
||||||
|
"%%S='%S'%t"
|
||||||
|
"%%OS='%OS'%t"
|
||||||
|
"%%p='%p'%t"
|
||||||
|
"%%R='%R'%t"
|
||||||
|
"%%T='%T'%t"
|
||||||
|
"%%r='%r'%t"
|
||||||
|
"%%X='%X'%t"
|
||||||
|
"%%EX='%EX'%t"
|
||||||
|
"%n}");
|
||||||
|
constexpr std::basic_string_view<CharT> lfmt = SV(
|
||||||
|
"{:L"
|
||||||
|
"%%H='%H'%t"
|
||||||
|
"%%OH='%OH'%t"
|
||||||
|
"%%I='%I'%t"
|
||||||
|
"%%OI='%OI'%t"
|
||||||
|
"%%M='%M'%t"
|
||||||
|
"%%OM='%OM'%t"
|
||||||
|
"%%S='%S'%t"
|
||||||
|
"%%OS='%OS'%t"
|
||||||
|
"%%p='%p'%t"
|
||||||
|
"%%R='%R'%t"
|
||||||
|
"%%T='%T'%t"
|
||||||
|
"%%r='%r'%t"
|
||||||
|
"%%X='%X'%t"
|
||||||
|
"%%EX='%EX'%t"
|
||||||
|
"%n}");
|
||||||
|
|
||||||
|
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||||
|
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||||
|
|
||||||
|
// Non localized output using C-locale
|
||||||
|
check(SV("%H='00'\t"
|
||||||
|
"%OH='00'\t"
|
||||||
|
"%I='12'\t"
|
||||||
|
"%OI='12'\t"
|
||||||
|
"%M='00'\t"
|
||||||
|
"%OM='00'\t"
|
||||||
|
"%S='00'\t"
|
||||||
|
"%OS='00'\t"
|
||||||
|
"%p='AM'\t"
|
||||||
|
"%R='00:00'\t"
|
||||||
|
"%T='00:00:00'\t"
|
||||||
|
"%r='12:00:00 AM'\t"
|
||||||
|
"%X='00:00:00'\t"
|
||||||
|
"%EX='00:00:00'\t"
|
||||||
|
"\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%H='23'\t"
|
||||||
|
"%OH='23'\t"
|
||||||
|
"%I='11'\t"
|
||||||
|
"%OI='11'\t"
|
||||||
|
"%M='31'\t"
|
||||||
|
"%OM='31'\t"
|
||||||
|
"%S='30.123'\t"
|
||||||
|
"%OS='30.123'\t"
|
||||||
|
"%p='PM'\t"
|
||||||
|
"%R='23:31'\t"
|
||||||
|
"%T='23:31:30.123'\t"
|
||||||
|
"%r='11:31:30 PM'\t"
|
||||||
|
"%X='23:31:30'\t"
|
||||||
|
"%EX='23:31:30'\t"
|
||||||
|
"\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_time<cr::milliseconds>(918'603'105'123ms)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
|
||||||
|
// Use the global locale (fr_FR)
|
||||||
|
check(SV("%H='00'\t"
|
||||||
|
"%OH='00'\t"
|
||||||
|
"%I='12'\t"
|
||||||
|
"%OI='12'\t"
|
||||||
|
"%M='00'\t"
|
||||||
|
"%OM='00'\t"
|
||||||
|
"%S='00'\t"
|
||||||
|
"%OS='00'\t"
|
||||||
|
#if defined(_AIX)
|
||||||
|
"%p='AM'\t"
|
||||||
|
#else
|
||||||
|
"%p=''\t"
|
||||||
|
#endif
|
||||||
|
"%R='00:00'\t"
|
||||||
|
"%T='00:00:00'\t"
|
||||||
|
#ifdef _WIN32
|
||||||
|
"%r='00:00:00'\t"
|
||||||
|
#elif defined(_AIX)
|
||||||
|
"%r='12:00:00 AM'\t"
|
||||||
|
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
||||||
|
"%r=''\t"
|
||||||
|
#else
|
||||||
|
"%r='12:00:00 '\t"
|
||||||
|
#endif
|
||||||
|
"%X='00:00:00'\t"
|
||||||
|
"%EX='00:00:00'\t"
|
||||||
|
"\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%H='23'\t"
|
||||||
|
"%OH='23'\t"
|
||||||
|
"%I='11'\t"
|
||||||
|
"%OI='11'\t"
|
||||||
|
"%M='31'\t"
|
||||||
|
"%OM='31'\t"
|
||||||
|
"%S='30,123'\t"
|
||||||
|
"%OS='30,123'\t"
|
||||||
|
#if defined(_AIX)
|
||||||
|
"%p='PM'\t"
|
||||||
|
#else
|
||||||
|
"%p=''\t"
|
||||||
|
#endif
|
||||||
|
"%R='23:31'\t"
|
||||||
|
"%T='23:31:30,123'\t"
|
||||||
|
#ifdef _WIN32
|
||||||
|
"%r='23:31:30'\t"
|
||||||
|
#elif defined(_AIX)
|
||||||
|
"%r='11:31:30 PM'\t"
|
||||||
|
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
||||||
|
"%r=''\t"
|
||||||
|
#else
|
||||||
|
"%r='11:31:30 '\t"
|
||||||
|
#endif
|
||||||
|
"%X='23:31:30'\t"
|
||||||
|
"%EX='23:31:30'\t"
|
||||||
|
"\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_time<cr::milliseconds>(918'603'105'123ms)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
|
||||||
|
// Use supplied locale (ja_JP). This locale has a different alternate.
|
||||||
|
#if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%H='00'\t"
|
||||||
|
"%OH='00'\t"
|
||||||
|
"%I='12'\t"
|
||||||
|
"%OI='12'\t"
|
||||||
|
"%M='00'\t"
|
||||||
|
"%OM='00'\t"
|
||||||
|
"%S='00'\t"
|
||||||
|
"%OS='00'\t"
|
||||||
|
# if defined(__APPLE__)
|
||||||
|
"%p='AM'\t"
|
||||||
|
# else
|
||||||
|
"%p='午前'\t"
|
||||||
|
# endif
|
||||||
|
"%R='00:00'\t"
|
||||||
|
"%T='00:00:00'\t"
|
||||||
|
# if defined(__APPLE__) || defined(__FreeBSD__)
|
||||||
|
# if defined(__APPLE__)
|
||||||
|
"%r='12:00:00 AM'\t"
|
||||||
|
# else
|
||||||
|
"%r='12:00:00 午前'\t"
|
||||||
|
# endif
|
||||||
|
"%X='00時00分00秒'\t"
|
||||||
|
"%EX='00時00分00秒'\t"
|
||||||
|
# elif defined(_WIN32)
|
||||||
|
"%r='0:00:00'\t"
|
||||||
|
"%X='0:00:00'\t"
|
||||||
|
"%EX='0:00:00'\t"
|
||||||
|
# else
|
||||||
|
"%r='午前12:00:00'\t"
|
||||||
|
"%X='00:00:00'\t"
|
||||||
|
"%EX='00:00:00'\t"
|
||||||
|
# endif
|
||||||
|
"\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::hh_mm_ss(0s));
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%H='23'\t"
|
||||||
|
"%OH='23'\t"
|
||||||
|
"%I='11'\t"
|
||||||
|
"%OI='11'\t"
|
||||||
|
"%M='31'\t"
|
||||||
|
"%OM='31'\t"
|
||||||
|
"%S='30.123'\t"
|
||||||
|
"%OS='30.123'\t"
|
||||||
|
# if defined(__APPLE__)
|
||||||
|
"%p='PM'\t"
|
||||||
|
# else
|
||||||
|
"%p='午後'\t"
|
||||||
|
# endif
|
||||||
|
"%R='23:31'\t"
|
||||||
|
"%T='23:31:30.123'\t"
|
||||||
|
# if defined(__APPLE__) || defined(__FreeBSD__)
|
||||||
|
# if defined(__APPLE__)
|
||||||
|
"%r='11:31:30 PM'\t"
|
||||||
|
# else
|
||||||
|
"%r='11:31:30 午後'\t"
|
||||||
|
# endif
|
||||||
|
"%X='23時31分30秒'\t"
|
||||||
|
"%EX='23時31分30秒'\t"
|
||||||
|
# elif defined(_WIN32)
|
||||||
|
"%r='23:31:30'\t"
|
||||||
|
"%X='23:31:30'\t"
|
||||||
|
"%EX='23:31:30'\t"
|
||||||
|
# else
|
||||||
|
"%r='午後11:31:30'\t"
|
||||||
|
"%X='23:31:30'\t"
|
||||||
|
"%EX='23:31:30'\t"
|
||||||
|
# endif
|
||||||
|
"\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::hh_mm_ss(23h + 31min + 30s + 123ms));
|
||||||
|
#else // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%H='00'\t"
|
||||||
|
"%OH='〇'\t"
|
||||||
|
"%I='12'\t"
|
||||||
|
"%OI='十二'\t"
|
||||||
|
"%M='00'\t"
|
||||||
|
"%OM='〇'\t"
|
||||||
|
"%S='00'\t"
|
||||||
|
"%OS='〇'\t"
|
||||||
|
"%p='午前'\t"
|
||||||
|
"%R='00:00'\t"
|
||||||
|
"%T='00:00:00'\t"
|
||||||
|
"%r='午前12時00分00秒'\t"
|
||||||
|
"%X='00時00分00秒'\t"
|
||||||
|
"%EX='00時00分00秒'\t"
|
||||||
|
"\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%H='23'\t"
|
||||||
|
"%OH='二十三'\t"
|
||||||
|
"%I='11'\t"
|
||||||
|
"%OI='十一'\t"
|
||||||
|
"%M='31'\t"
|
||||||
|
"%OM='三十一'\t"
|
||||||
|
"%S='30.123'\t"
|
||||||
|
"%OS='三十.123'\t"
|
||||||
|
"%p='午後'\t"
|
||||||
|
"%R='23:31'\t"
|
||||||
|
"%T='23:31:30.123'\t"
|
||||||
|
"%r='午後11時31分30秒'\t"
|
||||||
|
"%X='23時31分30秒'\t"
|
||||||
|
"%EX='23時31分30秒'\t"
|
||||||
|
"\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_time<cr::milliseconds>(918'603'105'123ms)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
#endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
|
||||||
|
|
||||||
|
std::locale::global(std::locale::classic());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_valid_values_date_time() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
constexpr std::basic_string_view<CharT> fmt = SV("{:%%c='%c'%t%%Ec='%Ec'%n}");
|
||||||
|
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%c='%c'%t%%Ec='%Ec'%n}");
|
||||||
|
|
||||||
|
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||||
|
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||||
|
|
||||||
|
// Non localized output using C-locale
|
||||||
|
check(SV("%c='Sun Jan 6 00:00:00 1980'\t%Ec='Sun Jan 6 00:00:00 1980'\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(SV("%c='Fri Feb 13 23:31:30 2009'\t%Ec='Fri Feb 13 23:31:30 2009'\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
|
||||||
|
// Use the global locale (fr_FR)
|
||||||
|
check(
|
||||||
|
// https://sourceware.org/bugzilla/show_bug.cgi?id=24054
|
||||||
|
#if defined(__powerpc__) && defined(__linux__)
|
||||||
|
SV("%c='dim. 06 janv. 1980 00:00:00 GPS'\t%Ec='dim. 06 janv. 1958 00:00:00 GPS'\n"),
|
||||||
|
#elif defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29
|
||||||
|
SV("%c='dim. 06 janv. 1980 00:00:00 GMT'\t%Ec='dim. 06 janv. 1980 00:00:00 GMT'\n"),
|
||||||
|
#elif defined(_AIX)
|
||||||
|
SV("%c=' 1 janvier 1980 à 00:00:00 GPS'\t%Ec=' 6 janvier 1980 à 00:00:00 GPS'\n"),
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
SV("%c='Dim 6 jan 00:00:00 1980'\t%Ec='Dim 6 jan 00:00:00 1980'\n"),
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
SV("%c='06/01/1980 00:00:00'\t%Ec='06/01/1980 00:00:00'\n"),
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
SV("%c='dim. 6 janv. 00:00:00 1980'\t%Ec='dim. 6 janv. 00:00:00 1980'\n"),
|
||||||
|
#else
|
||||||
|
SV("%c='dim. 06 janv. 1980 00:00:00'\t%Ec='dim. 06 janv. 1980 00:00:00'\n"),
|
||||||
|
#endif
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(
|
||||||
|
// https://sourceware.org/bugzilla/show_bug.cgi?id=24054
|
||||||
|
#if defined(__powerpc__) && defined(__linux__)
|
||||||
|
SV("%c='ven. 13 févr. 2009 23:31:30 GPS'\t%Ec='ven. 13 févr. 2009 23:31:30 GPS'\n"),
|
||||||
|
#elif defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29
|
||||||
|
SV("%c='ven. 13 févr. 2009 23:31:30 GMT'\t%Ec='ven. 13 févr. 2009 23:31:30 GMT'\n"),
|
||||||
|
#elif defined(_AIX)
|
||||||
|
SV("%c='13 février 2009 à 23:31:30 GPS'\t%Ec='13 février 2009 à 23:31:30 GPS'\n"),
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
SV("%c='Ven 13 fév 23:31:30 2009'\t%Ec='Ven 13 fév 23:31:30 2009'\n"),
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
SV("%c='13/02/2009 23:31:30'\t%Ec='13/02/2009 23:31:30'\n"),
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
SV("%c='ven. 13 févr. 23:31:30 2009'\t%Ec='ven. 13 févr. 23:31:30 2009'\n"),
|
||||||
|
#else
|
||||||
|
SV("%c='ven. 13 févr. 2009 23:31:30'\t%Ec='ven. 13 févr. 2009 23:31:30'\n"),
|
||||||
|
#endif
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
|
||||||
|
// Use supplied locale (ja_JP). This locale has a different alternate.a
|
||||||
|
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%c='水 1/ 6 00:00:00 1980'\t%Ec='水 1/ 6 00:00:00 1980'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
check(loc,
|
||||||
|
SV("%c='金 2/13 23:31:30 2009'\t%Ec='金 2/13 23:31:30 2009'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
#elif defined(_AIX) // defined(__APPLE__)|| defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%c='1980年01月 6日 00:00:00 GPS'\t%Ec='1980年01月 6日 00:00:00 GPS'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
check(loc,
|
||||||
|
SV("%c='2009年02月13日 23:31:30 GPS'\t%Ec='2009年02月13日 23:31:30 GPS'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
#elif defined(_WIN32) // defined(__APPLE__)|| defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%c='1980/01/06 0:00:00'\t%Ec='1980/01/06 0:00:00'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
check(loc,
|
||||||
|
SV("%c='2009/02/13 23:31:30'\t%Ec='2009/02/13 23:31:30'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
#else // defined(__APPLE__)|| defined(__FreeBSD__)
|
||||||
|
check(loc,
|
||||||
|
SV("%c='1980年01月06日 00時00分00秒'\t%Ec='昭和55年01月06日 00時00分00秒'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
check(loc,
|
||||||
|
SV("%c='2009年02月13日 23時31分30秒'\t%Ec='平成21年02月13日 23時31分30秒'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
|
||||||
|
#endif // defined(__APPLE__)|| defined(__FreeBSD__)
|
||||||
|
|
||||||
|
std::locale::global(std::locale::classic());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_valid_values_time_zone() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
constexpr std::basic_string_view<CharT> fmt = SV("{:%%z='%z'%t%%Ez='%Ez'%t%%Oz='%Oz'%t%%Z='%Z'%n}");
|
||||||
|
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%z='%z'%t%%Ez='%Ez'%t%%Oz='%Oz'%t%%Z='%Z'%n}");
|
||||||
|
|
||||||
|
const std::locale loc(LOCALE_ja_JP_UTF_8);
|
||||||
|
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
|
||||||
|
|
||||||
|
// Non localized output using C-locale
|
||||||
|
check(SV("%z='+0000'\t%Ez='+00:00'\t%Oz='+00:00'\t%Z='GPS'\n"),
|
||||||
|
fmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
// Use the global locale (fr_FR)
|
||||||
|
check(SV("%z='+0000'\t%Ez='+00:00'\t%Oz='+00:00'\t%Z='GPS'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
// Use supplied locale (ja_JP).
|
||||||
|
check(loc,
|
||||||
|
SV("%z='+0000'\t%Ez='+00:00'\t%Oz='+00:00'\t%Z='GPS'\n"),
|
||||||
|
lfmt,
|
||||||
|
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
|
||||||
|
|
||||||
|
std::locale::global(std::locale::classic());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test_valid_values() {
|
||||||
|
test_valid_values_year<CharT>();
|
||||||
|
test_valid_values_month<CharT>();
|
||||||
|
test_valid_values_day<CharT>();
|
||||||
|
test_valid_values_weekday<CharT>();
|
||||||
|
test_valid_values_day_of_year<CharT>();
|
||||||
|
test_valid_values_week<CharT>();
|
||||||
|
test_valid_values_iso_8601_week<CharT>();
|
||||||
|
test_valid_values_date<CharT>();
|
||||||
|
test_valid_values_time<CharT>();
|
||||||
|
test_valid_values_date_time<CharT>();
|
||||||
|
test_valid_values_time_zone<CharT>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CharT>
|
||||||
|
static void test() {
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
namespace cr = std::chrono;
|
||||||
|
|
||||||
|
test_no_chrono_specs<CharT>();
|
||||||
|
test_valid_values<CharT>();
|
||||||
|
check_invalid_types<CharT>(
|
||||||
|
{SV("a"), SV("A"), SV("b"), SV("B"), SV("c"), SV("C"), SV("d"), SV("D"), SV("e"), SV("F"), SV("g"),
|
||||||
|
SV("G"), SV("h"), SV("H"), SV("I"), SV("j"), SV("m"), SV("M"), SV("p"), SV("r"), SV("R"), SV("S"),
|
||||||
|
SV("T"), SV("u"), SV("U"), SV("V"), SV("w"), SV("W"), SV("x"), SV("X"), SV("y"), SV("Y"), SV("z"),
|
||||||
|
SV("Z"), SV("Ec"), SV("EC"), SV("Ex"), SV("EX"), SV("Ey"), SV("EY"), SV("Ez"), SV("Od"), SV("Oe"), SV("OH"),
|
||||||
|
SV("OI"), SV("Om"), SV("OM"), SV("OS"), SV("Ou"), SV("OU"), SV("OV"), SV("Ow"), SV("OW"), SV("Oy"), SV("Oz")},
|
||||||
|
cr::gps_seconds(0s));
|
||||||
|
|
||||||
|
check_exception("The format specifier expects a '%' or a '}'", SV("{:A"), cr::gps_seconds(0s));
|
||||||
|
check_exception("The chrono specifiers contain a '{'", SV("{:%%{"), cr::gps_seconds(0s));
|
||||||
|
check_exception("End of input while parsing a conversion specifier", SV("{:%"), cr::gps_seconds(0s));
|
||||||
|
check_exception("End of input while parsing the modifier E", SV("{:%E"), cr::gps_seconds(0s));
|
||||||
|
check_exception("End of input while parsing the modifier O", SV("{:%O"), cr::gps_seconds(0s));
|
||||||
|
|
||||||
|
// Precision not allowed
|
||||||
|
check_exception("The format specifier expects a '%' or a '}'", SV("{:.3}"), cr::gps_seconds(0s));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
test<char>();
|
||||||
|
|
||||||
|
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||||
|
test<wchar_t>();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user