Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #pragma once |
8 | | |
9 | | #include <AK/Array.h> |
10 | | #include <AK/Assertions.h> |
11 | | #include <AK/Badge.h> |
12 | | #include <AK/Checked.h> |
13 | | #include <AK/Platform.h> |
14 | | #include <AK/Tuple.h> |
15 | | #include <AK/Types.h> |
16 | | |
17 | | #if defined(AK_OS_SERENITY) && defined(KERNEL) |
18 | | # include <Kernel/API/POSIX/sys/time.h> |
19 | | # include <Kernel/API/POSIX/time.h> |
20 | | |
21 | | // We need a Badge<TimeManagement> for some MonotonicTime operations. |
22 | | namespace Kernel { |
23 | | class TimeManagement; |
24 | | } |
25 | | |
26 | | #else |
27 | | # include <sys/time.h> |
28 | | # include <time.h> |
29 | | #endif |
30 | | |
31 | | namespace AK { |
32 | | |
33 | | // Concept to detect types which look like timespec without requiring the type. |
34 | | template<typename T> |
35 | | concept TimeSpecType = requires(T t) { |
36 | | t.tv_sec; |
37 | | t.tv_nsec; |
38 | | }; |
39 | | |
40 | | constexpr bool is_leap_year(int year) |
41 | 1.37k | { |
42 | 1.37k | return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); |
43 | 1.37k | } |
44 | | |
45 | | // Month and day start at 1. Month must be >= 1 and <= 12. |
46 | | // The return value is 0-indexed, that is 0 is Sunday, 1 is Monday, etc. |
47 | | // Day may be negative or larger than the number of days |
48 | | // in the given month. |
49 | | unsigned day_of_week(int year, unsigned month, int day); |
50 | | |
51 | | // Month and day start at 1. Month must be >= 1 and <= 12. |
52 | | // The return value is 0-indexed, that is Jan 1 is day 0. |
53 | | // Day may be negative or larger than the number of days |
54 | | // in the given month. If day is negative enough, the result |
55 | | // can be negative. |
56 | | constexpr int day_of_year(int year, unsigned month, int day) |
57 | 2.63k | { |
58 | 2.63k | if (is_constant_evaluated()) |
59 | 0 | VERIFY(month >= 1 && month <= 12); // Note that this prevents bad constexpr months, but never actually prints anything. |
60 | 2.63k | else if (!(month >= 1 && month <= 12)) |
61 | 1.25k | return 0; |
62 | | |
63 | 1.37k | constexpr Array seek_table = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; |
64 | 1.37k | int day_of_year = seek_table[month - 1] + day - 1; |
65 | | |
66 | 1.37k | if (is_leap_year(year) && month >= 3) |
67 | 299 | day_of_year++; |
68 | | |
69 | 1.37k | return day_of_year; |
70 | 2.63k | } AK::day_of_year(int, unsigned int, int) Line | Count | Source | 57 | 2.63k | { | 58 | 2.63k | if (is_constant_evaluated()) | 59 | 0 | VERIFY(month >= 1 && month <= 12); // Note that this prevents bad constexpr months, but never actually prints anything. | 60 | 2.63k | else if (!(month >= 1 && month <= 12)) | 61 | 1.25k | return 0; | 62 | | | 63 | 1.37k | constexpr Array seek_table = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; | 64 | 1.37k | int day_of_year = seek_table[month - 1] + day - 1; | 65 | | | 66 | 1.37k | if (is_leap_year(year) && month >= 3) | 67 | 299 | day_of_year++; | 68 | | | 69 | 1.37k | return day_of_year; | 70 | 2.63k | } |
Unexecuted instantiation: AK::day_of_year(int, unsigned int, int) |
71 | | |
72 | | // Month starts at 1. Month must be >= 1 and <= 12. |
73 | | int days_in_month(int year, unsigned month); |
74 | | |
75 | | constexpr int days_in_year(int year) |
76 | 0 | { |
77 | 0 | return 365 + (is_leap_year(year) ? 1 : 0); |
78 | 0 | } |
79 | | |
80 | | namespace Detail { |
81 | | // Integer division rounding towards negative infinity. |
82 | | // TODO: This feels like there should be an easier way to do this. |
83 | | template<int divisor> |
84 | | constexpr i64 floor_div_by(i64 dividend) |
85 | 15.7k | { |
86 | 15.7k | static_assert(divisor > 1); |
87 | 15.7k | int is_negative = dividend < 0; |
88 | 15.7k | return (dividend + is_negative) / divisor - is_negative; |
89 | 15.7k | } long AK::Detail::floor_div_by<4>(long) Line | Count | Source | 85 | 5.26k | { | 86 | 5.26k | static_assert(divisor > 1); | 87 | 5.26k | int is_negative = dividend < 0; | 88 | 5.26k | return (dividend + is_negative) / divisor - is_negative; | 89 | 5.26k | } |
long AK::Detail::floor_div_by<100>(long) Line | Count | Source | 85 | 5.26k | { | 86 | 5.26k | static_assert(divisor > 1); | 87 | 5.26k | int is_negative = dividend < 0; | 88 | 5.26k | return (dividend + is_negative) / divisor - is_negative; | 89 | 5.26k | } |
long AK::Detail::floor_div_by<400>(long) Line | Count | Source | 85 | 5.26k | { | 86 | 5.26k | static_assert(divisor > 1); | 87 | 5.26k | int is_negative = dividend < 0; | 88 | 5.26k | return (dividend + is_negative) / divisor - is_negative; | 89 | 5.26k | } |
|
90 | | |
91 | | // Counts how many integers n are in the interval [begin, end) with n % positive_mod == 0. |
92 | | // NOTE: "end" is not considered to be part of the range, hence "[begin, end)". |
93 | | template<int positive_mod> |
94 | | constexpr i64 mod_zeros_in_range(i64 begin, i64 end) |
95 | 7.89k | { |
96 | 7.89k | return floor_div_by<positive_mod>(end - 1) - floor_div_by<positive_mod>(begin - 1); |
97 | 7.89k | } long AK::Detail::mod_zeros_in_range<4>(long, long) Line | Count | Source | 95 | 2.63k | { | 96 | 2.63k | return floor_div_by<positive_mod>(end - 1) - floor_div_by<positive_mod>(begin - 1); | 97 | 2.63k | } |
long AK::Detail::mod_zeros_in_range<100>(long, long) Line | Count | Source | 95 | 2.63k | { | 96 | 2.63k | return floor_div_by<positive_mod>(end - 1) - floor_div_by<positive_mod>(begin - 1); | 97 | 2.63k | } |
long AK::Detail::mod_zeros_in_range<400>(long, long) Line | Count | Source | 95 | 2.63k | { | 96 | 2.63k | return floor_div_by<positive_mod>(end - 1) - floor_div_by<positive_mod>(begin - 1); | 97 | 2.63k | } |
|
98 | | } |
99 | | |
100 | | constexpr i64 years_to_days_since_epoch(int year) |
101 | 2.63k | { |
102 | 2.63k | int begin_year, end_year, leap_sign; |
103 | 2.63k | if (year < 1970) { |
104 | 507 | begin_year = year; |
105 | 507 | end_year = 1970; |
106 | 507 | leap_sign = -1; |
107 | 2.12k | } else { |
108 | 2.12k | begin_year = 1970; |
109 | 2.12k | end_year = year; |
110 | 2.12k | leap_sign = +1; |
111 | 2.12k | } |
112 | 2.63k | i64 year_i64 = year; |
113 | | // This duplicates the logic of 'is_leap_year', with the advantage of not needing any loops. |
114 | | // Given that the definition of leap years is not expected to change, this should be a good trade-off. |
115 | 2.63k | i64 days = 365 * (year_i64 - 1970); |
116 | 2.63k | i64 extra_leap_days = 0; |
117 | 2.63k | extra_leap_days += Detail::mod_zeros_in_range<4>(begin_year, end_year); |
118 | 2.63k | extra_leap_days -= Detail::mod_zeros_in_range<100>(begin_year, end_year); |
119 | 2.63k | extra_leap_days += Detail::mod_zeros_in_range<400>(begin_year, end_year); |
120 | 2.63k | return days + extra_leap_days * leap_sign; |
121 | 2.63k | } |
122 | | |
123 | | constexpr i64 days_since_epoch(int year, int month, int day) |
124 | 2.63k | { |
125 | 2.63k | return years_to_days_since_epoch(year) + day_of_year(year, month, day); |
126 | 2.63k | } |
127 | | |
128 | | template<typename T> |
129 | | constexpr Tuple<T, u8, u8> days_since_epoch_to_date(T days) |
130 | 0 | { |
131 | | // Adapted from https://howardhinnant.github.io/date_algorithms.html#civil_from_days |
132 | 0 | static_assert(NumericLimits<T>::digits() >= 20, "This algorithm has not been ported to a 16 bit signed integer"); |
133 | | |
134 | | // An era is a 400 year period. |
135 | 0 | constexpr u32 last_day_of_year_three = 4 * 365; |
136 | 0 | constexpr u32 days_in_first_hundred_era_years = 365 * 100 + 100 / 4 - 1; |
137 | 0 | constexpr u64 era_days = 365 * 400 + 100 - 3; |
138 | 0 | constexpr u32 last_day_of_era = era_days - 1; |
139 | 0 | constexpr u32 era_month_offset = 2; |
140 | | |
141 | | // Shift the epoch from 1970-01-01 to 0000-03-01. |
142 | 0 | VERIFY(days <= NumericLimits<T>::max() - 719468); |
143 | 0 | days += 719468; |
144 | |
|
145 | 0 | T era = (days >= 0 ? days : days - last_day_of_era) / era_days; |
146 | 0 | u32 day_of_era = days - era * era_days; |
147 | 0 | u32 year_of_era = (day_of_era - day_of_era / last_day_of_year_three + day_of_era / days_in_first_hundred_era_years - day_of_era / last_day_of_era) / 365; |
148 | | // The latter part of this comes from accounting for leap years (the year 400 need not be accounted for, because an era only has 400 years in total). |
149 | 0 | u32 day_of_year_of_era = day_of_era - (365 * year_of_era + year_of_era / 4 - year_of_era / 100); |
150 | | // Starting from March 1st, not January 1st. |
151 | 0 | u32 month_of_era = (5 * day_of_year_of_era + 2) / 153; |
152 | 0 | u32 day = day_of_year_of_era - (153 * month_of_era + 2) / 5 + 1; |
153 | 0 | u32 month = month_of_era < 10 ? month_of_era + 3 : month_of_era - 9; |
154 | 0 | T year = (static_cast<T>(year_of_era) + era * 400) + (month <= era_month_offset); |
155 | |
|
156 | 0 | return { year, month, day }; |
157 | 0 | } Unexecuted instantiation: AK::Tuple<long, unsigned char, unsigned char> AK::days_since_epoch_to_date<long>(long) Unexecuted instantiation: AK::Tuple<unsigned long, unsigned char, unsigned char> AK::days_since_epoch_to_date<unsigned long>(unsigned long) |
158 | | |
159 | | constexpr i64 seconds_since_epoch_to_year(i64 seconds) |
160 | 0 | { |
161 | 0 | constexpr auto seconds_per_day = 60 * 60 * 24; |
162 | 0 | i64 day_offset_to_epoch = seconds >= 0 ? seconds / seconds_per_day : floor_div(seconds, seconds_per_day); |
163 | 0 | auto [year, month, day] = days_since_epoch_to_date(day_offset_to_epoch); |
164 | 0 | return year; |
165 | 0 | } |
166 | | |
167 | | // Represents a duration in a "safe" way. |
168 | | // Minimum: -(2**63) seconds, 0 nanoseconds |
169 | | // Maximum: 2**63-1 seconds, 999'999'999 nanoseconds |
170 | | // If any operation (e.g. 'from_timeval' or operator-) would over- or underflow, the closest legal value is returned instead. |
171 | | // Inputs (e.g. to 'from_timespec') are allowed to be in non-normal form (e.g. "1 second, 2'012'345'678 nanoseconds" or "1 second, -2 microseconds"). |
172 | | // Outputs (e.g. from 'to_timeval') are always in normal form. |
173 | | // |
174 | | // NOTE: This class is naive. It may represent either absolute offsets or relative durations. It does not have a reference point in itself, |
175 | | // and therefore comparing multiple instances of this class is only sensible if you are sure that their reference point is identical. |
176 | | // You should not be using this class directly to represent absolute time. |
177 | | class Duration { |
178 | | public: |
179 | 0 | constexpr Duration() = default; |
180 | | constexpr Duration(Duration const&) = default; |
181 | | constexpr Duration& operator=(Duration const&) = default; |
182 | | |
183 | | constexpr Duration(Duration&& other) |
184 | 0 | : m_seconds(exchange(other.m_seconds, 0)) |
185 | 0 | , m_nanoseconds(exchange(other.m_nanoseconds, 0)) |
186 | 0 | { |
187 | 0 | } |
188 | | constexpr Duration& operator=(Duration&& other) |
189 | 0 | { |
190 | 0 | if (this != &other) { |
191 | 0 | m_seconds = exchange(other.m_seconds, 0); |
192 | 0 | m_nanoseconds = exchange(other.m_nanoseconds, 0); |
193 | 0 | } |
194 | 0 | return *this; |
195 | 0 | } |
196 | | |
197 | | private: |
198 | | // This must be part of the header in order to make the various 'from_*' functions constexpr. |
199 | | // However, sane_mod can only deal with a limited range of values for 'denominator', so this can't be made public. |
200 | | ALWAYS_INLINE static constexpr i64 sane_mod(i64& numerator, i64 denominator) |
201 | 2.68k | { |
202 | 2.68k | VERIFY(2 <= denominator && denominator <= 1'000'000'000); |
203 | | // '%' in C/C++ does not work in the obvious way: |
204 | | // For example, -9 % 7 is -2, not +5. |
205 | | // However, we want a representation like "(-2)*7 + (+5)". |
206 | 2.68k | i64 dividend = numerator / denominator; |
207 | 2.68k | numerator %= denominator; |
208 | 2.68k | if (numerator < 0) { |
209 | | // Does not overflow: different signs. |
210 | 0 | numerator += denominator; |
211 | | // Does not underflow: denominator >= 2. |
212 | 0 | dividend -= 1; |
213 | 0 | } |
214 | 2.68k | return dividend; |
215 | 2.68k | } |
216 | | ALWAYS_INLINE static constexpr i32 sane_mod(i32& numerator, i32 denominator) |
217 | 54 | { |
218 | 54 | i64 numerator_64 = numerator; |
219 | 54 | i64 dividend = sane_mod(numerator_64, denominator); |
220 | | // Does not underflow: numerator can only become smaller. |
221 | 54 | numerator = static_cast<i32>(numerator_64); |
222 | | // Does not overflow: Will be smaller than original value of 'numerator'. |
223 | 54 | return static_cast<i32>(dividend); |
224 | 54 | } |
225 | | |
226 | | public: |
227 | 2.63k | [[nodiscard]] constexpr static Duration from_seconds(i64 seconds) { return Duration(seconds, 0); } |
228 | | [[nodiscard]] constexpr static Duration from_nanoseconds(i64 nanoseconds) |
229 | 0 | { |
230 | 0 | i64 seconds = sane_mod(nanoseconds, 1'000'000'000); |
231 | 0 | return Duration(seconds, nanoseconds); |
232 | 0 | } |
233 | | [[nodiscard]] constexpr static Duration from_microseconds(i64 microseconds) |
234 | 0 | { |
235 | 0 | i64 seconds = sane_mod(microseconds, 1'000'000); |
236 | 0 | return Duration(seconds, microseconds * 1'000); |
237 | 0 | } |
238 | | [[nodiscard]] constexpr static Duration from_milliseconds(i64 milliseconds) |
239 | 2.63k | { |
240 | 2.63k | i64 seconds = sane_mod(milliseconds, 1'000); |
241 | 2.63k | return Duration(seconds, milliseconds * 1'000'000); |
242 | 2.63k | } |
243 | | [[nodiscard]] static Duration from_ticks(clock_t, time_t); |
244 | | [[nodiscard]] static Duration from_timespec(const struct timespec&); |
245 | | [[nodiscard]] static Duration from_timeval(const struct timeval&); |
246 | | // We don't pull in <stdint.h> for the pretty min/max definitions because this file is also included in the Kernel |
247 | 0 | [[nodiscard]] constexpr static Duration min() { return Duration(-__INT64_MAX__ - 1LL, 0); } |
248 | 9.34k | [[nodiscard]] constexpr static Duration zero() { return Duration(0, 0); } |
249 | 0 | [[nodiscard]] constexpr static Duration max() { return Duration(__INT64_MAX__, 999'999'999); } |
250 | | |
251 | | // Truncates towards zero (2.8s to 2s, -2.8s to -2s). |
252 | | [[nodiscard]] i64 to_truncated_seconds() const; |
253 | | [[nodiscard]] i64 to_truncated_milliseconds() const; |
254 | | [[nodiscard]] i64 to_truncated_microseconds() const; |
255 | | |
256 | | // Rounds away from zero (2.3s to 3s, -2.3s to -3s). |
257 | | [[nodiscard]] constexpr i64 to_seconds() const |
258 | 0 | { |
259 | 0 | VERIFY(m_nanoseconds < 1'000'000'000); |
260 | 0 | if (m_seconds >= 0 && m_nanoseconds) |
261 | 0 | return Checked<i64>::saturating_add(m_seconds, 1); |
262 | | |
263 | 0 | return m_seconds; |
264 | 0 | } Unexecuted instantiation: AK::Duration::to_seconds() const Unexecuted instantiation: AK::Duration::to_seconds() const |
265 | | |
266 | | [[nodiscard]] constexpr i64 to_milliseconds() const |
267 | 0 | { |
268 | 0 | VERIFY(m_nanoseconds < 1'000'000'000); |
269 | 0 | Checked<i64> milliseconds((m_seconds < 0) ? m_seconds + 1 : m_seconds); |
270 | 0 | milliseconds *= 1'000; |
271 | 0 | milliseconds += m_nanoseconds / 1'000'000; |
272 | 0 | if (m_seconds >= 0 && m_nanoseconds % 1'000'000 != 0) |
273 | 0 | milliseconds++; |
274 | 0 | if (m_seconds < 0) { |
275 | | // We dropped one second previously, put it back in now that we have handled the rounding. |
276 | 0 | milliseconds -= 1'000; |
277 | 0 | } |
278 | 0 | if (!milliseconds.has_overflow()) |
279 | 0 | return milliseconds.value(); |
280 | 0 | return m_seconds < 0 ? -0x8000'0000'0000'0000LL : 0x7fff'ffff'ffff'ffffLL; |
281 | 0 | } Unexecuted instantiation: AK::Duration::to_milliseconds() const Unexecuted instantiation: AK::Duration::to_milliseconds() const |
282 | | |
283 | | [[nodiscard]] constexpr i64 to_microseconds() const |
284 | 0 | { |
285 | 0 | VERIFY(m_nanoseconds < 1'000'000'000); |
286 | 0 | Checked<i64> microseconds((m_seconds < 0) ? m_seconds + 1 : m_seconds); |
287 | 0 | microseconds *= 1'000'000; |
288 | 0 | microseconds += m_nanoseconds / 1'000; |
289 | 0 | if (m_seconds >= 0 && m_nanoseconds % 1'000 != 0) |
290 | 0 | microseconds++; |
291 | 0 | if (m_seconds < 0) { |
292 | 0 | // We dropped one second previously, put it back in now that we have handled the rounding. |
293 | 0 | microseconds -= 1'000'000; |
294 | 0 | } |
295 | 0 | if (!microseconds.has_overflow()) |
296 | 0 | return microseconds.value(); |
297 | 0 | return m_seconds < 0 ? -0x8000'0000'0000'0000LL : 0x7fff'ffff'ffff'ffffLL; |
298 | 0 | } |
299 | | |
300 | | [[nodiscard]] constexpr i64 to_nanoseconds() const |
301 | 0 | { |
302 | 0 | VERIFY(m_nanoseconds < 1'000'000'000); |
303 | 0 | Checked<i64> nanoseconds((m_seconds < 0) ? m_seconds + 1 : m_seconds); |
304 | 0 | nanoseconds *= 1'000'000'000; |
305 | 0 | nanoseconds += m_nanoseconds; |
306 | 0 | if (m_seconds < 0) { |
307 | | // We dropped one second previously, put it back in now that we have handled the rounding. |
308 | 0 | nanoseconds -= 1'000'000'000; |
309 | 0 | } |
310 | 0 | if (!nanoseconds.has_overflow()) |
311 | 0 | return nanoseconds.value(); |
312 | 0 | return m_seconds < 0 ? -0x8000'0000'0000'0000LL : 0x7fff'ffff'ffff'ffffLL; |
313 | 0 | } Unexecuted instantiation: AK::Duration::to_nanoseconds() const Unexecuted instantiation: AK::Duration::to_nanoseconds() const |
314 | | |
315 | | [[nodiscard]] timespec to_timespec() const; |
316 | | // Rounds towards -inf (it was the easiest to implement). |
317 | | [[nodiscard]] timeval to_timeval() const; |
318 | | |
319 | | [[nodiscard]] constexpr i64 nanoseconds_within_second() const |
320 | 0 | { |
321 | 0 | VERIFY(m_nanoseconds < 1'000'000'000); |
322 | 0 | return m_nanoseconds; |
323 | 0 | } |
324 | | |
325 | 0 | [[nodiscard]] bool is_zero() const { return (m_seconds == 0) && (m_nanoseconds == 0); } |
326 | 0 | [[nodiscard]] bool is_negative() const { return m_seconds < 0; } |
327 | | |
328 | | constexpr Duration operator+(Duration const& other) const |
329 | 2.63k | { |
330 | 2.63k | VERIFY(m_nanoseconds < 1'000'000'000); |
331 | 2.63k | VERIFY(other.m_nanoseconds < 1'000'000'000); |
332 | | |
333 | 2.63k | u32 new_nsecs = m_nanoseconds + other.m_nanoseconds; |
334 | 2.63k | u32 extra_secs = new_nsecs / 1'000'000'000; |
335 | 2.63k | new_nsecs %= 1'000'000'000; |
336 | | |
337 | 2.63k | i64 this_secs = m_seconds; |
338 | 2.63k | i64 other_secs = other.m_seconds; |
339 | | // We would like to just add "this_secs + other_secs + extra_secs". |
340 | | // However, computing this naively may overflow even though the result is in-bounds. |
341 | | // Example in 8-bit: (-127) + (-2) + (+1) = (-128), which fits in an i8. |
342 | | // Example in 8-bit, the other way around: (-2) + (127) + (+1) = 126. |
343 | | // So we do something more sophisticated: |
344 | 2.63k | if (extra_secs) { |
345 | 0 | VERIFY(extra_secs == 1); |
346 | 0 | if (this_secs != 0x7fff'ffff'ffff'ffff) { |
347 | 0 | this_secs += 1; |
348 | 0 | } else if (other_secs != 0x7fff'ffff'ffff'ffff) { |
349 | 0 | other_secs += 1; |
350 | 0 | } else { |
351 | | /* If *both* are INT64_MAX, then adding them will overflow in any case. */ |
352 | 0 | return Duration::max(); |
353 | 0 | } |
354 | 0 | } |
355 | | |
356 | 2.63k | Checked<i64> new_secs { this_secs }; |
357 | 2.63k | new_secs += other_secs; |
358 | 2.63k | if (new_secs.has_overflow()) { |
359 | 0 | if (other_secs > 0) |
360 | 0 | return Duration::max(); |
361 | 0 | else |
362 | 0 | return Duration::min(); |
363 | 0 | } |
364 | | |
365 | 2.63k | return Duration { new_secs.value(), new_nsecs }; |
366 | 2.63k | } AK::Duration::operator+(AK::Duration const&) const Line | Count | Source | 329 | 2.63k | { | 330 | 2.63k | VERIFY(m_nanoseconds < 1'000'000'000); | 331 | 2.63k | VERIFY(other.m_nanoseconds < 1'000'000'000); | 332 | | | 333 | 2.63k | u32 new_nsecs = m_nanoseconds + other.m_nanoseconds; | 334 | 2.63k | u32 extra_secs = new_nsecs / 1'000'000'000; | 335 | 2.63k | new_nsecs %= 1'000'000'000; | 336 | | | 337 | 2.63k | i64 this_secs = m_seconds; | 338 | 2.63k | i64 other_secs = other.m_seconds; | 339 | | // We would like to just add "this_secs + other_secs + extra_secs". | 340 | | // However, computing this naively may overflow even though the result is in-bounds. | 341 | | // Example in 8-bit: (-127) + (-2) + (+1) = (-128), which fits in an i8. | 342 | | // Example in 8-bit, the other way around: (-2) + (127) + (+1) = 126. | 343 | | // So we do something more sophisticated: | 344 | 2.63k | if (extra_secs) { | 345 | 0 | VERIFY(extra_secs == 1); | 346 | 0 | if (this_secs != 0x7fff'ffff'ffff'ffff) { | 347 | 0 | this_secs += 1; | 348 | 0 | } else if (other_secs != 0x7fff'ffff'ffff'ffff) { | 349 | 0 | other_secs += 1; | 350 | 0 | } else { | 351 | | /* If *both* are INT64_MAX, then adding them will overflow in any case. */ | 352 | 0 | return Duration::max(); | 353 | 0 | } | 354 | 0 | } | 355 | | | 356 | 2.63k | Checked<i64> new_secs { this_secs }; | 357 | 2.63k | new_secs += other_secs; | 358 | 2.63k | if (new_secs.has_overflow()) { | 359 | 0 | if (other_secs > 0) | 360 | 0 | return Duration::max(); | 361 | 0 | else | 362 | 0 | return Duration::min(); | 363 | 0 | } | 364 | | | 365 | 2.63k | return Duration { new_secs.value(), new_nsecs }; | 366 | 2.63k | } |
Unexecuted instantiation: AK::Duration::operator+(AK::Duration const&) const |
367 | | |
368 | | constexpr Duration& operator+=(Duration const& other) |
369 | 0 | { |
370 | 0 | *this = *this + other; |
371 | 0 | return *this; |
372 | 0 | } |
373 | | |
374 | | constexpr Duration operator-(Duration const& other) const |
375 | 0 | { |
376 | 0 | VERIFY(m_nanoseconds < 1'000'000'000); |
377 | 0 | VERIFY(other.m_nanoseconds < 1'000'000'000); |
378 | | |
379 | 0 | if (other.m_nanoseconds) |
380 | 0 | return *this + Duration((i64) ~(u64)other.m_seconds, 1'000'000'000 - other.m_nanoseconds); |
381 | | |
382 | 0 | if (other.m_seconds != (i64)-0x8000'0000'0000'0000) |
383 | 0 | return *this + Duration(-other.m_seconds, 0); |
384 | | |
385 | | // Only remaining case: We want to subtract -0x8000'0000'0000'0000 seconds, |
386 | | // i.e. add a very large number. |
387 | | |
388 | 0 | if (m_seconds >= 0) |
389 | 0 | return Duration::max(); |
390 | 0 | return Duration { (m_seconds + 0x4000'0000'0000'0000) + 0x4000'0000'0000'0000, m_nanoseconds }; |
391 | 0 | } Unexecuted instantiation: AK::Duration::operator-(AK::Duration const&) const Unexecuted instantiation: AK::Duration::operator-(AK::Duration const&) const |
392 | | |
393 | | constexpr Duration& operator-=(Duration const& other) |
394 | 0 | { |
395 | 0 | *this = *this - other; |
396 | 0 | return *this; |
397 | 0 | } |
398 | | |
399 | 0 | constexpr bool operator==(Duration const& other) const = default; |
400 | | constexpr int operator<=>(Duration const& other) const |
401 | 0 | { |
402 | 0 | if (int cmp = (m_seconds > other.m_seconds ? 1 : m_seconds < other.m_seconds ? -1 |
403 | 0 | : 0); |
404 | 0 | cmp != 0) |
405 | 0 | return cmp; |
406 | 0 | if (int cmp = (m_nanoseconds > other.m_nanoseconds ? 1 : m_nanoseconds < other.m_nanoseconds ? -1 |
407 | 0 | : 0); |
408 | 0 | cmp != 0) |
409 | 0 | return cmp; |
410 | 0 | return 0; |
411 | 0 | } |
412 | | |
413 | | private: |
414 | | constexpr explicit Duration(i64 seconds, u32 nanoseconds) |
415 | 17.2k | : m_seconds(seconds) |
416 | 17.2k | , m_nanoseconds(nanoseconds) |
417 | 17.2k | { |
418 | 17.2k | } |
419 | | |
420 | | [[nodiscard]] static Duration from_half_sanitized(i64 seconds, i32 extra_seconds, u32 nanoseconds); |
421 | | |
422 | | i64 m_seconds { 0 }; |
423 | | u32 m_nanoseconds { 0 }; // Always less than 1'000'000'000 |
424 | | }; |
425 | | |
426 | | namespace Detail { |
427 | | |
428 | | // Common base class for all unaware time types. |
429 | | // Naive, or unaware, in the time context means to make heavily simplifying assumptions about time. |
430 | | // In the case of this class and its children, they are not timezone-aware and strictly ordered. |
431 | | class UnawareTime { |
432 | | public: |
433 | | constexpr UnawareTime(UnawareTime const&) = default; |
434 | | constexpr UnawareTime& operator=(UnawareTime const&) = default; |
435 | | |
436 | 0 | [[nodiscard]] timespec to_timespec() const { return m_offset.to_timespec(); } |
437 | | // Rounds towards -inf. |
438 | 0 | [[nodiscard]] timeval to_timeval() const { return m_offset.to_timeval(); } |
439 | | |
440 | | // We intentionally do not define a comparison operator here to avoid accidentally comparing incompatible time types. |
441 | | |
442 | | protected: |
443 | | constexpr explicit UnawareTime(Duration offset) |
444 | 13.8k | : m_offset(offset) |
445 | 13.8k | { |
446 | 13.8k | } |
447 | | |
448 | | Duration m_offset {}; |
449 | | }; |
450 | | |
451 | | } |
452 | | |
453 | | // Naive UNIX time, representing an offset from 1970-01-01 00:00:00Z, without accounting for UTC leap seconds. |
454 | | // This class is mainly intended for interoperating with anything that expects a unix timestamp. |
455 | | class UnixDateTime : public Detail::UnawareTime { |
456 | | public: |
457 | | constexpr UnixDateTime() |
458 | 8.57k | : Detail::UnawareTime(Duration::zero()) |
459 | 8.57k | { |
460 | 8.57k | } |
461 | | |
462 | | constexpr static UnixDateTime epoch() |
463 | 0 | { |
464 | 0 | return UnixDateTime {}; |
465 | 0 | } |
466 | | |
467 | | // Creates UNIX time from a unix timestamp. |
468 | | // Note that the returned time is probably not equivalent to the same timestamp in UTC time, since UNIX time does not observe leap seconds. |
469 | | [[nodiscard]] constexpr static UnixDateTime from_unix_time_parts(i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond) |
470 | 2.63k | { |
471 | 2.63k | constexpr auto seconds_per_day = 86'400; |
472 | 2.63k | constexpr auto seconds_per_hour = 3'600; |
473 | 2.63k | constexpr auto seconds_per_minute = 60; |
474 | | |
475 | 2.63k | i64 days = days_since_epoch(year, month, day); |
476 | | // With year=2'147'483'648, we can end up with days=569'603'931'504. |
477 | | // Expressing that in milliseconds would require more than 64 bits, |
478 | | // so we must choose seconds here, and not milliseconds. |
479 | 2.63k | i64 seconds_since_epoch = days * seconds_per_day; |
480 | | |
481 | 2.63k | seconds_since_epoch += hour * seconds_per_hour; |
482 | 2.63k | seconds_since_epoch += minute * seconds_per_minute; |
483 | 2.63k | seconds_since_epoch += second; |
484 | 2.63k | return from_seconds_since_epoch(seconds_since_epoch) + Duration::from_milliseconds(millisecond); |
485 | 2.63k | } |
486 | | |
487 | | [[nodiscard]] constexpr static UnixDateTime from_seconds_since_epoch(i64 seconds) |
488 | 2.63k | { |
489 | 2.63k | return UnixDateTime { Duration::from_seconds(seconds) }; |
490 | 2.63k | } |
491 | | |
492 | | [[nodiscard]] constexpr static UnixDateTime from_milliseconds_since_epoch(i64 milliseconds) |
493 | 0 | { |
494 | 0 | return UnixDateTime { Duration::from_milliseconds(milliseconds) }; |
495 | 0 | } |
496 | | |
497 | | [[nodiscard]] constexpr static UnixDateTime from_nanoseconds_since_epoch(i64 nanoseconds) |
498 | 0 | { |
499 | 0 | return UnixDateTime { Duration::from_nanoseconds(nanoseconds) }; |
500 | 0 | } |
501 | | |
502 | | [[nodiscard]] static UnixDateTime from_unix_timespec(struct timespec const& time) |
503 | 0 | { |
504 | 0 | return UnixDateTime { Duration::from_timespec(time) }; |
505 | 0 | } |
506 | | |
507 | | // Earliest and latest representable UNIX timestamps. |
508 | 0 | [[nodiscard]] constexpr static UnixDateTime earliest() { return UnixDateTime { Duration::min() }; } |
509 | 0 | [[nodiscard]] constexpr static UnixDateTime latest() { return UnixDateTime { Duration::max() }; } |
510 | | |
511 | 0 | [[nodiscard]] constexpr Duration offset_to_epoch() const { return m_offset; } |
512 | | // May return an epoch offset *after* what this UnixDateTime contains, because rounding to seconds occurs. |
513 | 0 | [[nodiscard]] constexpr i64 seconds_since_epoch() const { return m_offset.to_seconds(); } |
514 | 0 | [[nodiscard]] constexpr i64 milliseconds_since_epoch() const { return m_offset.to_milliseconds(); } |
515 | 0 | [[nodiscard]] constexpr i64 nanoseconds_since_epoch() const { return m_offset.to_nanoseconds(); } |
516 | | // Never returns a point after this UnixDateTime, since fractional seconds are cut off. |
517 | 0 | [[nodiscard]] i64 truncated_seconds_since_epoch() const { return m_offset.to_truncated_seconds(); } |
518 | 0 | [[nodiscard]] i64 truncated_milliseconds_since_epoch() const { return m_offset.to_truncated_milliseconds(); } |
519 | | |
520 | | // Offsetting a UNIX time by a duration yields another UNIX time. |
521 | 2.63k | constexpr UnixDateTime operator+(Duration const& other) const { return UnixDateTime { m_offset + other }; } |
522 | | constexpr UnixDateTime& operator+=(Duration const& other) |
523 | 0 | { |
524 | 0 | this->m_offset = this->m_offset + other; |
525 | 0 | return *this; |
526 | 0 | } |
527 | | |
528 | 0 | constexpr UnixDateTime operator-(Duration const& other) const { return UnixDateTime { m_offset - other }; } |
529 | | constexpr UnixDateTime& operator-=(Duration const& other) |
530 | 0 | { |
531 | 0 | m_offset = m_offset - other; |
532 | 0 | return *this; |
533 | 0 | } |
534 | | |
535 | | // Subtracting two UNIX times yields their time difference. |
536 | 0 | constexpr Duration operator-(UnixDateTime const& other) const { return m_offset - other.m_offset; } |
537 | | |
538 | | #ifndef KERNEL |
539 | | [[nodiscard]] static UnixDateTime now(); |
540 | | [[nodiscard]] static UnixDateTime now_coarse(); |
541 | | #endif |
542 | | |
543 | | constexpr bool operator==(UnixDateTime const& other) const |
544 | 0 | { |
545 | 0 | return this->m_offset == other.m_offset; |
546 | 0 | } |
547 | 0 | constexpr int operator<=>(UnixDateTime const& other) const { return this->m_offset <=> other.m_offset; } |
548 | | |
549 | | private: |
550 | | constexpr explicit UnixDateTime(Duration offset) |
551 | 5.26k | : Detail::UnawareTime(offset) |
552 | 5.26k | { |
553 | 5.26k | } |
554 | | }; |
555 | | |
556 | | // Monotonic time represents time returned from the CLOCK_MONOTONIC clock, which has an arbitrary fixed reference point. |
557 | | class MonotonicTime : private Detail::UnawareTime { |
558 | | public: |
559 | | // Monotonic time does not have a defined reference point. |
560 | | // A MonotonicTime at the reference point is therefore meaningless. |
561 | | MonotonicTime() = delete; |
562 | | constexpr MonotonicTime(MonotonicTime const&) = default; |
563 | | constexpr MonotonicTime(MonotonicTime&&) = default; |
564 | | constexpr MonotonicTime& operator=(MonotonicTime const&) = default; |
565 | | constexpr MonotonicTime& operator=(MonotonicTime&&) = default; |
566 | | |
567 | | #ifndef KERNEL |
568 | | [[nodiscard]] static MonotonicTime now(); |
569 | | [[nodiscard]] static MonotonicTime now_coarse(); |
570 | | #endif |
571 | | |
572 | 0 | [[nodiscard]] i64 seconds() const { return m_offset.to_seconds(); } |
573 | 0 | [[nodiscard]] i64 milliseconds() const { return m_offset.to_milliseconds(); } |
574 | 0 | [[nodiscard]] i64 nanoseconds() const { return m_offset.to_nanoseconds(); } |
575 | | // Never returns a point in the future, since fractional seconds are cut off. |
576 | 0 | [[nodiscard]] i64 truncated_seconds() const { return m_offset.to_truncated_seconds(); } |
577 | 0 | [[nodiscard]] i64 nanoseconds_within_second() const { return m_offset.nanoseconds_within_second(); } |
578 | | |
579 | 0 | constexpr bool operator==(MonotonicTime const& other) const { return this->m_offset == other.m_offset; } |
580 | 0 | constexpr int operator<=>(MonotonicTime const& other) const { return this->m_offset <=> other.m_offset; } |
581 | | |
582 | 0 | constexpr MonotonicTime operator+(Duration const& other) const { return MonotonicTime { m_offset + other }; } |
583 | | constexpr MonotonicTime& operator+=(Duration const& other) |
584 | 0 | { |
585 | 0 | this->m_offset = this->m_offset + other; |
586 | 0 | return *this; |
587 | 0 | } |
588 | 0 | constexpr MonotonicTime operator-(Duration const& other) const { return MonotonicTime { m_offset - other }; } |
589 | 0 | constexpr Duration operator-(MonotonicTime const& other) const { return m_offset - other.m_offset; } |
590 | | |
591 | | #ifdef KERNEL |
592 | | // Required in the Kernel in order to create monotonic time information from hardware timers. |
593 | | [[nodiscard]] static MonotonicTime from_hardware_time(Badge<Kernel::TimeManagement>, time_t seconds, long nanoseconds) |
594 | | { |
595 | | return MonotonicTime { Duration::from_timespec({ seconds, nanoseconds }) }; |
596 | | } |
597 | | |
598 | | // "Start" is whenever the hardware timers started counting (e.g. for HPET it's most certainly boot). |
599 | | [[nodiscard]] Duration time_since_start(Badge<Kernel::TimeManagement>) |
600 | | { |
601 | | return m_offset; |
602 | | } |
603 | | #endif |
604 | | |
605 | | private: |
606 | | constexpr explicit MonotonicTime(Duration offset) |
607 | 54 | : Detail::UnawareTime(offset) |
608 | 54 | { |
609 | 54 | } |
610 | | }; |
611 | | |
612 | | template<typename TimevalType> |
613 | | inline void timeval_sub(TimevalType const& a, TimevalType const& b, TimevalType& result) |
614 | | { |
615 | | result.tv_sec = a.tv_sec - b.tv_sec; |
616 | | result.tv_usec = a.tv_usec - b.tv_usec; |
617 | | if (result.tv_usec < 0) { |
618 | | --result.tv_sec; |
619 | | result.tv_usec += 1'000'000; |
620 | | } |
621 | | } |
622 | | |
623 | | template<typename TimevalType> |
624 | | inline void timeval_add(TimevalType const& a, TimevalType const& b, TimevalType& result) |
625 | | { |
626 | | result.tv_sec = a.tv_sec + b.tv_sec; |
627 | | result.tv_usec = a.tv_usec + b.tv_usec; |
628 | | if (result.tv_usec >= 1'000'000) { |
629 | | ++result.tv_sec; |
630 | | result.tv_usec -= 1'000'000; |
631 | | } |
632 | | } |
633 | | |
634 | | template<typename TimespecType> |
635 | | inline void timespec_sub(TimespecType const& a, TimespecType const& b, TimespecType& result) |
636 | | { |
637 | | result.tv_sec = a.tv_sec - b.tv_sec; |
638 | | result.tv_nsec = a.tv_nsec - b.tv_nsec; |
639 | | if (result.tv_nsec < 0) { |
640 | | --result.tv_sec; |
641 | | result.tv_nsec += 1'000'000'000; |
642 | | } |
643 | | } |
644 | | |
645 | | template<typename TimespecType> |
646 | | inline void timespec_add(TimespecType const& a, TimespecType const& b, TimespecType& result) |
647 | | { |
648 | | result.tv_sec = a.tv_sec + b.tv_sec; |
649 | | result.tv_nsec = a.tv_nsec + b.tv_nsec; |
650 | | if (result.tv_nsec >= 1000'000'000) { |
651 | | ++result.tv_sec; |
652 | | result.tv_nsec -= 1000'000'000; |
653 | | } |
654 | | } |
655 | | |
656 | | template<typename TimespecType, typename TimevalType> |
657 | | inline void timespec_add_timeval(TimespecType const& a, TimevalType const& b, TimespecType& result) |
658 | | { |
659 | | result.tv_sec = a.tv_sec + b.tv_sec; |
660 | | result.tv_nsec = a.tv_nsec + b.tv_usec * 1000; |
661 | | if (result.tv_nsec >= 1000'000'000) { |
662 | | ++result.tv_sec; |
663 | | result.tv_nsec -= 1000'000'000; |
664 | | } |
665 | | } |
666 | | |
667 | | template<typename TimevalType, typename TimespecType> |
668 | | inline void timeval_to_timespec(TimevalType const& tv, TimespecType& ts) |
669 | | { |
670 | | ts.tv_sec = tv.tv_sec; |
671 | | ts.tv_nsec = tv.tv_usec * 1000; |
672 | | } |
673 | | |
674 | | template<typename TimespecType, typename TimevalType> |
675 | | inline void timespec_to_timeval(TimespecType const& ts, TimevalType& tv) |
676 | | { |
677 | | tv.tv_sec = ts.tv_sec; |
678 | | tv.tv_usec = ts.tv_nsec / 1000; |
679 | | } |
680 | | |
681 | | // To use these, add a ``using namespace AK::TimeLiterals`` at block or file scope |
682 | | namespace TimeLiterals { |
683 | | |
684 | 0 | constexpr Duration operator""_ns(unsigned long long nanoseconds) { return Duration::from_nanoseconds(static_cast<i64>(nanoseconds)); } |
685 | 0 | constexpr Duration operator""_us(unsigned long long microseconds) { return Duration::from_microseconds(static_cast<i64>(microseconds)); } |
686 | 0 | constexpr Duration operator""_ms(unsigned long long milliseconds) { return Duration::from_milliseconds(static_cast<i64>(milliseconds)); } |
687 | 0 | constexpr Duration operator""_sec(unsigned long long seconds) { return Duration::from_seconds(static_cast<i64>(seconds)); } |
688 | | |
689 | | } |
690 | | |
691 | | } |
692 | | |
693 | | #if USING_AK_GLOBALLY |
694 | | using AK::day_of_week; |
695 | | using AK::day_of_year; |
696 | | using AK::days_in_month; |
697 | | using AK::days_in_year; |
698 | | using AK::days_since_epoch; |
699 | | using AK::days_since_epoch_to_date; |
700 | | using AK::Duration; |
701 | | using AK::is_leap_year; |
702 | | using AK::MonotonicTime; |
703 | | using AK::seconds_since_epoch_to_year; |
704 | | using AK::timespec_add; |
705 | | using AK::timespec_add_timeval; |
706 | | using AK::timespec_sub; |
707 | | using AK::timespec_to_timeval; |
708 | | using AK::timeval_add; |
709 | | using AK::timeval_sub; |
710 | | using AK::timeval_to_timespec; |
711 | | using AK::UnixDateTime; |
712 | | using AK::years_to_days_since_epoch; |
713 | | #endif |