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_TIME_POINT_H
11#define _LIBCPP___CHRONO_TIME_POINT_H
12
13#include <__chrono/duration.h>
14#include <__compare/ordering.h>
15#include <__compare/three_way_comparable.h>
16#include <__config>
17#include <__cstddef/size_t.h>
18#include <__functional/hash.h>
19#include <__type_traits/common_type.h>
20#include <__type_traits/enable_if.h>
21#include <__type_traits/is_convertible.h>
22#include <limits>
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
33namespace chrono {
34
35template <class _Clock, class _Duration = typename _Clock::duration>
36class time_point {
37 static_assert(__is_duration_v<_Duration>, "Second template parameter of time_point must be a std::chrono::duration");
38
39public:
40 typedef _Clock clock;
41 typedef _Duration duration;
42 typedef typename duration::rep rep;
43 typedef typename duration::period period;
44
45private:
46 duration __d_;
47
48public:
49 _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point() : __d_(duration::zero()) {}
50 _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit time_point(const duration& __d) : __d_(__d) {}
51
52 // conversions
53 template <class _Duration2, __enable_if_t<is_convertible<_Duration2, duration>::value, int> = 0>
54 _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point(const time_point<clock, _Duration2>& __t) : __d_(__t.time_since_epoch()) {}
55
56 // observer
57
58 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX14 duration time_since_epoch() const { return __d_; }
59
60 // arithmetic
61
62#if _LIBCPP_STD_VER >= 20
63 constexpr time_point& operator++() {
64 ++__d_;
65 return *this;
66 }
67 constexpr time_point operator++(int) { return time_point{__d_++}; }
68 constexpr time_point& operator--() {
69 --__d_;
70 return *this;
71 }
72 constexpr time_point operator--(int) { return time_point{__d_--}; }
73#endif // _LIBCPP_STD_VER >= 20
74
75 _LIBCPP_CONSTEXPR_SINCE_CXX17 time_point& operator+=(const duration& __d) {
76 __d_ += __d;
77 return *this;
78 }
79 _LIBCPP_CONSTEXPR_SINCE_CXX17 time_point& operator-=(const duration& __d) {
80 __d_ -= __d;
81 return *this;
82 }
83
84 // special values
85
86 [[__nodiscard__]] static _LIBCPP_CONSTEXPR time_point min() _NOEXCEPT { return time_point(duration::min()); }
87 [[__nodiscard__]] static _LIBCPP_CONSTEXPR time_point max() _NOEXCEPT { return time_point(duration::max()); }
88};
89
90} // namespace chrono
91
92template <class _Clock, class _Duration1, class _Duration2>
93struct common_type<chrono::time_point<_Clock, _Duration1>, chrono::time_point<_Clock, _Duration2> > {
94 typedef chrono::time_point<_Clock, typename common_type<_Duration1, _Duration2>::type> type;
95};
96
97namespace chrono {
98
99template <class _ToDuration, class _Clock, class _Duration, __enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
100[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, _ToDuration>
101time_point_cast(const time_point<_Clock, _Duration>& __t) {
102 return time_point<_Clock, _ToDuration>(chrono::duration_cast<_ToDuration>(__t.time_since_epoch()));
103}
104
105#if _LIBCPP_STD_VER >= 17
106template <class _ToDuration, class _Clock, class _Duration, enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
107[[nodiscard]] inline constexpr time_point<_Clock, _ToDuration> floor(const time_point<_Clock, _Duration>& __t) {
108 return time_point<_Clock, _ToDuration>{chrono::floor<_ToDuration>(__t.time_since_epoch())};
109}
110
111template <class _ToDuration, class _Clock, class _Duration, enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
112[[nodiscard]] inline constexpr time_point<_Clock, _ToDuration> ceil(const time_point<_Clock, _Duration>& __t) {
113 return time_point<_Clock, _ToDuration>{chrono::ceil<_ToDuration>(__t.time_since_epoch())};
114}
115
116template <class _ToDuration, class _Clock, class _Duration, enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
117[[nodiscard]] inline constexpr time_point<_Clock, _ToDuration> round(const time_point<_Clock, _Duration>& __t) {
118 return time_point<_Clock, _ToDuration>{chrono::round<_ToDuration>(__t.time_since_epoch())};
119}
120
121template <class _Rep, class _Period, enable_if_t<numeric_limits<_Rep>::is_signed, int> = 0>
122[[nodiscard]] inline constexpr duration<_Rep, _Period> abs(duration<_Rep, _Period> __d) {
123 return __d >= __d.zero() ? +__d : -__d;
124}
125#endif // _LIBCPP_STD_VER >= 17
126
127// time_point ==
128
129template <class _Clock, class _Duration1, class _Duration2>
130inline _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
131operator==(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
132 return __lhs.time_since_epoch() == __rhs.time_since_epoch();
133}
134
135#if _LIBCPP_STD_VER <= 17
136
137// time_point !=
138
139template <class _Clock, class _Duration1, class _Duration2>
140inline _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
141operator!=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
142 return !(__lhs == __rhs);
143}
144
145#endif // _LIBCPP_STD_VER <= 17
146
147// time_point <
148
149template <class _Clock, class _Duration1, class _Duration2>
150inline _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
151operator<(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
152 return __lhs.time_since_epoch() < __rhs.time_since_epoch();
153}
154
155// time_point >
156
157template <class _Clock, class _Duration1, class _Duration2>
158inline _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
159operator>(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
160 return __rhs < __lhs;
161}
162
163// time_point <=
164
165template <class _Clock, class _Duration1, class _Duration2>
166inline _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
167operator<=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
168 return !(__rhs < __lhs);
169}
170
171// time_point >=
172
173template <class _Clock, class _Duration1, class _Duration2>
174inline _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
175operator>=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
176 return !(__lhs < __rhs);
177}
178
179#if _LIBCPP_STD_VER >= 20
180
181template <class _Clock, class _Duration1, three_way_comparable_with<_Duration1> _Duration2>
182constexpr auto operator<=>(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
183 return __lhs.time_since_epoch() <=> __rhs.time_since_epoch();
184}
185
186#endif // _LIBCPP_STD_VER >= 20
187
188// time_point operator+(time_point x, duration y);
189
190template <class _Clock, class _Duration1, class _Rep2, class _Period2>
191[[__nodiscard__]] inline
192 _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type>
193 operator+(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) {
194 typedef time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> _Tr;
195 return _Tr(__lhs.time_since_epoch() + __rhs);
196}
197
198// time_point operator+(duration x, time_point y);
199
200template <class _Rep1, class _Period1, class _Clock, class _Duration2>
201[[__nodiscard__]] inline
202 _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<duration<_Rep1, _Period1>, _Duration2>::type>
203 operator+(const duration<_Rep1, _Period1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
204 return __rhs + __lhs;
205}
206
207// time_point operator-(time_point x, duration y);
208
209template <class _Clock, class _Duration1, class _Rep2, class _Period2>
210[[__nodiscard__]] inline
211 _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type>
212 operator-(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) {
213 typedef time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> _Ret;
214 return _Ret(__lhs.time_since_epoch() - __rhs);
215}
216
217// duration operator-(time_point x, time_point y);
218
219template <class _Clock, class _Duration1, class _Duration2>
220[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX14 typename common_type<_Duration1, _Duration2>::type
221operator-(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
222 return __lhs.time_since_epoch() - __rhs.time_since_epoch();
223}
224
225} // namespace chrono
226
227#if _LIBCPP_STD_VER >= 26
228
229template <class _Clock, class _Duration>
230 requires __has_enabled_hash<_Duration>::value
231struct hash<chrono::time_point<_Clock, _Duration>> {
232 [[nodiscard]] static size_t operator()(const chrono::time_point<_Clock, _Duration>& __tp) {
233 return hash<_Duration>{}(__tp.time_since_epoch());
234 }
235};
236
237#endif // _LIBCPP_STD_VER >= 26
238
239_LIBCPP_END_NAMESPACE_STD
240
241_LIBCPP_POP_MACROS
242
243#endif // _LIBCPP___CHRONO_TIME_POINT_H
244