about summary refs log tree commit diff
path: root/absl/time
diff options
context:
space:
mode:
Diffstat (limited to 'absl/time')
-rw-r--r--absl/time/internal/cctz/include/cctz/civil_time_detail.h38
-rw-r--r--absl/time/internal/cctz/src/cctz_benchmark.cc50
2 files changed, 84 insertions, 4 deletions
diff --git a/absl/time/internal/cctz/include/cctz/civil_time_detail.h b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
index bb191b3faee5..3e2434033935 100644
--- a/absl/time/internal/cctz/include/cctz/civil_time_detail.h
+++ b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
@@ -555,13 +555,43 @@ CONSTEXPR_F weekday get_weekday(const civil_day& cd) noexcept {
 ////////////////////////////////////////////////////////////////////////
 
 CONSTEXPR_F civil_day next_weekday(civil_day cd, weekday wd) noexcept {
-  do { cd += 1; } while (get_weekday(cd) != wd);
-  return cd;
+  CONSTEXPR_D weekday k_weekdays_forw[14] = {
+      weekday::monday,    weekday::tuesday,  weekday::wednesday,
+      weekday::thursday,  weekday::friday,   weekday::saturday,
+      weekday::sunday,    weekday::monday,   weekday::tuesday,
+      weekday::wednesday, weekday::thursday, weekday::friday,
+      weekday::saturday,  weekday::sunday,
+  };
+  weekday base = get_weekday(cd);
+  for (int i = 0;; ++i) {
+    if (base == k_weekdays_forw[i]) {
+      for (int j = i + 1;; ++j) {
+        if (wd == k_weekdays_forw[j]) {
+          return cd + (j - i);
+        }
+      }
+    }
+  }
 }
 
 CONSTEXPR_F civil_day prev_weekday(civil_day cd, weekday wd) noexcept {
-  do { cd -= 1; } while (get_weekday(cd) != wd);
-  return cd;
+  CONSTEXPR_D weekday k_weekdays_back[14] = {
+      weekday::sunday,   weekday::saturday,  weekday::friday,
+      weekday::thursday, weekday::wednesday, weekday::tuesday,
+      weekday::monday,   weekday::sunday,    weekday::saturday,
+      weekday::friday,   weekday::thursday,  weekday::wednesday,
+      weekday::tuesday,  weekday::monday,
+  };
+  weekday base = get_weekday(cd);
+  for (int i = 0;; ++i) {
+    if (base == k_weekdays_back[i]) {
+      for (int j = i + 1;; ++j) {
+        if (wd == k_weekdays_back[j]) {
+          return cd - (j - i);
+        }
+      }
+    }
+  }
 }
 
 CONSTEXPR_F int get_yearday(const civil_day& cd) noexcept {
diff --git a/absl/time/internal/cctz/src/cctz_benchmark.cc b/absl/time/internal/cctz/src/cctz_benchmark.cc
index 445366eae506..a40f504e063e 100644
--- a/absl/time/internal/cctz/src/cctz_benchmark.cc
+++ b/absl/time/internal/cctz/src/cctz_benchmark.cc
@@ -47,6 +47,56 @@ void BM_Step_Days(benchmark::State& state) {
 }
 BENCHMARK(BM_Step_Days);
 
+void BM_GetWeekday(benchmark::State& state) {
+  const cctz::civil_day c(2014, 8, 22);
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(cctz::get_weekday(c));
+  }
+}
+BENCHMARK(BM_GetWeekday);
+
+void BM_NextWeekday(benchmark::State& state) {
+  const cctz::civil_day kStart(2014, 8, 22);
+  const cctz::civil_day kDays[7] = {
+      kStart + 0, kStart + 1, kStart + 2, kStart + 3,
+      kStart + 4, kStart + 5, kStart + 6,
+  };
+  const cctz::weekday kWeekdays[7] = {
+      cctz::weekday::monday,   cctz::weekday::tuesday, cctz::weekday::wednesday,
+      cctz::weekday::thursday, cctz::weekday::friday,  cctz::weekday::saturday,
+      cctz::weekday::sunday,
+  };
+  while (state.KeepRunningBatch(7 * 7)) {
+    for (const auto from : kDays) {
+      for (const auto to : kWeekdays) {
+        benchmark::DoNotOptimize(cctz::next_weekday(from, to));
+      }
+    }
+  }
+}
+BENCHMARK(BM_NextWeekday);
+
+void BM_PrevWeekday(benchmark::State& state) {
+  const cctz::civil_day kStart(2014, 8, 22);
+  const cctz::civil_day kDays[7] = {
+      kStart + 0, kStart + 1, kStart + 2, kStart + 3,
+      kStart + 4, kStart + 5, kStart + 6,
+  };
+  const cctz::weekday kWeekdays[7] = {
+      cctz::weekday::monday,   cctz::weekday::tuesday, cctz::weekday::wednesday,
+      cctz::weekday::thursday, cctz::weekday::friday,  cctz::weekday::saturday,
+      cctz::weekday::sunday,
+  };
+  while (state.KeepRunningBatch(7 * 7)) {
+    for (const auto from : kDays) {
+      for (const auto to : kWeekdays) {
+        benchmark::DoNotOptimize(cctz::prev_weekday(from, to));
+      }
+    }
+  }
+}
+BENCHMARK(BM_PrevWeekday);
+
 const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
 const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez";