summaryrefslogtreecommitdiff
path: root/libc/src/time
diff options
context:
space:
mode:
Diffstat (limited to 'libc/src/time')
-rw-r--r--libc/src/time/CMakeLists.txt30
-rw-r--r--libc/src/time/asctime.cpp8
-rw-r--r--libc/src/time/asctime.h2
-rw-r--r--libc/src/time/asctime_r.cpp6
-rw-r--r--libc/src/time/asctime_r.h2
-rw-r--r--libc/src/time/ctime.cpp11
-rw-r--r--libc/src/time/ctime_r.cpp9
-rw-r--r--libc/src/time/difftime.h2
-rw-r--r--libc/src/time/gmtime.h3
-rw-r--r--libc/src/time/gmtime_r.h3
-rw-r--r--libc/src/time/gpu/clock.cpp2
-rw-r--r--libc/src/time/gpu/nanosleep.cpp1
-rw-r--r--libc/src/time/mktime.cpp37
-rw-r--r--libc/src/time/mktime.h3
-rw-r--r--libc/src/time/time.cpp3
-rw-r--r--libc/src/time/time_constants.h100
-rw-r--r--libc/src/time/time_utils.cpp53
-rw-r--r--libc/src/time/time_utils.h93
18 files changed, 215 insertions, 153 deletions
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index ae835dcc7427..ef9bfe57bc4e 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -2,6 +2,17 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
endif()
+add_header_library(
+ time_constants
+ HDRS
+ time_constants.h
+ DEPENDS
+ libc.include.time
+ libc.src.__support.CPP.array
+ libc.src.__support.CPP.string_view
+ libc.hdr.types.time_t
+)
+
add_object_library(
time_utils
SRCS
@@ -12,6 +23,10 @@ add_object_library(
libc.include.time
libc.src.__support.CPP.limits
libc.src.errno.errno
+ .time_constants
+ libc.hdr.types.time_t
+ libc.hdr.types.size_t
+ libc.hdr.types.struct_tm
)
add_entrypoint_object(
@@ -22,7 +37,9 @@ add_entrypoint_object(
asctime.h
DEPENDS
.time_utils
+ .time_constants
libc.include.time
+ libc.hdr.types.struct_tm
)
add_entrypoint_object(
@@ -33,7 +50,9 @@ add_entrypoint_object(
asctime_r.h
DEPENDS
.time_utils
+ .time_constants
libc.include.time
+ libc.hdr.types.struct_tm
)
add_entrypoint_object(
@@ -44,6 +63,7 @@ add_entrypoint_object(
ctime.h
DEPENDS
.time_utils
+ .time_constants
libc.hdr.types.time_t
libc.include.time
)
@@ -56,6 +76,7 @@ add_entrypoint_object(
ctime_r.h
DEPENDS
.time_utils
+ .time_constants
libc.hdr.types.time_t
libc.include.time
)
@@ -68,6 +89,7 @@ add_entrypoint_object(
difftime.h
DEPENDS
libc.include.time
+ libc.hdr.types.time_t
)
add_entrypoint_object(
@@ -79,6 +101,8 @@ add_entrypoint_object(
DEPENDS
.time_utils
libc.include.time
+ libc.hdr.types.time_t
+ libc.hdr.types.struct_tm
)
add_entrypoint_object(
@@ -90,6 +114,8 @@ add_entrypoint_object(
DEPENDS
.time_utils
libc.include.time
+ libc.hdr.types.time_t
+ libc.hdr.types.struct_tm
)
add_entrypoint_object(
@@ -100,8 +126,11 @@ add_entrypoint_object(
mktime.h
DEPENDS
.time_utils
+ .time_constants
libc.include.time
libc.src.errno.errno
+ libc.hdr.types.time_t
+ libc.hdr.types.struct_tm
)
add_entrypoint_object(
@@ -115,6 +144,7 @@ add_entrypoint_object(
libc.hdr.types.time_t
libc.src.__support.time.clock_gettime
libc.src.errno.errno
+ libc.hdr.types.struct_tm
)
add_entrypoint_object(
diff --git a/libc/src/time/asctime.cpp b/libc/src/time/asctime.cpp
index d6fbe7316ced..2b00c4136f90 100644
--- a/libc/src/time/asctime.cpp
+++ b/libc/src/time/asctime.cpp
@@ -9,15 +9,15 @@
#include "src/time/asctime.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
+#include "src/time/time_constants.h"
#include "src/time/time_utils.h"
namespace LIBC_NAMESPACE_DECL {
-using LIBC_NAMESPACE::time_utils::TimeConstants;
-
LLVM_LIBC_FUNCTION(char *, asctime, (const struct tm *timeptr)) {
- static char buffer[TimeConstants::ASCTIME_BUFFER_SIZE];
- return time_utils::asctime(timeptr, buffer, TimeConstants::ASCTIME_MAX_BYTES);
+ static char buffer[time_constants::ASCTIME_BUFFER_SIZE];
+ return time_utils::asctime(timeptr, buffer,
+ time_constants::ASCTIME_MAX_BYTES);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/asctime.h b/libc/src/time/asctime.h
index 623e6dff60c3..37325e75b829 100644
--- a/libc/src/time/asctime.h
+++ b/libc/src/time/asctime.h
@@ -9,8 +9,8 @@
#ifndef LLVM_LIBC_SRC_TIME_ASCTIME_H
#define LLVM_LIBC_SRC_TIME_ASCTIME_H
+#include "hdr/types/struct_tm.h"
#include "src/__support/macros/config.h"
-#include <time.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/time/asctime_r.cpp b/libc/src/time/asctime_r.cpp
index caa22f1cd778..bf53bfdf2f8c 100644
--- a/libc/src/time/asctime_r.cpp
+++ b/libc/src/time/asctime_r.cpp
@@ -9,15 +9,15 @@
#include "src/time/asctime_r.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
+#include "src/time/time_constants.h"
#include "src/time/time_utils.h"
namespace LIBC_NAMESPACE_DECL {
-using LIBC_NAMESPACE::time_utils::TimeConstants;
-
LLVM_LIBC_FUNCTION(char *, asctime_r,
(const struct tm *timeptr, char *buffer)) {
- return time_utils::asctime(timeptr, buffer, TimeConstants::ASCTIME_MAX_BYTES);
+ return time_utils::asctime(timeptr, buffer,
+ time_constants::ASCTIME_MAX_BYTES);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/asctime_r.h b/libc/src/time/asctime_r.h
index 328b7dff19c2..65a6b84ca38f 100644
--- a/libc/src/time/asctime_r.h
+++ b/libc/src/time/asctime_r.h
@@ -9,8 +9,8 @@
#ifndef LLVM_LIBC_SRC_TIME_ASCTIME_R_H
#define LLVM_LIBC_SRC_TIME_ASCTIME_R_H
+#include "hdr/types/struct_tm.h"
#include "src/__support/macros/config.h"
-#include <time.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/time/ctime.cpp b/libc/src/time/ctime.cpp
index 8adae9be7380..ac0ffe5b32ae 100644
--- a/libc/src/time/ctime.cpp
+++ b/libc/src/time/ctime.cpp
@@ -6,23 +6,22 @@
//
//===----------------------------------------------------------------------===//
-#include "ctime.h"
+#include "src/time/ctime.h"
#include "src/__support/CPP/limits.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
-#include "time_utils.h"
+#include "src/time/time_constants.h"
+#include "src/time/time_utils.h"
namespace LIBC_NAMESPACE_DECL {
-using LIBC_NAMESPACE::time_utils::TimeConstants;
-
LLVM_LIBC_FUNCTION(char *, ctime, (const time_t *t_ptr)) {
if (t_ptr == nullptr || *t_ptr > cpp::numeric_limits<int32_t>::max()) {
return nullptr;
}
- static char buffer[TimeConstants::ASCTIME_BUFFER_SIZE];
+ static char buffer[time_constants::ASCTIME_BUFFER_SIZE];
return time_utils::asctime(time_utils::localtime(t_ptr), buffer,
- TimeConstants::ASCTIME_MAX_BYTES);
+ time_constants::ASCTIME_MAX_BYTES);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/ctime_r.cpp b/libc/src/time/ctime_r.cpp
index 63d93c4085f3..7224f7742f13 100644
--- a/libc/src/time/ctime_r.cpp
+++ b/libc/src/time/ctime_r.cpp
@@ -6,16 +6,15 @@
//
//===----------------------------------------------------------------------===//
-#include "ctime_r.h"
+#include "src/time/ctime_r.h"
#include "src/__support/CPP/limits.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
-#include "time_utils.h"
+#include "src/time/time_constants.h"
+#include "src/time/time_utils.h"
namespace LIBC_NAMESPACE_DECL {
-using LIBC_NAMESPACE::time_utils::TimeConstants;
-
LLVM_LIBC_FUNCTION(char *, ctime_r, (const time_t *t_ptr, char *buffer)) {
if (t_ptr == nullptr || buffer == nullptr ||
*t_ptr > cpp::numeric_limits<int32_t>::max()) {
@@ -23,7 +22,7 @@ LLVM_LIBC_FUNCTION(char *, ctime_r, (const time_t *t_ptr, char *buffer)) {
}
return time_utils::asctime(time_utils::localtime(t_ptr), buffer,
- TimeConstants::ASCTIME_MAX_BYTES);
+ time_constants::ASCTIME_MAX_BYTES);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/difftime.h b/libc/src/time/difftime.h
index d5cd593cc533..12de5678864c 100644
--- a/libc/src/time/difftime.h
+++ b/libc/src/time/difftime.h
@@ -9,8 +9,8 @@
#ifndef LLVM_LIBC_SRC_TIME_DIFFTIME_H
#define LLVM_LIBC_SRC_TIME_DIFFTIME_H
+#include "hdr/types/time_t.h"
#include "src/__support/macros/config.h"
-#include <time.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/time/gmtime.h b/libc/src/time/gmtime.h
index 3de3cebbfde2..ac7f1be7bbce 100644
--- a/libc/src/time/gmtime.h
+++ b/libc/src/time/gmtime.h
@@ -9,8 +9,9 @@
#ifndef LLVM_LIBC_SRC_TIME_GMTIME_H
#define LLVM_LIBC_SRC_TIME_GMTIME_H
+#include "hdr/types/struct_tm.h"
+#include "hdr/types/time_t.h"
#include "src/__support/macros/config.h"
-#include <time.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/time/gmtime_r.h b/libc/src/time/gmtime_r.h
index b4f387ef443b..4c88b22faf4c 100644
--- a/libc/src/time/gmtime_r.h
+++ b/libc/src/time/gmtime_r.h
@@ -9,8 +9,9 @@
#ifndef LLVM_LIBC_SRC_TIME_GMTIME_R_H
#define LLVM_LIBC_SRC_TIME_GMTIME_R_H
+#include "hdr/types/struct_tm.h"
+#include "hdr/types/time_t.h"
#include "src/__support/macros/config.h"
-#include <time.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/time/gpu/clock.cpp b/libc/src/time/gpu/clock.cpp
index add5b2725ef8..8609c5cd6b6b 100644
--- a/libc/src/time/gpu/clock.cpp
+++ b/libc/src/time/gpu/clock.cpp
@@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
#include "src/time/clock.h"
+
+#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/time/gpu/time_utils.h"
diff --git a/libc/src/time/gpu/nanosleep.cpp b/libc/src/time/gpu/nanosleep.cpp
index a92f660f225c..d22d9d6bd8d7 100644
--- a/libc/src/time/gpu/nanosleep.cpp
+++ b/libc/src/time/gpu/nanosleep.cpp
@@ -8,6 +8,7 @@
#include "src/time/nanosleep.h"
+#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/time/gpu/time_utils.h"
diff --git a/libc/src/time/mktime.cpp b/libc/src/time/mktime.cpp
index 72cd22912053..3874cad02fac 100644
--- a/libc/src/time/mktime.cpp
+++ b/libc/src/time/mktime.cpp
@@ -9,15 +9,11 @@
#include "src/time/mktime.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
+#include "src/time/time_constants.h"
#include "src/time/time_utils.h"
namespace LIBC_NAMESPACE_DECL {
-using LIBC_NAMESPACE::time_utils::TimeConstants;
-
-static constexpr int NON_LEAP_YEAR_DAYS_IN_MONTH[] = {31, 28, 31, 30, 31, 30,
- 31, 31, 30, 31, 30, 31};
-
// Returns number of years from (1, year).
static constexpr int64_t get_num_of_leap_years_before(int64_t year) {
return (year / 4) - (year / 100) + (year / 400);
@@ -31,12 +27,12 @@ static constexpr bool is_leap_year(const int64_t year) {
LLVM_LIBC_FUNCTION(time_t, mktime, (struct tm * tm_out)) {
// Unlike most C Library functions, mktime doesn't just die on bad input.
// TODO(rtenneti); Handle leap seconds.
- int64_t tm_year_from_base = tm_out->tm_year + TimeConstants::TIME_YEAR_BASE;
+ int64_t tm_year_from_base = tm_out->tm_year + time_constants::TIME_YEAR_BASE;
// 32-bit end-of-the-world is 03:14:07 UTC on 19 January 2038.
if (sizeof(time_t) == 4 &&
- tm_year_from_base >= TimeConstants::END_OF32_BIT_EPOCH_YEAR) {
- if (tm_year_from_base > TimeConstants::END_OF32_BIT_EPOCH_YEAR)
+ tm_year_from_base >= time_constants::END_OF32_BIT_EPOCH_YEAR) {
+ if (tm_year_from_base > time_constants::END_OF32_BIT_EPOCH_YEAR)
return time_utils::out_of_range();
if (tm_out->tm_mon > 0)
return time_utils::out_of_range();
@@ -64,7 +60,7 @@ LLVM_LIBC_FUNCTION(time_t, mktime, (struct tm * tm_out)) {
// Calculate number of months and years from tm_mon.
int64_t month = tm_out->tm_mon;
- if (month < 0 || month >= TimeConstants::MONTHS_PER_YEAR - 1) {
+ if (month < 0 || month >= time_constants::MONTHS_PER_YEAR - 1) {
int64_t years = month / 12;
month %= 12;
if (month < 0) {
@@ -78,23 +74,23 @@ LLVM_LIBC_FUNCTION(time_t, mktime, (struct tm * tm_out)) {
// Calculate total number of days based on the month and the day (tm_mday).
int64_t total_days = tm_out->tm_mday - 1;
for (int64_t i = 0; i < month; ++i)
- total_days += NON_LEAP_YEAR_DAYS_IN_MONTH[i];
+ total_days += time_constants::NON_LEAP_YEAR_DAYS_IN_MONTH[i];
// Add one day if it is a leap year and the month is after February.
if (tm_year_is_leap && month > 1)
total_days++;
// Calculate total numbers of days based on the year.
- total_days += (tm_year_from_base - TimeConstants::EPOCH_YEAR) *
- TimeConstants::DAYS_PER_NON_LEAP_YEAR;
- if (tm_year_from_base >= TimeConstants::EPOCH_YEAR) {
+ total_days += (tm_year_from_base - time_constants::EPOCH_YEAR) *
+ time_constants::DAYS_PER_NON_LEAP_YEAR;
+ if (tm_year_from_base >= time_constants::EPOCH_YEAR) {
total_days += get_num_of_leap_years_before(tm_year_from_base - 1) -
- get_num_of_leap_years_before(TimeConstants::EPOCH_YEAR);
+ get_num_of_leap_years_before(time_constants::EPOCH_YEAR);
} else if (tm_year_from_base >= 1) {
- total_days -= get_num_of_leap_years_before(TimeConstants::EPOCH_YEAR) -
+ total_days -= get_num_of_leap_years_before(time_constants::EPOCH_YEAR) -
get_num_of_leap_years_before(tm_year_from_base - 1);
} else {
// Calculate number of leap years until 0th year.
- total_days -= get_num_of_leap_years_before(TimeConstants::EPOCH_YEAR) -
+ total_days -= get_num_of_leap_years_before(time_constants::EPOCH_YEAR) -
get_num_of_leap_years_before(0);
if (tm_year_from_base <= 0) {
total_days -= 1; // Subtract 1 for 0th year.
@@ -106,11 +102,12 @@ LLVM_LIBC_FUNCTION(time_t, mktime, (struct tm * tm_out)) {
}
}
- // TODO(rtenneti): Need to handle timezone and update of tm_isdst.
+ // TODO: https://github.com/llvm/llvm-project/issues/121962
+ // Need to handle timezone and update of tm_isdst.
int64_t seconds = tm_out->tm_sec +
- tm_out->tm_min * TimeConstants::SECONDS_PER_MIN +
- tm_out->tm_hour * TimeConstants::SECONDS_PER_HOUR +
- total_days * TimeConstants::SECONDS_PER_DAY;
+ tm_out->tm_min * time_constants::SECONDS_PER_MIN +
+ tm_out->tm_hour * time_constants::SECONDS_PER_HOUR +
+ total_days * time_constants::SECONDS_PER_DAY;
// Update the tm structure's year, month, day, etc. from seconds.
if (time_utils::update_from_seconds(seconds, tm_out) < 0)
diff --git a/libc/src/time/mktime.h b/libc/src/time/mktime.h
index 2b4c67996555..985c6293f9d5 100644
--- a/libc/src/time/mktime.h
+++ b/libc/src/time/mktime.h
@@ -9,8 +9,9 @@
#ifndef LLVM_LIBC_SRC_TIME_MKTIME_H
#define LLVM_LIBC_SRC_TIME_MKTIME_H
+#include "hdr/types/struct_tm.h"
+#include "hdr/types/time_t.h"
#include "src/__support/macros/config.h"
-#include <time.h>
namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/time/time.cpp b/libc/src/time/time.cpp
index 4a0b614a68ef..860909af7488 100644
--- a/libc/src/time/time.cpp
+++ b/libc/src/time/time.cpp
@@ -6,12 +6,13 @@
//
//===----------------------------------------------------------------------===//
+#include "src/time/time_func.h"
+
#include "hdr/time_macros.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/time/clock_gettime.h"
#include "src/errno/libc_errno.h"
-#include "src/time/time_func.h"
namespace LIBC_NAMESPACE_DECL {
// avoid inconsitent clang-format behavior
diff --git a/libc/src/time/time_constants.h b/libc/src/time/time_constants.h
new file mode 100644
index 000000000000..3e25f741745a
--- /dev/null
+++ b/libc/src/time/time_constants.h
@@ -0,0 +1,100 @@
+//===-- Collection of constants for time functions --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_TIME_TIME_CONSTANTS_H
+#define LLVM_LIBC_SRC_TIME_TIME_CONSTANTS_H
+
+#include "hdr/types/time_t.h"
+#include "src/__support/CPP/array.h"
+#include "src/__support/CPP/string_view.h"
+#include <stdint.h>
+
+namespace LIBC_NAMESPACE_DECL {
+namespace time_constants {
+
+enum Month : int {
+ JANUARY,
+ FEBRUARY,
+ MARCH,
+ APRIL,
+ MAY,
+ JUNE,
+ JULY,
+ AUGUST,
+ SEPTEMBER,
+ OCTOBER,
+ NOVEMBER,
+ DECEMBER
+};
+
+constexpr int SECONDS_PER_MIN = 60;
+constexpr int MINUTES_PER_HOUR = 60;
+constexpr int HOURS_PER_DAY = 24;
+constexpr int DAYS_PER_WEEK = 7;
+constexpr int MONTHS_PER_YEAR = 12;
+constexpr int DAYS_PER_NON_LEAP_YEAR = 365;
+constexpr int DAYS_PER_LEAP_YEAR = 366;
+
+constexpr int SECONDS_PER_HOUR = SECONDS_PER_MIN * MINUTES_PER_HOUR;
+constexpr int SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY;
+constexpr int NUMBER_OF_SECONDS_IN_LEAP_YEAR =
+ DAYS_PER_LEAP_YEAR * SECONDS_PER_DAY;
+
+constexpr int TIME_YEAR_BASE = 1900;
+constexpr int EPOCH_YEAR = 1970;
+constexpr int EPOCH_WEEK_DAY = 4;
+
+// For asctime the behavior is undefined if struct tm's tm_wday or tm_mon are
+// not within the normal ranges as defined in <time.h>, or if struct tm's
+// tm_year exceeds {INT_MAX}-1990, or if the below asctime_internal algorithm
+// would attempt to generate more than 26 bytes of output (including the
+// terminating null).
+constexpr int ASCTIME_BUFFER_SIZE = 256;
+constexpr int ASCTIME_MAX_BYTES = 26;
+
+/* 2000-03-01 (mod 400 year, immediately after feb29 */
+constexpr int64_t SECONDS_UNTIL2000_MARCH_FIRST =
+ (946684800LL + SECONDS_PER_DAY * (31 + 29));
+constexpr int WEEK_DAY_OF2000_MARCH_FIRST = 3;
+
+constexpr int DAYS_PER400_YEARS =
+ (DAYS_PER_NON_LEAP_YEAR * 400) + (400 / 4) - 3;
+constexpr int DAYS_PER100_YEARS =
+ (DAYS_PER_NON_LEAP_YEAR * 100) + (100 / 4) - 1;
+constexpr int DAYS_PER4_YEARS = (DAYS_PER_NON_LEAP_YEAR * 4) + 1;
+
+// The latest time that can be represented in this form is 03:14:07 UTC on
+// Tuesday, 19 January 2038 (corresponding to 2,147,483,647 seconds since the
+// start of the epoch). This means that systems using a 32-bit time_t type are
+// susceptible to the Year 2038 problem.
+constexpr int END_OF32_BIT_EPOCH_YEAR = 2038;
+
+constexpr time_t OUT_OF_RANGE_RETURN_VALUE = -1;
+
+constexpr cpp::array<cpp::string_view, DAYS_PER_WEEK> WEEK_DAY_NAMES = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+
+constexpr cpp::array<cpp::string_view, DAYS_PER_WEEK> WEEK_DAY_FULL_NAMES = {
+ "Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday"};
+
+constexpr cpp::array<cpp::string_view, MONTHS_PER_YEAR> MONTH_NAMES = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+constexpr cpp::array<cpp::string_view, MONTHS_PER_YEAR> MONTH_FULL_NAMES = {
+ "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"};
+
+constexpr int NON_LEAP_YEAR_DAYS_IN_MONTH[] = {31, 28, 31, 30, 31, 30,
+ 31, 31, 30, 31, 30, 31};
+
+} // namespace time_constants
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_TIME_TIME_CONSTANTS_H
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index 509cad8146df..abc93b8cb961 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -10,12 +10,11 @@
#include "src/__support/CPP/limits.h" // INT_MIN, INT_MAX
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
+#include "src/time/time_constants.h"
namespace LIBC_NAMESPACE_DECL {
namespace time_utils {
-using LIBC_NAMESPACE::time_utils::TimeConstants;
-
static int64_t computeRemainingYears(int64_t daysPerYears,
int64_t quotientYears,
int64_t *remainingDays) {
@@ -52,36 +51,36 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
(sizeof(time_t) == 4)
? INT_MIN
: INT_MIN * static_cast<int64_t>(
- TimeConstants::NUMBER_OF_SECONDS_IN_LEAP_YEAR);
+ time_constants::NUMBER_OF_SECONDS_IN_LEAP_YEAR);
constexpr time_t time_max =
(sizeof(time_t) == 4)
? INT_MAX
: INT_MAX * static_cast<int64_t>(
- TimeConstants::NUMBER_OF_SECONDS_IN_LEAP_YEAR);
+ time_constants::NUMBER_OF_SECONDS_IN_LEAP_YEAR);
time_t ts = static_cast<time_t>(total_seconds);
if (ts < time_min || ts > time_max)
return time_utils::out_of_range();
int64_t seconds =
- total_seconds - TimeConstants::SECONDS_UNTIL2000_MARCH_FIRST;
- int64_t days = seconds / TimeConstants::SECONDS_PER_DAY;
- int64_t remainingSeconds = seconds % TimeConstants::SECONDS_PER_DAY;
+ total_seconds - time_constants::SECONDS_UNTIL2000_MARCH_FIRST;
+ int64_t days = seconds / time_constants::SECONDS_PER_DAY;
+ int64_t remainingSeconds = seconds % time_constants::SECONDS_PER_DAY;
if (remainingSeconds < 0) {
- remainingSeconds += TimeConstants::SECONDS_PER_DAY;
+ remainingSeconds += time_constants::SECONDS_PER_DAY;
days--;
}
- int64_t wday = (TimeConstants::WEEK_DAY_OF2000_MARCH_FIRST + days) %
- TimeConstants::DAYS_PER_WEEK;
+ int64_t wday = (time_constants::WEEK_DAY_OF2000_MARCH_FIRST + days) %
+ time_constants::DAYS_PER_WEEK;
if (wday < 0)
- wday += TimeConstants::DAYS_PER_WEEK;
+ wday += time_constants::DAYS_PER_WEEK;
// Compute the number of 400 year cycles.
- int64_t numOfFourHundredYearCycles = days / TimeConstants::DAYS_PER400_YEARS;
- int64_t remainingDays = days % TimeConstants::DAYS_PER400_YEARS;
+ int64_t numOfFourHundredYearCycles = days / time_constants::DAYS_PER400_YEARS;
+ int64_t remainingDays = days % time_constants::DAYS_PER400_YEARS;
if (remainingDays < 0) {
- remainingDays += TimeConstants::DAYS_PER400_YEARS;
+ remainingDays += time_constants::DAYS_PER400_YEARS;
numOfFourHundredYearCycles--;
}
@@ -89,17 +88,17 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
// "four hundred year cycles" will be 4 hundred year cycles or less in 400
// years.
int64_t numOfHundredYearCycles = computeRemainingYears(
- TimeConstants::DAYS_PER100_YEARS, 4, &remainingDays);
+ time_constants::DAYS_PER100_YEARS, 4, &remainingDays);
// The remaining number of years after computing the number of
// "hundred year cycles" will be 25 four year cycles or less in 100 years.
- int64_t numOfFourYearCycles =
- computeRemainingYears(TimeConstants::DAYS_PER4_YEARS, 25, &remainingDays);
+ int64_t numOfFourYearCycles = computeRemainingYears(
+ time_constants::DAYS_PER4_YEARS, 25, &remainingDays);
// The remaining number of years after computing the number of
// "four year cycles" will be 4 one year cycles or less in 4 years.
int64_t remainingYears = computeRemainingYears(
- TimeConstants::DAYS_PER_NON_LEAP_YEAR, 4, &remainingDays);
+ time_constants::DAYS_PER_NON_LEAP_YEAR, 4, &remainingDays);
// Calculate number of years from year 2000.
int64_t years = remainingYears + 4 * numOfFourYearCycles +
@@ -112,8 +111,8 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
// We add 31 and 28 for the number of days in January and February, since our
// starting point was March 1st.
int64_t yday = remainingDays + 31 + 28 + leapDay;
- if (yday >= TimeConstants::DAYS_PER_NON_LEAP_YEAR + leapDay)
- yday -= TimeConstants::DAYS_PER_NON_LEAP_YEAR + leapDay;
+ if (yday >= time_constants::DAYS_PER_NON_LEAP_YEAR + leapDay)
+ yday -= time_constants::DAYS_PER_NON_LEAP_YEAR + leapDay;
int64_t months = 0;
while (daysInMonth[months] <= remainingDays) {
@@ -121,8 +120,8 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
months++;
}
- if (months >= TimeConstants::MONTHS_PER_YEAR - 2) {
- months -= TimeConstants::MONTHS_PER_YEAR;
+ if (months >= time_constants::MONTHS_PER_YEAR - 2) {
+ months -= time_constants::MONTHS_PER_YEAR;
years++;
}
@@ -131,19 +130,19 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
// All the data (years, month and remaining days) was calculated from
// March, 2000. Thus adjust the data to be from January, 1900.
- tm->tm_year = static_cast<int>(years + 2000 - TimeConstants::TIME_YEAR_BASE);
+ tm->tm_year = static_cast<int>(years + 2000 - time_constants::TIME_YEAR_BASE);
tm->tm_mon = static_cast<int>(months + 2);
tm->tm_mday = static_cast<int>(remainingDays + 1);
tm->tm_wday = static_cast<int>(wday);
tm->tm_yday = static_cast<int>(yday);
tm->tm_hour =
- static_cast<int>(remainingSeconds / TimeConstants::SECONDS_PER_HOUR);
+ static_cast<int>(remainingSeconds / time_constants::SECONDS_PER_HOUR);
tm->tm_min =
- static_cast<int>(remainingSeconds / TimeConstants::SECONDS_PER_MIN %
- TimeConstants::SECONDS_PER_MIN);
+ static_cast<int>(remainingSeconds / time_constants::SECONDS_PER_MIN %
+ time_constants::SECONDS_PER_MIN);
tm->tm_sec =
- static_cast<int>(remainingSeconds % TimeConstants::SECONDS_PER_MIN);
+ static_cast<int>(remainingSeconds % time_constants::SECONDS_PER_MIN);
// TODO(rtenneti): Need to handle timezone and update of tm_isdst.
tm->tm_isdst = 0;
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 552ea925c1c7..5e0a692d4db0 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -9,79 +9,19 @@
#ifndef LLVM_LIBC_SRC_TIME_TIME_UTILS_H
#define LLVM_LIBC_SRC_TIME_TIME_UTILS_H
-#include <stddef.h> // For size_t.
-
+#include "hdr/types/size_t.h"
+#include "hdr/types/struct_tm.h"
+#include "hdr/types/time_t.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/errno/libc_errno.h"
-#include "src/time/mktime.h"
+#include "time_constants.h"
#include <stdint.h>
namespace LIBC_NAMESPACE_DECL {
namespace time_utils {
-enum Month : int {
- JANUARY,
- FEBRUARY,
- MARCH,
- APRIL,
- MAY,
- JUNE,
- JULY,
- AUGUST,
- SEPTEMBER,
- OCTOBER,
- NOVEMBER,
- DECEMBER
-};
-
-struct TimeConstants {
- static constexpr int SECONDS_PER_MIN = 60;
- static constexpr int MINUTES_PER_HOUR = 60;
- static constexpr int HOURS_PER_DAY = 24;
- static constexpr int DAYS_PER_WEEK = 7;
- static constexpr int MONTHS_PER_YEAR = 12;
- static constexpr int DAYS_PER_NON_LEAP_YEAR = 365;
- static constexpr int DAYS_PER_LEAP_YEAR = 366;
-
- static constexpr int SECONDS_PER_HOUR = SECONDS_PER_MIN * MINUTES_PER_HOUR;
- static constexpr int SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY;
- static constexpr int NUMBER_OF_SECONDS_IN_LEAP_YEAR =
- DAYS_PER_LEAP_YEAR * SECONDS_PER_DAY;
-
- static constexpr int TIME_YEAR_BASE = 1900;
- static constexpr int EPOCH_YEAR = 1970;
- static constexpr int EPOCH_WEEK_DAY = 4;
-
- // For asctime the behavior is undefined if struct tm's tm_wday or tm_mon are
- // not within the normal ranges as defined in <time.h>, or if struct tm's
- // tm_year exceeds {INT_MAX}-1990, or if the below asctime_internal algorithm
- // would attempt to generate more than 26 bytes of output (including the
- // terminating null).
- static constexpr int ASCTIME_BUFFER_SIZE = 256;
- static constexpr int ASCTIME_MAX_BYTES = 26;
-
- /* 2000-03-01 (mod 400 year, immediately after feb29 */
- static constexpr int64_t SECONDS_UNTIL2000_MARCH_FIRST =
- (946684800LL + SECONDS_PER_DAY * (31 + 29));
- static constexpr int WEEK_DAY_OF2000_MARCH_FIRST = 3;
-
- static constexpr int DAYS_PER400_YEARS =
- (DAYS_PER_NON_LEAP_YEAR * 400) + (400 / 4) - 3;
- static constexpr int DAYS_PER100_YEARS =
- (DAYS_PER_NON_LEAP_YEAR * 100) + (100 / 4) - 1;
- static constexpr int DAYS_PER4_YEARS = (DAYS_PER_NON_LEAP_YEAR * 4) + 1;
-
- // The latest time that can be represented in this form is 03:14:07 UTC on
- // Tuesday, 19 January 2038 (corresponding to 2,147,483,647 seconds since the
- // start of the epoch). This means that systems using a 32-bit time_t type are
- // susceptible to the Year 2038 problem.
- static constexpr int END_OF32_BIT_EPOCH_YEAR = 2038;
-
- static constexpr time_t OUT_OF_RANGE_RETURN_VALUE = -1;
-};
-
// Update the "tm" structure's year, month, etc. members from seconds.
// "total_seconds" is the number of seconds since January 1st, 1970.
extern int64_t update_from_seconds(int64_t total_seconds, struct tm *tm);
@@ -98,7 +38,7 @@ LIBC_INLINE time_t out_of_range() {
// require it.
libc_errno = EOVERFLOW;
#endif
- return TimeConstants::OUT_OF_RANGE_RETURN_VALUE;
+ return time_constants::OUT_OF_RANGE_RETURN_VALUE;
}
LIBC_INLINE void invalid_value() { libc_errno = EINVAL; }
@@ -110,32 +50,23 @@ LIBC_INLINE char *asctime(const struct tm *timeptr, char *buffer,
return nullptr;
}
if (timeptr->tm_wday < 0 ||
- timeptr->tm_wday > (TimeConstants::DAYS_PER_WEEK - 1)) {
+ timeptr->tm_wday > (time_constants::DAYS_PER_WEEK - 1)) {
invalid_value();
return nullptr;
}
if (timeptr->tm_mon < 0 ||
- timeptr->tm_mon > (TimeConstants::MONTHS_PER_YEAR - 1)) {
+ timeptr->tm_mon > (time_constants::MONTHS_PER_YEAR - 1)) {
invalid_value();
return nullptr;
}
- // TODO(rtenneti): i18n the following strings.
- static const char *week_days_name[TimeConstants::DAYS_PER_WEEK] = {
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
-
- static const char *months_name[TimeConstants::MONTHS_PER_YEAR] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
-
- // TODO(michaelr): look into removing this call to __builtin_snprintf that may
- // be emitted as a call to snprintf. Alternatively, look into using our
- // internal printf machinery.
+ // TODO(michaelr): move this to use the strftime machinery
int written_size = __builtin_snprintf(
buffer, bufferLength, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
- week_days_name[timeptr->tm_wday], months_name[timeptr->tm_mon],
- timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec,
- TimeConstants::TIME_YEAR_BASE + timeptr->tm_year);
+ time_constants::WEEK_DAY_NAMES[timeptr->tm_wday].data(),
+ time_constants::MONTH_NAMES[timeptr->tm_mon].data(), timeptr->tm_mday,
+ timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec,
+ time_constants::TIME_YEAR_BASE + timeptr->tm_year);
if (written_size < 0)
return nullptr;
if (static_cast<size_t>(written_size) >= bufferLength) {