diff options
Diffstat (limited to 'absl/time')
-rw-r--r-- | absl/time/duration.cc | 5 | ||||
-rw-r--r-- | absl/time/format.cc | 8 | ||||
-rw-r--r-- | absl/time/internal/cctz/src/time_zone_impl.cc | 11 | ||||
-rw-r--r-- | absl/time/time.cc | 14 | ||||
-rw-r--r-- | absl/time/time.h | 9 | ||||
-rw-r--r-- | absl/time/time_test.cc | 24 |
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) { |