summaryrefslogtreecommitdiff
path: root/absl/time/internal/cctz
diff options
context:
space:
mode:
Diffstat (limited to 'absl/time/internal/cctz')
-rw-r--r--absl/time/internal/cctz/include/cctz/civil_time_detail.h6
-rw-r--r--absl/time/internal/cctz/include/cctz/time_zone.h5
-rw-r--r--absl/time/internal/cctz/src/civil_time_test.cc2
-rw-r--r--absl/time/internal/cctz/src/time_zone_fixed.cc25
-rw-r--r--absl/time/internal/cctz/src/time_zone_libc.cc2
-rw-r--r--absl/time/internal/cctz/src/time_zone_lookup_test.cc12
-rw-r--r--absl/time/internal/cctz/src/time_zone_posix.h40
7 files changed, 70 insertions, 22 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 5fe0967f..d7f72717 100644
--- a/absl/time/internal/cctz/include/cctz/civil_time_detail.h
+++ b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
@@ -416,6 +416,12 @@ class civil_time {
return difference(T{}, lhs.f_, rhs.f_);
}
+ template <typename H>
+ friend H AbslHashValue(H h, civil_time a) {
+ return H::combine(std::move(h), a.f_.y, a.f_.m, a.f_.d,
+ a.f_.hh, a.f_.mm, a.f_.ss);
+ }
+
private:
// All instantiations of this template are allowed to call the following
// private constructor and access the private fields member.
diff --git a/absl/time/internal/cctz/include/cctz/time_zone.h b/absl/time/internal/cctz/include/cctz/time_zone.h
index c86a5552..f28dad17 100644
--- a/absl/time/internal/cctz/include/cctz/time_zone.h
+++ b/absl/time/internal/cctz/include/cctz/time_zone.h
@@ -224,6 +224,11 @@ class time_zone {
return !(lhs == rhs);
}
+ template <typename H>
+ friend H AbslHashValue(H h, time_zone tz) {
+ return H::combine(std::move(h), &tz.effective_impl());
+ }
+
class Impl;
private:
diff --git a/absl/time/internal/cctz/src/civil_time_test.cc b/absl/time/internal/cctz/src/civil_time_test.cc
index f6648c8f..faffde47 100644
--- a/absl/time/internal/cctz/src/civil_time_test.cc
+++ b/absl/time/internal/cctz/src/civil_time_test.cc
@@ -620,7 +620,7 @@ TEST(CivilTime, Relational) {
TEST_RELATIONAL(civil_second(2014, 1, 1, 1, 1, 0),
civil_second(2014, 1, 1, 1, 1, 1));
- // Tests the relational operators of two different CivilTime types.
+ // Tests the relational operators of two different civil-time types.
TEST_RELATIONAL(civil_day(2014, 1, 1), civil_minute(2014, 1, 1, 1, 1));
TEST_RELATIONAL(civil_day(2014, 1, 1), civil_month(2014, 2));
diff --git a/absl/time/internal/cctz/src/time_zone_fixed.cc b/absl/time/internal/cctz/src/time_zone_fixed.cc
index 598b08fd..db9a475a 100644
--- a/absl/time/internal/cctz/src/time_zone_fixed.cc
+++ b/absl/time/internal/cctz/src/time_zone_fixed.cc
@@ -15,8 +15,8 @@
#include "time_zone_fixed.h"
#include <algorithm>
+#include <cassert>
#include <chrono>
-#include <cstdio>
#include <cstring>
#include <string>
@@ -29,8 +29,15 @@ namespace {
// The prefix used for the internal names of fixed-offset zones.
const char kFixedOffsetPrefix[] = "Fixed/UTC";
+const char kDigits[] = "0123456789";
+
+char* Format02d(char* p, int v) {
+ *p++ = kDigits[(v / 10) % 10];
+ *p++ = kDigits[v % 10];
+ return p;
+}
+
int Parse02d(const char* p) {
- static const char kDigits[] = "0123456789";
if (const char* ap = std::strchr(kDigits, *p)) {
int v = static_cast<int>(ap - kDigits);
if (const char* bp = std::strchr(kDigits, *++p)) {
@@ -95,9 +102,17 @@ std::string FixedOffsetToName(const seconds& offset) {
}
int hours = minutes / 60;
minutes %= 60;
- char buf[sizeof(kFixedOffsetPrefix) + sizeof("-24:00:00")];
- snprintf(buf, sizeof(buf), "%s%c%02d:%02d:%02d",
- kFixedOffsetPrefix, sign, hours, minutes, seconds);
+ char buf[sizeof(kFixedOffsetPrefix) - 1 + sizeof("-24:00:00")];
+ std::strcpy(buf, kFixedOffsetPrefix);
+ char* ep = buf + sizeof(kFixedOffsetPrefix) - 1;
+ *ep++ = sign;
+ ep = Format02d(ep, hours);
+ *ep++ = ':';
+ ep = Format02d(ep, minutes);
+ *ep++ = ':';
+ ep = Format02d(ep, seconds);
+ *ep++ = '\0';
+ assert(ep == buf + sizeof(buf));
return buf;
}
diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc
index 074c8d0a..e35fa18b 100644
--- a/absl/time/internal/cctz/src/time_zone_libc.cc
+++ b/absl/time/internal/cctz/src/time_zone_libc.cc
@@ -111,7 +111,7 @@ time_zone::absolute_lookup TimeZoneLibC::BreakTime(
al.offset = 0;
al.abbr = "UTC";
}
- al.cs = civil_second(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+ al.cs = civil_second(tm.tm_year + year_t{1900}, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
al.is_dst = tm.tm_isdst > 0;
return al;
diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
index 551292fb..f28e7f85 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -990,6 +990,18 @@ TEST(MakeTime, SysSecondsLimits) {
EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);
tp = convert(civil_second::min(), west);
EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);
+
+ if (sizeof(std::time_t) >= 8) {
+ // Checks that "tm_year + 1900", as used by the "libc" implementation,
+ // can produce year values beyond the range on an int without overflow.
+#if defined(_WIN32) || defined(_WIN64)
+ // localtime_s() and gmtime_s() don't believe in years past 3000.
+#else
+ const time_zone libc_utc = LoadZone("libc:UTC");
+ tp = convert(civil_year(year_t{2147483648}), libc_utc);
+ EXPECT_EQ("2147483648-01-01T00:00:00+00:00", format(RFC3339, tp, libc_utc));
+#endif
+ }
}
TEST(NextTransition, UTC) {
diff --git a/absl/time/internal/cctz/src/time_zone_posix.h b/absl/time/internal/cctz/src/time_zone_posix.h
index 9ccd4a8b..ef2a8c16 100644
--- a/absl/time/internal/cctz/src/time_zone_posix.h
+++ b/absl/time/internal/cctz/src/time_zone_posix.h
@@ -68,25 +68,35 @@ namespace cctz {
// it would take us to another day, and perhaps week, or even month.
struct PosixTransition {
enum DateFormat { J, N, M };
- struct {
+
+ struct Date {
+ struct NonLeapDay {
+ std::int_fast16_t day; // day of non-leap year [1:365]
+ };
+ struct Day {
+ std::int_fast16_t day; // day of year [0:365]
+ };
+ struct MonthWeekWeekday {
+ std::int_fast8_t month; // month of year [1:12]
+ std::int_fast8_t week; // week of month [1:5] (5==last)
+ std::int_fast8_t weekday; // 0==Sun, ..., 6=Sat
+ };
+
DateFormat fmt;
+
union {
- struct {
- std::int_fast16_t day; // day of non-leap year [1:365]
- } j;
- struct {
- std::int_fast16_t day; // day of year [0:365]
- } n;
- struct {
- std::int_fast8_t month; // month of year [1:12]
- std::int_fast8_t week; // week of month [1:5] (5==last)
- std::int_fast8_t weekday; // 0==Sun, ..., 6=Sat
- } m;
+ NonLeapDay j;
+ Day n;
+ MonthWeekWeekday m;
};
- } date;
- struct {
+ };
+
+ struct Time {
std::int_fast32_t offset; // seconds before/after 00:00:00
- } time;
+ };
+
+ Date date;
+ Time time;
};
// The entirety of a POSIX-string specified time-zone rule. The standard