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