1 //===-- Collection of utils for mktime and friends --------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_LIBC_SRC_TIME_TIME_UTILS_H
10 #define LLVM_LIBC_SRC_TIME_TIME_UTILS_H
11 
12 #include "include/errno.h"
13 
14 #include "src/errno/llvmlibc_errno.h"
15 #include "src/time/mktime.h"
16 
17 #include <stdint.h>
18 
19 namespace __llvm_libc {
20 namespace time_utils {
21 
22 struct TimeConstants {
23   static constexpr int SecondsPerMin = 60;
24   static constexpr int SecondsPerHour = 3600;
25   static constexpr int SecondsPerDay = 86400;
26   static constexpr int DaysPerWeek = 7;
27   static constexpr int MonthsPerYear = 12;
28   static constexpr int DaysPerNonLeapYear = 365;
29   static constexpr int DaysPerLeapYear = 366;
30   static constexpr int TimeYearBase = 1900;
31   static constexpr int EpochYear = 1970;
32   static constexpr int EpochWeekDay = 4;
33   static constexpr int NumberOfSecondsInLeapYear =
34       (DaysPerNonLeapYear + 1) * SecondsPerDay;
35 
36   /* 2000-03-01 (mod 400 year, immediately after feb29 */
37   static constexpr int64_t SecondsUntil2000MarchFirst =
38       (946684800LL + SecondsPerDay * (31 + 29));
39   static constexpr int WeekDayOf2000MarchFirst = 3;
40 
41   static constexpr int DaysPer400Years =
42       (DaysPerNonLeapYear * 400 + (400 / 4) - 3);
43   static constexpr int DaysPer100Years =
44       (DaysPerNonLeapYear * 100 + (100 / 4) - 1);
45   static constexpr int DaysPer4Years = (DaysPerNonLeapYear * 4 + 1);
46 
47   // The latest time that can be represented in this form is 03:14:07 UTC on
48   // Tuesday, 19 January 2038 (corresponding to 2,147,483,647 seconds since the
49   // start of the epoch). This means that systems using a 32-bit time_t type are
50   // susceptible to the Year 2038 problem.
51   static constexpr int EndOf32BitEpochYear = 2038;
52 
53   static constexpr time_t OutOfRangeReturnValue = -1;
54 };
55 
56 // Update the "tm" structure's year, month, etc. members from seconds.
57 // "total_seconds" is the number of seconds since January 1st, 1970.
58 extern int64_t UpdateFromSeconds(int64_t total_seconds, struct tm *tm);
59 
60 // POSIX.1-2017 requires this.
61 static inline time_t OutOfRange() {
62   llvmlibc_errno = EOVERFLOW;
63   return static_cast<time_t>(-1);
64 }
65 
66 static inline struct tm *gmtime_internal(const time_t *timer,
67                                          struct tm *result) {
68   int64_t seconds = *timer;
69   // Update the tm structure's year, month, day, etc. from seconds.
70   if (UpdateFromSeconds(seconds, result) < 0) {
71     OutOfRange();
72     return nullptr;
73   }
74 
75   return result;
76 }
77 
78 } // namespace time_utils
79 } // namespace __llvm_libc
80 
81 #endif // LLVM_LIBC_SRC_TIME_TIME_UTILS_H
82