Time.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Array.h>
  7. #include <AK/Checked.h>
  8. #include <AK/Time.h>
  9. // Make a reasonable guess as to which timespec/timeval definition to use.
  10. // It doesn't really matter, since both are identical.
  11. #ifdef KERNEL
  12. # include <Kernel/UnixTypes.h>
  13. #else
  14. # include <sys/time.h>
  15. # include <time.h>
  16. #endif
  17. namespace AK {
  18. int day_of_year(int year, unsigned month, int day)
  19. {
  20. VERIFY(month >= 1 && month <= 12);
  21. constexpr Array seek_table = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
  22. int day_of_year = seek_table[month - 1] + day - 1;
  23. if (is_leap_year(year) && month >= 3)
  24. day_of_year++;
  25. return day_of_year;
  26. }
  27. int days_in_month(int year, unsigned month)
  28. {
  29. VERIFY(month >= 1 && month <= 12);
  30. if (month == 2)
  31. return is_leap_year(year) ? 29 : 28;
  32. bool is_long_month = (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12);
  33. return is_long_month ? 31 : 30;
  34. }
  35. unsigned day_of_week(int year, unsigned month, int day)
  36. {
  37. VERIFY(month >= 1 && month <= 12);
  38. constexpr Array seek_table = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
  39. if (month < 3)
  40. --year;
  41. return (year + year / 4 - year / 100 + year / 400 + seek_table[month - 1] + day) % 7;
  42. }
  43. Time Time::from_timespec(const struct timespec& ts)
  44. {
  45. i32 nsecs = ts.tv_nsec;
  46. i32 extra_secs = sane_mod(nsecs, 1'000'000'000);
  47. return Time::from_half_sanitized(ts.tv_sec, extra_secs, nsecs);
  48. }
  49. Time Time::from_timeval(const struct timeval& tv)
  50. {
  51. i32 usecs = tv.tv_usec;
  52. i32 extra_secs = sane_mod(usecs, 1'000'000);
  53. VERIFY(0 <= usecs && usecs < 1'000'000);
  54. return Time::from_half_sanitized(tv.tv_sec, extra_secs, usecs * 1'000);
  55. }
  56. i64 Time::to_truncated_seconds() const
  57. {
  58. VERIFY(m_nanoseconds < 1'000'000'000);
  59. if (m_seconds < 0 && m_nanoseconds) {
  60. // Since m_seconds is negative, adding 1 can't possibly overflow
  61. return m_seconds + 1;
  62. }
  63. return m_seconds;
  64. }
  65. i64 Time::to_truncated_milliseconds() const
  66. {
  67. VERIFY(m_nanoseconds < 1'000'000'000);
  68. Checked<i64> milliseconds((m_seconds < 0) ? m_seconds + 1 : m_seconds);
  69. milliseconds *= 1'000;
  70. milliseconds += m_nanoseconds / 1'000'000;
  71. if (m_seconds < 0) {
  72. if (m_nanoseconds % 1'000'000 != 0) {
  73. // Does not overflow: milliseconds <= 1'999.
  74. milliseconds++;
  75. }
  76. // We dropped one second previously, put it back in now that we have handled the rounding.
  77. milliseconds -= 1'000;
  78. }
  79. if (!milliseconds.has_overflow())
  80. return milliseconds.value();
  81. return m_seconds < 0 ? -0x8000'0000'0000'0000LL : 0x7fff'ffff'ffff'ffffLL;
  82. }
  83. i64 Time::to_truncated_microseconds() const
  84. {
  85. VERIFY(m_nanoseconds < 1'000'000'000);
  86. Checked<i64> microseconds((m_seconds < 0) ? m_seconds + 1 : m_seconds);
  87. microseconds *= 1'000'000;
  88. microseconds += m_nanoseconds / 1'000;
  89. if (m_seconds < 0) {
  90. if (m_nanoseconds % 1'000 != 0) {
  91. // Does not overflow: microseconds <= 1'999'999.
  92. microseconds++;
  93. }
  94. // We dropped one second previously, put it back in now that we have handled the rounding.
  95. microseconds -= 1'000'000;
  96. }
  97. if (!microseconds.has_overflow())
  98. return microseconds.value();
  99. return m_seconds < 0 ? -0x8000'0000'0000'0000LL : 0x7fff'ffff'ffff'ffffLL;
  100. }
  101. i64 Time::to_seconds() const
  102. {
  103. VERIFY(m_nanoseconds < 1'000'000'000);
  104. if (m_seconds >= 0 && m_nanoseconds) {
  105. Checked<i64> seconds(m_seconds);
  106. seconds++;
  107. return seconds.has_overflow() ? 0x7fff'ffff'ffff'ffffLL : seconds.value();
  108. }
  109. return m_seconds;
  110. }
  111. i64 Time::to_milliseconds() const
  112. {
  113. VERIFY(m_nanoseconds < 1'000'000'000);
  114. Checked<i64> milliseconds((m_seconds < 0) ? m_seconds + 1 : m_seconds);
  115. milliseconds *= 1'000;
  116. milliseconds += m_nanoseconds / 1'000'000;
  117. if (m_seconds >= 0 && m_nanoseconds % 1'000'000 != 0)
  118. milliseconds++;
  119. if (m_seconds < 0) {
  120. // We dropped one second previously, put it back in now that we have handled the rounding.
  121. milliseconds -= 1'000;
  122. }
  123. if (!milliseconds.has_overflow())
  124. return milliseconds.value();
  125. return m_seconds < 0 ? -0x8000'0000'0000'0000LL : 0x7fff'ffff'ffff'ffffLL;
  126. }
  127. i64 Time::to_microseconds() const
  128. {
  129. VERIFY(m_nanoseconds < 1'000'000'000);
  130. Checked<i64> microseconds((m_seconds < 0) ? m_seconds + 1 : m_seconds);
  131. microseconds *= 1'000'000;
  132. microseconds += m_nanoseconds / 1'000;
  133. if (m_seconds >= 0 && m_nanoseconds % 1'000 != 0)
  134. microseconds++;
  135. if (m_seconds < 0) {
  136. // We dropped one second previously, put it back in now that we have handled the rounding.
  137. microseconds -= 1'000'000;
  138. }
  139. if (!microseconds.has_overflow())
  140. return microseconds.value();
  141. return m_seconds < 0 ? -0x8000'0000'0000'0000LL : 0x7fff'ffff'ffff'ffffLL;
  142. }
  143. i64 Time::to_nanoseconds() const
  144. {
  145. VERIFY(m_nanoseconds < 1'000'000'000);
  146. Checked<i64> nanoseconds((m_seconds < 0) ? m_seconds + 1 : m_seconds);
  147. nanoseconds *= 1'000'000'000;
  148. nanoseconds += m_nanoseconds;
  149. if (m_seconds < 0) {
  150. // We dropped one second previously, put it back in now that we have handled the rounding.
  151. nanoseconds -= 1'000'000'000;
  152. }
  153. if (!nanoseconds.has_overflow())
  154. return nanoseconds.value();
  155. return m_seconds < 0 ? -0x8000'0000'0000'0000LL : 0x7fff'ffff'ffff'ffffLL;
  156. }
  157. timespec Time::to_timespec() const
  158. {
  159. VERIFY(m_nanoseconds < 1'000'000'000);
  160. return { static_cast<time_t>(m_seconds), static_cast<long>(m_nanoseconds) };
  161. }
  162. timeval Time::to_timeval() const
  163. {
  164. VERIFY(m_nanoseconds < 1'000'000'000);
  165. return { static_cast<time_t>(m_seconds), static_cast<suseconds_t>(m_nanoseconds) / 1000 };
  166. }
  167. Time Time::operator+(const Time& other) const
  168. {
  169. VERIFY(m_nanoseconds < 1'000'000'000);
  170. VERIFY(other.m_nanoseconds < 1'000'000'000);
  171. u32 new_nsecs = m_nanoseconds + other.m_nanoseconds;
  172. u32 extra_secs = new_nsecs / 1'000'000'000;
  173. new_nsecs %= 1'000'000'000;
  174. i64 this_secs = m_seconds;
  175. i64 other_secs = other.m_seconds;
  176. // We would like to just add "this_secs + other_secs + extra_secs".
  177. // However, computing this naively may overflow even though the result is in-bounds.
  178. // Example in 8-bit: (-127) + (-2) + (+1) = (-128), which fits in an i8.
  179. // Example in 8-bit, the other way around: (-2) + (127) + (+1) = 126.
  180. // So we do something more sophisticated:
  181. if (extra_secs) {
  182. VERIFY(extra_secs == 1);
  183. if (this_secs != 0x7fff'ffff'ffff'ffff) {
  184. this_secs += 1;
  185. } else if (other_secs != 0x7fff'ffff'ffff'ffff) {
  186. other_secs += 1;
  187. } else {
  188. /* If *both* are INT64_MAX, then adding them will overflow in any case. */
  189. return Time::max();
  190. }
  191. }
  192. Checked<i64> new_secs { this_secs };
  193. new_secs += other_secs;
  194. if (new_secs.has_overflow()) {
  195. if (other_secs > 0)
  196. return Time::max();
  197. else
  198. return Time::min();
  199. }
  200. return Time { new_secs.value(), new_nsecs };
  201. }
  202. Time& Time::operator+=(const Time& other)
  203. {
  204. *this = *this + other;
  205. return *this;
  206. }
  207. Time Time::operator-(const Time& other) const
  208. {
  209. VERIFY(m_nanoseconds < 1'000'000'000);
  210. VERIFY(other.m_nanoseconds < 1'000'000'000);
  211. if (other.m_nanoseconds)
  212. return *this + Time((i64) ~(u64)other.m_seconds, 1'000'000'000 - other.m_nanoseconds);
  213. if (other.m_seconds != (i64)-0x8000'0000'0000'0000)
  214. return *this + Time(-other.m_seconds, 0);
  215. // Only remaining case: We want to subtract -0x8000'0000'0000'0000 seconds,
  216. // i.e. add a very large number.
  217. if (m_seconds >= 0)
  218. return Time::max();
  219. return Time { (m_seconds + 0x4000'0000'0000'0000) + 0x4000'0000'0000'0000, m_nanoseconds };
  220. }
  221. Time& Time::operator-=(const Time& other)
  222. {
  223. *this = *this - other;
  224. return *this;
  225. }
  226. bool Time::operator<(const Time& other) const
  227. {
  228. return m_seconds < other.m_seconds || (m_seconds == other.m_seconds && m_nanoseconds < other.m_nanoseconds);
  229. }
  230. bool Time::operator<=(const Time& other) const
  231. {
  232. return m_seconds < other.m_seconds || (m_seconds == other.m_seconds && m_nanoseconds <= other.m_nanoseconds);
  233. }
  234. bool Time::operator>(const Time& other) const
  235. {
  236. return m_seconds > other.m_seconds || (m_seconds == other.m_seconds && m_nanoseconds > other.m_nanoseconds);
  237. }
  238. bool Time::operator>=(const Time& other) const
  239. {
  240. return m_seconds > other.m_seconds || (m_seconds == other.m_seconds && m_nanoseconds >= other.m_nanoseconds);
  241. }
  242. Time Time::from_half_sanitized(i64 seconds, i32 extra_seconds, u32 nanoseconds)
  243. {
  244. VERIFY(nanoseconds < 1'000'000'000);
  245. if ((seconds <= 0 && extra_seconds > 0) || (seconds >= 0 && extra_seconds < 0)) {
  246. // Opposite signs mean that we can definitely add them together without fear of overflowing i64:
  247. seconds += extra_seconds;
  248. extra_seconds = 0;
  249. }
  250. // Now the only possible way to become invalid is overflowing i64 towards positive infinity:
  251. if (Checked<i64>::addition_would_overflow<i64, i64>(seconds, extra_seconds)) {
  252. if (seconds < 0) {
  253. return Time::min();
  254. } else {
  255. return Time::max();
  256. }
  257. }
  258. return Time { seconds + extra_seconds, nanoseconds };
  259. }
  260. #ifndef KERNEL
  261. namespace {
  262. static Time now_time_from_clock(clockid_t clock_id)
  263. {
  264. timespec now_spec {};
  265. ::clock_gettime(clock_id, &now_spec);
  266. return Time::from_timespec(now_spec);
  267. }
  268. }
  269. Time Time::now_realtime()
  270. {
  271. return now_time_from_clock(CLOCK_REALTIME);
  272. }
  273. Time Time::now_realtime_coarse()
  274. {
  275. return now_time_from_clock(CLOCK_REALTIME_COARSE);
  276. }
  277. Time Time::now_monotonic()
  278. {
  279. return now_time_from_clock(CLOCK_MONOTONIC);
  280. }
  281. Time Time::now_monotonic_coarse()
  282. {
  283. return now_time_from_clock(CLOCK_MONOTONIC_COARSE);
  284. }
  285. #endif
  286. }