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/duration.cc5
-rw-r--r--absl/time/format.cc8
-rw-r--r--absl/time/internal/cctz/src/time_zone_impl.cc11
-rw-r--r--absl/time/time.cc14
-rw-r--r--absl/time/time.h9
-rw-r--r--absl/time/time_test.cc24
6 files changed, 66 insertions, 5 deletions
diff --git a/absl/time/duration.cc b/absl/time/duration.cc
index a3ac61a91894..9a8768113f31 100644
--- a/absl/time/duration.cc
+++ b/absl/time/duration.cc
@@ -906,6 +906,11 @@ bool ParseDuration(const std::string& dur_string, Duration* d) {
   return true;
 }
 
+bool AbslParseFlag(absl::string_view text, Duration* dst, std::string*) {
+  return ParseDuration(std::string(text), dst);
+}
+
+std::string AbslUnparseFlag(Duration d) { return FormatDuration(d); }
 bool ParseFlag(const std::string& text, Duration* dst, std::string* ) {
   return ParseDuration(text, dst);
 }
diff --git a/absl/time/format.cc b/absl/time/format.cc
index d6ca860038dc..ebe872cf7402 100644
--- a/absl/time/format.cc
+++ b/absl/time/format.cc
@@ -129,6 +129,14 @@ bool ParseTime(const std::string& format, const std::string& input,
 }
 
 // Functions required to support absl::Time flags.
+bool AbslParseFlag(absl::string_view text, absl::Time* t, std::string* error) {
+  return absl::ParseTime(RFC3339_full, std::string(text), absl::UTCTimeZone(),
+                         t, error);
+}
+
+std::string AbslUnparseFlag(absl::Time t) {
+  return absl::FormatTime(RFC3339_full, t, absl::UTCTimeZone());
+}
 bool ParseFlag(const std::string& text, absl::Time* t, std::string* error) {
   return absl::ParseTime(RFC3339_full, text, absl::UTCTimeZone(), t, error);
 }
diff --git a/absl/time/internal/cctz/src/time_zone_impl.cc b/absl/time/internal/cctz/src/time_zone_impl.cc
index a26151d3e917..a241e951d1fb 100644
--- a/absl/time/internal/cctz/src/time_zone_impl.cc
+++ b/absl/time/internal/cctz/src/time_zone_impl.cc
@@ -14,6 +14,7 @@
 
 #include "time_zone_impl.h"
 
+#include <deque>
 #include <mutex>
 #include <string>
 #include <unordered_map>
@@ -91,8 +92,14 @@ bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) {
 void time_zone::Impl::ClearTimeZoneMapTestOnly() {
   std::lock_guard<std::mutex> lock(TimeZoneMutex());
   if (time_zone_map != nullptr) {
-    // Existing time_zone::Impl* entries are in the wild, so we simply
-    // leak them.  Future requests will result in reloading the data.
+    // Existing time_zone::Impl* entries are in the wild, so we can't delete
+    // them. Instead, we move them to a private container, where they are
+    // logically unreachable but not "leaked".  Future requests will result
+    // in reloading the data.
+    static auto* cleared = new std::deque<const time_zone::Impl*>;
+    for (const auto& element : *time_zone_map) {
+      cleared->push_back(element.second);
+    }
     time_zone_map->clear();
   }
 }
diff --git a/absl/time/time.cc b/absl/time/time.cc
index 6a387bcee61f..60382be7b801 100644
--- a/absl/time/time.cc
+++ b/absl/time/time.cc
@@ -430,9 +430,17 @@ absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
 }
 
 absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) {
-  const CivilSecond cs(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-                       tm.tm_hour, tm.tm_min, tm.tm_sec);
-  const auto ti = tz.At(cs);
+  civil_year_t tm_year = tm.tm_year;
+  // Avoids years that are too extreme for CivilSecond to normalize.
+  if (tm_year > 300000000000ll) return InfiniteFuture();
+  if (tm_year < -300000000000ll) return InfinitePast();
+  int tm_mon = tm.tm_mon;
+  if (tm_mon == std::numeric_limits<int>::max()) {
+    tm_mon -= 12;
+    tm_year += 1;
+  }
+  const auto ti = tz.At(CivilSecond(tm_year + 1900, tm_mon + 1, tm.tm_mday,
+                                    tm.tm_hour, tm.tm_min, tm.tm_sec));
   return tm.tm_isdst == 0 ? ti.post : ti.pre;
 }
 
