xref: /freebsd/contrib/llvm-project/libcxx/include/__chrono/gps_clock.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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