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