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_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point() : __d_(duration::zero()) {}
50 _LIBCPP_HIDE_FROM_ABI _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_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point(const time_point<clock, _Duration2>& __t)
55 : __d_(__t.time_since_epoch()) {}
56
57 // observer
58
59 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 duration time_since_epoch() const {
60 return __d_;
61 }
62
63 // arithmetic
64
65#if _LIBCPP_STD_VER >= 20
66 _LIBCPP_HIDE_FROM_ABI constexpr time_point& operator++() {
67 ++__d_;
68 return *this;
69 }
70 _LIBCPP_HIDE_FROM_ABI constexpr time_point operator++(int) { return time_point{__d_++}; }
71 _LIBCPP_HIDE_FROM_ABI constexpr time_point& operator--() {
72 --__d_;
73 return *this;
74 }
75 _LIBCPP_HIDE_FROM_ABI constexpr time_point operator--(int) { return time_point{__d_--}; }
76#endif // _LIBCPP_STD_VER >= 20
77
78 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 time_point& operator+=(const duration& __d) {
79 __d_ += __d;
80 return *this;
81 }
82 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 time_point& operator-=(const duration& __d) {
83 __d_ -= __d;
84 return *this;
85 }
86
87 // special values
88
89 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR time_point min() _NOEXCEPT {
90 return time_point(duration::min());
91 }
92 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR time_point max() _NOEXCEPT {
93 return time_point(duration::max());
94 }
95};
96
97} // namespace chrono
98
99template <class _Clock, class _Duration1, class _Duration2>
100struct common_type<chrono::time_point<_Clock, _Duration1>, chrono::time_point<_Clock, _Duration2> > {
101 typedef chrono::time_point<_Clock, typename common_type<_Duration1, _Duration2>::type> type;
102};
103
104namespace chrono {
105
106template <class _ToDuration, class _Clock, class _Duration, __enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
107[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, _ToDuration>
108time_point_cast(const time_point<_Clock, _Duration>& __t) {
109 return time_point<_Clock, _ToDuration>(chrono::duration_cast<_ToDuration>(__t.time_since_epoch()));
110}
111
112#if _LIBCPP_STD_VER >= 17
113template <class _ToDuration, class _Clock, class _Duration, enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
114[[nodiscard]] inline
115 _LIBCPP_HIDE_FROM_ABI constexpr time_point<_Clock, _ToDuration> floor(const time_point<_Clock, _Duration>& __t) {
116 return time_point<_Clock, _ToDuration>{chrono::floor<_ToDuration>(__t.time_since_epoch())};
117}
118
119template <class _ToDuration, class _Clock, class _Duration, enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
120[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI constexpr time_point<_Clock, _ToDuration>
121ceil(const time_point<_Clock, _Duration>& __t) {
122 return time_point<_Clock, _ToDuration>{chrono::ceil<_ToDuration>(__t.time_since_epoch())};
123}
124
125template <class _ToDuration, class _Clock, class _Duration, enable_if_t<__is_duration_v<_ToDuration>, int> = 0>
126[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI constexpr time_point<_Clock, _ToDuration>
127round(const time_point<_Clock, _Duration>& __t) {
128 return time_point<_Clock, _ToDuration>{chrono::round<_ToDuration>(__t.time_since_epoch())};
129}
130
131template <class _Rep, class _Period, enable_if_t<numeric_limits<_Rep>::is_signed, int> = 0>
132[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI constexpr duration<_Rep, _Period> abs(duration<_Rep, _Period> __d) {
133 return __d >= __d.zero() ? +__d : -__d;
134}
135#endif // _LIBCPP_STD_VER >= 17
136
137// time_point ==
138
139template <class _Clock, class _Duration1, class _Duration2>
140inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
141operator==(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
142 return __lhs.time_since_epoch() == __rhs.time_since_epoch();
143}
144
145#if _LIBCPP_STD_VER <= 17
146
147// time_point !=
148
149template <class _Clock, class _Duration1, class _Duration2>
150inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
151operator!=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
152 return !(__lhs == __rhs);
153}
154
155#endif // _LIBCPP_STD_VER <= 17
156
157// time_point <
158
159template <class _Clock, class _Duration1, class _Duration2>
160inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
161operator<(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
162 return __lhs.time_since_epoch() < __rhs.time_since_epoch();
163}
164
165// time_point >
166
167template <class _Clock, class _Duration1, class _Duration2>
168inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
169operator>(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
170 return __rhs < __lhs;
171}
172
173// time_point <=
174
175template <class _Clock, class _Duration1, class _Duration2>
176inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
177operator<=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
178 return !(__rhs < __lhs);
179}
180
181// time_point >=
182
183template <class _Clock, class _Duration1, class _Duration2>
184inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
185operator>=(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
186 return !(__lhs < __rhs);
187}
188
189#if _LIBCPP_STD_VER >= 20
190
191template <class _Clock, class _Duration1, three_way_comparable_with<_Duration1> _Duration2>
192_LIBCPP_HIDE_FROM_ABI constexpr auto
193operator<=>(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
194 return __lhs.time_since_epoch() <=> __rhs.time_since_epoch();
195}
196
197#endif // _LIBCPP_STD_VER >= 20
198
199// time_point operator+(time_point x, duration y);
200
201template <class _Clock, class _Duration1, class _Rep2, class _Period2>
202[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
203_LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type>
204operator+(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) {
205 typedef time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> _Tr;
206 return _Tr(__lhs.time_since_epoch() + __rhs);
207}
208
209// time_point operator+(duration x, time_point y);
210
211template <class _Rep1, class _Period1, class _Clock, class _Duration2>
212[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
213_LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<duration<_Rep1, _Period1>, _Duration2>::type>
214operator+(const duration<_Rep1, _Period1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
215 return __rhs + __lhs;
216}
217
218// time_point operator-(time_point x, duration y);
219
220template <class _Clock, class _Duration1, class _Rep2, class _Period2>
221[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
222_LIBCPP_CONSTEXPR_SINCE_CXX14 time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type>
223operator-(const time_point<_Clock, _Duration1>& __lhs, const duration<_Rep2, _Period2>& __rhs) {
224 typedef time_point<_Clock, typename common_type<_Duration1, duration<_Rep2, _Period2> >::type> _Ret;
225 return _Ret(__lhs.time_since_epoch() - __rhs);
226}
227
228// duration operator-(time_point x, time_point y);
229
230template <class _Clock, class _Duration1, class _Duration2>
231[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
232typename common_type<_Duration1, _Duration2>::type
233operator-(const time_point<_Clock, _Duration1>& __lhs, const time_point<_Clock, _Duration2>& __rhs) {
234 return __lhs.time_since_epoch() - __rhs.time_since_epoch();
235}
236
237} // namespace chrono
238
239#if _LIBCPP_STD_VER >= 26
240
241template <class _Clock, class _Duration>
242 requires __has_enabled_hash<_Duration>::value
243struct hash<chrono::time_point<_Clock, _Duration>> {
244 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static size_t operator()(const chrono::time_point<_Clock, _Duration>& __tp) {
245 return hash<_Duration>{}(__tp.time_since_epoch());
246 }
247};
248
249#endif // _LIBCPP_STD_VER >= 26
250
251_LIBCPP_END_NAMESPACE_STD
252
253_LIBCPP_POP_MACROS
254
255#endif // _LIBCPP___CHRONO_TIME_POINT_H
256