diff --git a/absl/time/time.h b/absl/time/time.h
index 9c8f31774ac6..0b7312ee983d 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -83,6 +83,7 @@ struct timeval;
 #include <type_traits>
 #include <utility>
 
+#include "absl/base/macros.h"
 #include "absl/strings/string_view.h"
 #include "absl/time/civil_time.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
@@ -545,7 +546,11 @@ bool ParseDuration(const std::string& dur_string, Duration* d);
 
 // Support for flag values of type Duration. Duration flags must be specified
 // in a format that is valid input for absl::ParseDuration().
+bool AbslParseFlag(absl::string_view text, Duration* dst, std::string* error);
+std::string AbslUnparseFlag(Duration d);
+ABSL_DEPRECATED("Use AbslParseFlag() instead.")
 bool ParseFlag(const std::string& text, Duration* dst, std::string* error);
+ABSL_DEPRECATED("Use AbslUnparseFlag() instead.")
 std::string UnparseFlag(Duration d);
 
 // Time
@@ -815,7 +820,11 @@ std::chrono::system_clock::time_point ToChronoTime(Time);
 // Additionally, if you'd like to specify a time as a count of
 // seconds/milliseconds/etc from the Unix epoch, use an absl::Duration flag
 // and add that duration to absl::UnixEpoch() to get an absl::Time.
+bool AbslParseFlag(absl::string_view text, Time* t, std::string* error);
+std::string AbslUnparseFlag(Time t);
+ABSL_DEPRECATED("Use AbslParseFlag() instead.")
 bool ParseFlag(const std::string& text, Time* t, std::string* error);
+ABSL_DEPRECATED("Use AbslUnparseFlag() instead.")
 std::string UnparseFlag(Time t);
 
 // TimeZone
diff --git a/absl/time/time_test.cc b/absl/time/time_test.cc
index 37af39d99830..9c4709e6b469 100644
--- a/absl/time/time_test.cc
+++ b/absl/time/time_test.cc
@@ -795,6 +795,30 @@ TEST(Time, FromTM) {
   tm.tm_isdst = 1;
   t = FromTM(tm, nyc);
   EXPECT_EQ("2014-03-09T03:30:42-04:00", absl::FormatTime(t, nyc));  // DST
+
+  // Adjusts tm to refer to a time with a year larger than 2147483647.
+  tm.tm_year = 2147483647 - 1900 + 1;
+  tm.tm_mon = 6 - 1;
+  tm.tm_mday = 28;
+  tm.tm_hour = 1;
+  tm.tm_min = 2;
+  tm.tm_sec = 3;
+  tm.tm_isdst = -1;
+  t = FromTM(tm, absl::UTCTimeZone());
+  EXPECT_EQ("2147483648-06-28T01:02:03+00:00",
+            absl::FormatTime(t, absl::UTCTimeZone()));
+
+  // Adjusts tm to refer to a time with a very large month.
+  tm.tm_year = 2019 - 1900;
+  tm.tm_mon = 2147483647;
+  tm.tm_mday = 28;
+  tm.tm_hour = 1;
+  tm.tm_min = 2;
+  tm.tm_sec = 3;
+  tm.tm_isdst = -1;
+  t = FromTM(tm, absl::UTCTimeZone());
+  EXPECT_EQ("178958989-08-28T01:02:03+00:00",
+            absl::FormatTime(t, absl::UTCTimeZone()));
 }
 
 TEST(Time, TMRoundTrip) {