[libc-commits] [libc] [libc] create TimeReader to look at a struct tm (PR #126138)

Nick Desaulniers via libc-commits libc-commits at lists.llvm.org
Thu Feb 6 14:32:46 PST 2025


================
@@ -94,6 +101,255 @@ LIBC_INLINE struct tm *localtime(const time_t *t_ptr) {
   return time_utils::gmtime_internal(t_ptr, &result);
 }
 
+// Returns number of years from (1, year).
+LIBC_INLINE constexpr int64_t get_num_of_leap_years_before(int64_t year) {
+  return (year / 4) - (year / 100) + (year / 400);
+}
+
+// Returns True if year is a leap year.
+LIBC_INLINE constexpr bool is_leap_year(const int64_t year) {
+  return (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0));
+}
+
+LIBC_INLINE constexpr int get_days_in_year(const int year) {
+  return is_leap_year(year) ? time_constants::DAYS_PER_LEAP_YEAR
+                            : time_constants::DAYS_PER_NON_LEAP_YEAR;
+}
+
+// This is a helper class that takes a struct tm and lets you inspect its
+// values. Where relevant, results are bounds checked and returned as optionals.
+// This class does not, however, do data normalization except where necessary.
+// It will faithfully return a date of 9999-99-99, even though that makes no
+// sense.
+class TMReader final {
+  const tm *timeptr;
+
+public:
+  LIBC_INLINE constexpr TMReader(const tm *tmptr) : timeptr(tmptr) { ; }
+
+  // Strings
+  LIBC_INLINE constexpr cpp::optional<cpp::string_view>
+  get_weekday_short_name() const {
+    if (timeptr->tm_wday >= 0 &&
+        timeptr->tm_wday < time_constants::DAYS_PER_WEEK)
----------------
nickdesaulniers wrote:

I guess this is shorter than 
```suggestion
    if (timeptr->tm_wday >= 0 &&
        timeptr->tm_wday < time_constants::WEEK_DAY_NAMES.size())
```
but I think you could further share the bounds check and have less code:
```c++
cpp::string_view bounds_check(const cpp::span<cpp::string_view> &arr, int index) {
  return index >= 0 && index < arr.size() ? arr[index] : {};
}
cpp::string_view get_weekday_short_name() const {
  return bounds_check(time_constants::WEEK_DAY_NAMES, timeptr->tm_wday);
}
cpp::string_view get_weekday_full_name() const {
  return bounds_check(time_constants::WEEK_DAY_FULL_NAMES, timeptr->tm_wday);
}
cpp::string_view get_month_short_name const {
  return bounds_check(time_constants::MONTH_NAMES, timeptr->tm_mon);
}
cpp::string_view get_month_full_name const {
  return bounds_check(time_constants::MONTH_FULL_NAMES, timeptr->tm_mon);
}
```
but perhaps our cpp::array doesn't (yet) convert to cpp::span?

https://github.com/llvm/llvm-project/pull/126138


More information about the libc-commits mailing list