1*700637cbSDimitry Andric // -*- C++ -*- 2*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 3*700637cbSDimitry Andric // 4*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*700637cbSDimitry Andric // 8*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 9*700637cbSDimitry Andric 10*700637cbSDimitry Andric #ifndef _LIBCPP___CHRONO_GPS_CLOCK_H 11*700637cbSDimitry Andric #define _LIBCPP___CHRONO_GPS_CLOCK_H 12*700637cbSDimitry Andric 13*700637cbSDimitry Andric #include <version> 14*700637cbSDimitry Andric // Enable the contents of the header only when libc++ was built with experimental features enabled. 15*700637cbSDimitry Andric #if _LIBCPP_HAS_EXPERIMENTAL_TZDB 16*700637cbSDimitry Andric 17*700637cbSDimitry Andric # include <__assert> 18*700637cbSDimitry Andric # include <__chrono/duration.h> 19*700637cbSDimitry Andric # include <__chrono/time_point.h> 20*700637cbSDimitry Andric # include <__chrono/utc_clock.h> 21*700637cbSDimitry Andric # include <__config> 22*700637cbSDimitry Andric # include <__type_traits/common_type.h> 23*700637cbSDimitry Andric 24*700637cbSDimitry Andric # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 25*700637cbSDimitry Andric # pragma GCC system_header 26*700637cbSDimitry Andric # endif 27*700637cbSDimitry Andric 28*700637cbSDimitry Andric _LIBCPP_PUSH_MACROS 29*700637cbSDimitry Andric # include <__undef_macros> 30*700637cbSDimitry Andric 31*700637cbSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 32*700637cbSDimitry Andric 33*700637cbSDimitry Andric # if _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION 34*700637cbSDimitry Andric 35*700637cbSDimitry Andric namespace chrono { 36*700637cbSDimitry Andric 37*700637cbSDimitry Andric class gps_clock; 38*700637cbSDimitry Andric 39*700637cbSDimitry Andric template <class _Duration> 40*700637cbSDimitry Andric using gps_time = time_point<gps_clock, _Duration>; 41*700637cbSDimitry Andric using gps_seconds = gps_time<seconds>; 42*700637cbSDimitry Andric 43*700637cbSDimitry Andric class gps_clock { 44*700637cbSDimitry Andric public: 45*700637cbSDimitry Andric using rep = utc_clock::rep; 46*700637cbSDimitry Andric using period = utc_clock::period; 47*700637cbSDimitry Andric using duration = chrono::duration<rep, period>; 48*700637cbSDimitry Andric using time_point = chrono::time_point<gps_clock>; 49*700637cbSDimitry Andric static constexpr bool is_steady = false; // The utc_clock is not steady. 50*700637cbSDimitry Andric 51*700637cbSDimitry Andric // The static difference between UTC and GPS time as specified in the Standard. 52*700637cbSDimitry Andric static constexpr chrono::seconds __offset{315964809}; 53*700637cbSDimitry Andric now()54*700637cbSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static time_point now() { return from_utc(utc_clock::now()); } 55*700637cbSDimitry Andric 56*700637cbSDimitry Andric template <class _Duration> 57*700637cbSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static utc_time<common_type_t<_Duration, seconds>> to_utc(const gps_time<_Duration> & __time)58*700637cbSDimitry Andric to_utc(const gps_time<_Duration>& __time) noexcept { 59*700637cbSDimitry Andric using _Rp = common_type_t<_Duration, seconds>; 60*700637cbSDimitry Andric _Duration __time_since_epoch = __time.time_since_epoch(); 61*700637cbSDimitry Andric _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__time_since_epoch >= utc_time<_Rp>::min().time_since_epoch() + __offset, 62*700637cbSDimitry Andric "the GPS to UTC conversion would underflow"); 63*700637cbSDimitry Andric 64*700637cbSDimitry Andric return utc_time<_Rp>{__time_since_epoch + __offset}; 65*700637cbSDimitry Andric } 66*700637cbSDimitry Andric 67*700637cbSDimitry Andric template <class _Duration> 68*700637cbSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static gps_time<common_type_t<_Duration, seconds>> from_utc(const utc_time<_Duration> & __time)69*700637cbSDimitry Andric from_utc(const utc_time<_Duration>& __time) noexcept { 70*700637cbSDimitry Andric using _Rp = common_type_t<_Duration, seconds>; 71*700637cbSDimitry Andric _Duration __time_since_epoch = __time.time_since_epoch(); 72*700637cbSDimitry Andric _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__time_since_epoch <= utc_time<_Rp>::max().time_since_epoch() - __offset, 73*700637cbSDimitry Andric "the UTC to GPS conversion would overflow"); 74*700637cbSDimitry Andric 75*700637cbSDimitry Andric return gps_time<_Rp>{__time_since_epoch - __offset}; 76*700637cbSDimitry Andric } 77*700637cbSDimitry Andric }; 78*700637cbSDimitry Andric 79*700637cbSDimitry Andric } // namespace chrono 80*700637cbSDimitry Andric 81*700637cbSDimitry Andric # endif // _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && 82*700637cbSDimitry Andric // _LIBCPP_HAS_LOCALIZATION 83*700637cbSDimitry Andric 84*700637cbSDimitry Andric _LIBCPP_END_NAMESPACE_STD 85*700637cbSDimitry Andric 86*700637cbSDimitry Andric _LIBCPP_POP_MACROS 87*700637cbSDimitry Andric 88*700637cbSDimitry Andric #endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB 89*700637cbSDimitry Andric 90*700637cbSDimitry Andric #endif // _LIBCPP___CHRONO_GPS_CLOCK_H 91