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