-- f51743aa96e19aa3dda96d09d313b4390f1d61e7 by CJ Johnson <johnsoncj@google.com>: Minor touchup on the InlinedVector/Storage internal header file PiperOrigin-RevId: 262389640 -- e2f54c1f7142e40d30ff0fda43bef050625821a5 by Abseil Team <absl-team@google.com>: Update the absl codebase to use proper marketing names for macOS and Xcode PiperOrigin-RevId: 262389450 -- f29aae774edd0d00e2daa1fb96694a6dc3565a55 by CJ Johnson <johnsoncj@google.com>: Blocks code generator script from being affected by LTS inline namespaces PiperOrigin-RevId: 262376791 GitOrigin-RevId: f51743aa96e19aa3dda96d09d313b4390f1d61e7 Change-Id: I33be7f5a708ce8a2b7111b00151e43d73c5e0009
		
			
				
	
	
		
			441 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			441 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2017 The Abseil Authors.
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //      https://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| #include <cstdint>
 | |
| #include <limits>
 | |
| #include <string>
 | |
| 
 | |
| #include "gmock/gmock.h"
 | |
| #include "gtest/gtest.h"
 | |
| #include "absl/time/internal/test_util.h"
 | |
| #include "absl/time/time.h"
 | |
| 
 | |
| using testing::HasSubstr;
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| // A helper that tests the given format specifier by itself, and with leading
 | |
| // and trailing characters.  For example: TestFormatSpecifier(t, "%a", "Thu").
 | |
| void TestFormatSpecifier(absl::Time t, absl::TimeZone tz,
 | |
|                          const std::string& fmt, const std::string& ans) {
 | |
|   EXPECT_EQ(ans, absl::FormatTime(fmt, t, tz));
 | |
|   EXPECT_EQ("xxx " + ans, absl::FormatTime("xxx " + fmt, t, tz));
 | |
|   EXPECT_EQ(ans + " yyy", absl::FormatTime(fmt + " yyy", t, tz));
 | |
|   EXPECT_EQ("xxx " + ans + " yyy",
 | |
|             absl::FormatTime("xxx " + fmt + " yyy", t, tz));
 | |
| }
 | |
| 
 | |
| //
 | |
| // Testing FormatTime()
 | |
| //
 | |
| 
 | |
| TEST(FormatTime, Basics) {
 | |
|   absl::TimeZone tz = absl::UTCTimeZone();
 | |
|   absl::Time t = absl::FromTimeT(0);
 | |
| 
 | |
|   // Starts with a couple basic edge cases.
 | |
|   EXPECT_EQ("", absl::FormatTime("", t, tz));
 | |
|   EXPECT_EQ(" ", absl::FormatTime(" ", t, tz));
 | |
|   EXPECT_EQ("  ", absl::FormatTime("  ", t, tz));
 | |
|   EXPECT_EQ("xxx", absl::FormatTime("xxx", t, tz));
 | |
|   std::string big(128, 'x');
 | |
|   EXPECT_EQ(big, absl::FormatTime(big, t, tz));
 | |
|   // Cause the 1024-byte buffer to grow.
 | |
|   std::string bigger(100000, 'x');
 | |
|   EXPECT_EQ(bigger, absl::FormatTime(bigger, t, tz));
 | |
| 
 | |
|   t += absl::Hours(13) + absl::Minutes(4) + absl::Seconds(5);
 | |
|   t += absl::Milliseconds(6) + absl::Microseconds(7) + absl::Nanoseconds(8);
 | |
|   EXPECT_EQ("1970-01-01", absl::FormatTime("%Y-%m-%d", t, tz));
 | |
|   EXPECT_EQ("13:04:05", absl::FormatTime("%H:%M:%S", t, tz));
 | |
|   EXPECT_EQ("13:04:05.006", absl::FormatTime("%H:%M:%E3S", t, tz));
 | |
|   EXPECT_EQ("13:04:05.006007", absl::FormatTime("%H:%M:%E6S", t, tz));
 | |
|   EXPECT_EQ("13:04:05.006007008", absl::FormatTime("%H:%M:%E9S", t, tz));
 | |
| }
 | |
| 
 | |
| TEST(FormatTime, LocaleSpecific) {
 | |
|   const absl::TimeZone tz = absl::UTCTimeZone();
 | |
|   absl::Time t = absl::FromTimeT(0);
 | |
| 
 | |
|   TestFormatSpecifier(t, tz, "%a", "Thu");
 | |
|   TestFormatSpecifier(t, tz, "%A", "Thursday");
 | |
|   TestFormatSpecifier(t, tz, "%b", "Jan");
 | |
|   TestFormatSpecifier(t, tz, "%B", "January");
 | |
| 
 | |
|   // %c should at least produce the numeric year and time-of-day.
 | |
|   const std::string s =
 | |
|       absl::FormatTime("%c", absl::FromTimeT(0), absl::UTCTimeZone());
 | |
|   EXPECT_THAT(s, HasSubstr("1970"));
 | |
|   EXPECT_THAT(s, HasSubstr("00:00:00"));
 | |
| 
 | |
|   TestFormatSpecifier(t, tz, "%p", "AM");
 | |
|   TestFormatSpecifier(t, tz, "%x", "01/01/70");
 | |
|   TestFormatSpecifier(t, tz, "%X", "00:00:00");
 | |
| }
 | |
| 
 | |
| TEST(FormatTime, ExtendedSeconds) {
 | |
|   const absl::TimeZone tz = absl::UTCTimeZone();
 | |
| 
 | |
|   // No subseconds.
 | |
|   absl::Time t = absl::FromTimeT(0) + absl::Seconds(5);
 | |
|   EXPECT_EQ("05", absl::FormatTime("%E*S", t, tz));
 | |
|   EXPECT_EQ("05.000000000000000", absl::FormatTime("%E15S", t, tz));
 | |
| 
 | |
|   // With subseconds.
 | |
|   t += absl::Milliseconds(6) + absl::Microseconds(7) + absl::Nanoseconds(8);
 | |
|   EXPECT_EQ("05.006007008", absl::FormatTime("%E*S", t, tz));
 | |
|   EXPECT_EQ("05", absl::FormatTime("%E0S", t, tz));
 | |
|   EXPECT_EQ("05.006007008000000", absl::FormatTime("%E15S", t, tz));
 | |
| 
 | |
|   // Times before the Unix epoch.
 | |
|   t = absl::FromUnixMicros(-1);
 | |
|   EXPECT_EQ("1969-12-31 23:59:59.999999",
 | |
|             absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz));
 | |
| 
 | |
|   // Here is a "%E*S" case we got wrong for a while.  While the first
 | |
|   // instant below is correctly rendered as "...:07.333304", the second
 | |
|   // one used to appear as "...:07.33330499999999999".
 | |
|   t = absl::FromUnixMicros(1395024427333304);
 | |
|   EXPECT_EQ("2014-03-17 02:47:07.333304",
 | |
|             absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz));
 | |
|   t += absl::Microseconds(1);
 | |
|   EXPECT_EQ("2014-03-17 02:47:07.333305",
 | |
|             absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz));
 | |
| }
 | |
| 
 | |
| TEST(FormatTime, RFC1123FormatPadsYear) {  // locale specific
 | |
|   absl::TimeZone tz = absl::UTCTimeZone();
 | |
| 
 | |
|   // A year of 77 should be padded to 0077.
 | |
|   absl::Time t = absl::FromCivil(absl::CivilSecond(77, 6, 28, 9, 8, 7), tz);
 | |
|   EXPECT_EQ("Mon, 28 Jun 0077 09:08:07 +0000",
 | |
|             absl::FormatTime(absl::RFC1123_full, t, tz));
 | |
|   EXPECT_EQ("28 Jun 0077 09:08:07 +0000",
 | |
|             absl::FormatTime(absl::RFC1123_no_wday, t, tz));
 | |
| }
 | |
| 
 | |
| TEST(FormatTime, InfiniteTime) {
 | |
|   absl::TimeZone tz = absl::time_internal::LoadTimeZone("America/Los_Angeles");
 | |
| 
 | |
|   // The format and timezone are ignored.
 | |
|   EXPECT_EQ("infinite-future",
 | |
|             absl::FormatTime("%H:%M blah", absl::InfiniteFuture(), tz));
 | |
|   EXPECT_EQ("infinite-past",
 | |
|             absl::FormatTime("%H:%M blah", absl::InfinitePast(), tz));
 | |
| }
 | |
| 
 | |
| //
 | |
| // Testing ParseTime()
 | |
| //
 | |
| 
 | |
| TEST(ParseTime, Basics) {
 | |
|   absl::Time t = absl::FromTimeT(1234567890);
 | |
|   std::string err;
 | |
| 
 | |
|   // Simple edge cases.
 | |
|   EXPECT_TRUE(absl::ParseTime("", "", &t, &err)) << err;
 | |
|   EXPECT_EQ(absl::UnixEpoch(), t);  // everything defaulted
 | |
|   EXPECT_TRUE(absl::ParseTime(" ", " ", &t, &err)) << err;
 | |
|   EXPECT_TRUE(absl::ParseTime("  ", "  ", &t, &err)) << err;
 | |
|   EXPECT_TRUE(absl::ParseTime("x", "x", &t, &err)) << err;
 | |
|   EXPECT_TRUE(absl::ParseTime("xxx", "xxx", &t, &err)) << err;
 | |
| 
 | |
|   EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z",
 | |
|                               "2013-06-28 19:08:09 -0800", &t, &err))
 | |
|       << err;
 | |
|   const auto ci = absl::FixedTimeZone(-8 * 60 * 60).At(t);
 | |
|   EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
 | |
|   EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
 | |
| }
 | |
| 
 | |
| TEST(ParseTime, NullErrorString) {
 | |
|   absl::Time t;
 | |
|   EXPECT_FALSE(absl::ParseTime("%Q", "invalid format", &t, nullptr));
 | |
|   EXPECT_FALSE(absl::ParseTime("%H", "12 trailing data", &t, nullptr));
 | |
|   EXPECT_FALSE(
 | |
|       absl::ParseTime("%H out of range", "42 out of range", &t, nullptr));
 | |
| }
 | |
| 
 | |
| TEST(ParseTime, WithTimeZone) {
 | |
|   const absl::TimeZone tz =
 | |
|       absl::time_internal::LoadTimeZone("America/Los_Angeles");
 | |
|   absl::Time t;
 | |
|   std::string e;
 | |
| 
 | |
|   // We can parse a std::string without a UTC offset if we supply a timezone.
 | |
|   EXPECT_TRUE(
 | |
|       absl::ParseTime("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &t, &e))
 | |
|       << e;
 | |
|   auto ci = tz.At(t);
 | |
|   EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
 | |
|   EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
 | |
| 
 | |
|   // But the timezone is ignored when a UTC offset is present.
 | |
|   EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z",
 | |
|                               "2013-06-28 19:08:09 +0800", tz, &t, &e))
 | |
|       << e;
 | |
|   ci = absl::FixedTimeZone(8 * 60 * 60).At(t);
 | |
|   EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
 | |
|   EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
 | |
| }
 | |
| 
 | |
| TEST(ParseTime, ErrorCases) {
 | |
|   absl::Time t = absl::FromTimeT(0);
 | |
|   std::string err;
 | |
| 
 | |
|   EXPECT_FALSE(absl::ParseTime("%S", "123", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
 | |
| 
 | |
|   // Can't parse an illegal format specifier.
 | |
|   err.clear();
 | |
|   EXPECT_FALSE(absl::ParseTime("%Q", "x", &t, &err)) << err;
 | |
|   // Exact contents of "err" are platform-dependent because of
 | |
|   // differences in the strptime implementation between macOS and Linux.
 | |
|   EXPECT_FALSE(err.empty());
 | |
| 
 | |
|   // Fails because of trailing, unparsed data "blah".
 | |
|   EXPECT_FALSE(absl::ParseTime("%m-%d", "2-3 blah", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
 | |
| 
 | |
|   // Feb 31 requires normalization.
 | |
|   EXPECT_FALSE(absl::ParseTime("%m-%d", "2-31", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Out-of-range"));
 | |
| 
 | |
|   // Check that we cannot have spaces in UTC offsets.
 | |
|   EXPECT_TRUE(absl::ParseTime("%z", "-0203", &t, &err)) << err;
 | |
|   EXPECT_FALSE(absl::ParseTime("%z", "- 2 3", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Failed to parse"));
 | |
|   EXPECT_TRUE(absl::ParseTime("%Ez", "-02:03", &t, &err)) << err;
 | |
|   EXPECT_FALSE(absl::ParseTime("%Ez", "- 2: 3", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Failed to parse"));
 | |
| 
 | |
|   // Check that we reject other malformed UTC offsets.
 | |
|   EXPECT_FALSE(absl::ParseTime("%Ez", "+-08:00", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Failed to parse"));
 | |
|   EXPECT_FALSE(absl::ParseTime("%Ez", "-+08:00", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Failed to parse"));
 | |
| 
 | |
|   // Check that we do not accept "-0" in fields that allow zero.
 | |
|   EXPECT_FALSE(absl::ParseTime("%Y", "-0", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Failed to parse"));
 | |
|   EXPECT_FALSE(absl::ParseTime("%E4Y", "-0", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Failed to parse"));
 | |
|   EXPECT_FALSE(absl::ParseTime("%H", "-0", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Failed to parse"));
 | |
|   EXPECT_FALSE(absl::ParseTime("%M", "-0", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Failed to parse"));
 | |
|   EXPECT_FALSE(absl::ParseTime("%S", "-0", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Failed to parse"));
 | |
|   EXPECT_FALSE(absl::ParseTime("%z", "+-000", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Failed to parse"));
 | |
|   EXPECT_FALSE(absl::ParseTime("%Ez", "+-0:00", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Failed to parse"));
 | |
|   EXPECT_FALSE(absl::ParseTime("%z", "-00-0", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
 | |
|   EXPECT_FALSE(absl::ParseTime("%Ez", "-00:-0", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
 | |
| }
 | |
| 
 | |
| TEST(ParseTime, ExtendedSeconds) {
 | |
|   std::string err;
 | |
|   absl::Time t;
 | |
| 
 | |
|   // Here is a "%E*S" case we got wrong for a while.  The fractional
 | |
|   // part of the first instant is less than 2^31 and was correctly
 | |
|   // parsed, while the second (and any subsecond field >=2^31) failed.
 | |
|   t = absl::UnixEpoch();
 | |
|   EXPECT_TRUE(absl::ParseTime("%E*S", "0.2147483647", &t, &err)) << err;
 | |
|   EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +
 | |
|                 absl::Nanoseconds(1) / 2,
 | |
|             t);
 | |
|   t = absl::UnixEpoch();
 | |
|   EXPECT_TRUE(absl::ParseTime("%E*S", "0.2147483648", &t, &err)) << err;
 | |
|   EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +
 | |
|                 absl::Nanoseconds(3) / 4,
 | |
|             t);
 | |
| 
 | |
|   // We should also be able to specify long strings of digits far
 | |
|   // beyond the current resolution and have them convert the same way.
 | |
|   t = absl::UnixEpoch();
 | |
|   EXPECT_TRUE(absl::ParseTime(
 | |
|       "%E*S", "0.214748364801234567890123456789012345678901234567890123456789",
 | |
|       &t, &err))
 | |
|       << err;
 | |
|   EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +
 | |
|                 absl::Nanoseconds(3) / 4,
 | |
|             t);
 | |
| }
 | |
| 
 | |
| TEST(ParseTime, ExtendedOffsetErrors) {
 | |
|   std::string err;
 | |
|   absl::Time t;
 | |
| 
 | |
|   // %z against +-HHMM.
 | |
|   EXPECT_FALSE(absl::ParseTime("%z", "-123", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
 | |
| 
 | |
|   // %z against +-HH.
 | |
|   EXPECT_FALSE(absl::ParseTime("%z", "-1", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Failed to parse"));
 | |
| 
 | |
|   // %Ez against +-HH:MM.
 | |
|   EXPECT_FALSE(absl::ParseTime("%Ez", "-12:3", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
 | |
| 
 | |
|   // %Ez against +-HHMM.
 | |
|   EXPECT_FALSE(absl::ParseTime("%Ez", "-123", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
 | |
| 
 | |
|   // %Ez against +-HH.
 | |
|   EXPECT_FALSE(absl::ParseTime("%Ez", "-1", &t, &err)) << err;
 | |
|   EXPECT_THAT(err, HasSubstr("Failed to parse"));
 | |
| }
 | |
| 
 | |
| TEST(ParseTime, InfiniteTime) {
 | |
|   absl::Time t;
 | |
|   std::string err;
 | |
|   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-future", &t, &err));
 | |
|   EXPECT_EQ(absl::InfiniteFuture(), t);
 | |
| 
 | |
|   // Surrounding whitespace.
 | |
|   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "  infinite-future", &t, &err));
 | |
|   EXPECT_EQ(absl::InfiniteFuture(), t);
 | |
|   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-future  ", &t, &err));
 | |
|   EXPECT_EQ(absl::InfiniteFuture(), t);
 | |
|   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "  infinite-future  ", &t, &err));
 | |
|   EXPECT_EQ(absl::InfiniteFuture(), t);
 | |
| 
 | |
|   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-past", &t, &err));
 | |
|   EXPECT_EQ(absl::InfinitePast(), t);
 | |
| 
 | |
|   // Surrounding whitespace.
 | |
|   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "  infinite-past", &t, &err));
 | |
|   EXPECT_EQ(absl::InfinitePast(), t);
 | |
|   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-past  ", &t, &err));
 | |
|   EXPECT_EQ(absl::InfinitePast(), t);
 | |
|   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "  infinite-past  ", &t, &err));
 | |
|   EXPECT_EQ(absl::InfinitePast(), t);
 | |
| 
 | |
|   // "infinite-future" as literal std::string
 | |
|   absl::TimeZone tz = absl::UTCTimeZone();
 | |
|   EXPECT_TRUE(absl::ParseTime("infinite-future %H:%M", "infinite-future 03:04",
 | |
|                               &t, &err));
 | |
|   EXPECT_NE(absl::InfiniteFuture(), t);
 | |
|   EXPECT_EQ(3, tz.At(t).cs.hour());
 | |
|   EXPECT_EQ(4, tz.At(t).cs.minute());
 | |
| 
 | |
|   // "infinite-past" as literal std::string
 | |
|   EXPECT_TRUE(
 | |
|       absl::ParseTime("infinite-past %H:%M", "infinite-past 03:04", &t, &err));
 | |
|   EXPECT_NE(absl::InfinitePast(), t);
 | |
|   EXPECT_EQ(3, tz.At(t).cs.hour());
 | |
|   EXPECT_EQ(4, tz.At(t).cs.minute());
 | |
| 
 | |
|   // The input doesn't match the format.
 | |
|   EXPECT_FALSE(absl::ParseTime("infinite-future %H:%M", "03:04", &t, &err));
 | |
|   EXPECT_FALSE(absl::ParseTime("infinite-past %H:%M", "03:04", &t, &err));
 | |
| }
 | |
| 
 | |
| TEST(ParseTime, FailsOnUnrepresentableTime) {
 | |
|   const absl::TimeZone utc = absl::UTCTimeZone();
 | |
|   absl::Time t;
 | |
|   EXPECT_FALSE(
 | |
|       absl::ParseTime("%Y-%m-%d", "-292277022657-01-27", utc, &t, nullptr));
 | |
|   EXPECT_TRUE(
 | |
|       absl::ParseTime("%Y-%m-%d", "-292277022657-01-28", utc, &t, nullptr));
 | |
|   EXPECT_TRUE(
 | |
|       absl::ParseTime("%Y-%m-%d", "292277026596-12-04", utc, &t, nullptr));
 | |
|   EXPECT_FALSE(
 | |
|       absl::ParseTime("%Y-%m-%d", "292277026596-12-05", utc, &t, nullptr));
 | |
| }
 | |
| 
 | |
| //
 | |
| // Roundtrip test for FormatTime()/ParseTime().
 | |
| //
 | |
| 
 | |
| TEST(FormatParse, RoundTrip) {
 | |
|   const absl::TimeZone lax =
 | |
|       absl::time_internal::LoadTimeZone("America/Los_Angeles");
 | |
|   const absl::Time in =
 | |
|       absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax);
 | |
|   const absl::Duration subseconds = absl::Nanoseconds(654321);
 | |
|   std::string err;
 | |
| 
 | |
|   // RFC3339, which renders subseconds.
 | |
|   {
 | |
|     absl::Time out;
 | |
|     const std::string s =
 | |
|         absl::FormatTime(absl::RFC3339_full, in + subseconds, lax);
 | |
|     EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
 | |
|         << s << ": " << err;
 | |
|     EXPECT_EQ(in + subseconds, out);  // RFC3339_full includes %Ez
 | |
|   }
 | |
| 
 | |
|   // RFC1123, which only does whole seconds.
 | |
|   {
 | |
|     absl::Time out;
 | |
|     const std::string s = absl::FormatTime(absl::RFC1123_full, in, lax);
 | |
|     EXPECT_TRUE(absl::ParseTime(absl::RFC1123_full, s, &out, &err))
 | |
|         << s << ": " << err;
 | |
|     EXPECT_EQ(in, out);  // RFC1123_full includes %z
 | |
|   }
 | |
| 
 | |
|   // `absl::FormatTime()` falls back to strftime() for "%c", which appears to
 | |
|   // work. On Windows, `absl::ParseTime()` falls back to std::get_time() which
 | |
|   // appears to fail on "%c" (or at least on the "%c" text produced by
 | |
|   // `strftime()`). This makes it fail the round-trip test.
 | |
|   //
 | |
|   // Under the emscripten compiler `absl::ParseTime() falls back to
 | |
|   // `strptime()`, but that ends up using a different definition for "%c"
 | |
|   // compared to `strftime()`, also causing the round-trip test to fail
 | |
|   // (see https://github.com/kripken/emscripten/pull/7491).
 | |
| #if !defined(_MSC_VER) && !defined(__EMSCRIPTEN__)
 | |
|   // Even though we don't know what %c will produce, it should roundtrip,
 | |
|   // but only in the 0-offset timezone.
 | |
|   {
 | |
|     absl::Time out;
 | |
|     const std::string s = absl::FormatTime("%c", in, absl::UTCTimeZone());
 | |
|     EXPECT_TRUE(absl::ParseTime("%c", s, &out, &err)) << s << ": " << err;
 | |
|     EXPECT_EQ(in, out);
 | |
|   }
 | |
| #endif  // !_MSC_VER && !__EMSCRIPTEN__
 | |
| }
 | |
| 
 | |
| TEST(FormatParse, RoundTripDistantFuture) {
 | |
|   const absl::TimeZone tz = absl::UTCTimeZone();
 | |
|   const absl::Time in =
 | |
|       absl::FromUnixSeconds(std::numeric_limits<int64_t>::max());
 | |
|   std::string err;
 | |
| 
 | |
|   absl::Time out;
 | |
|   const std::string s = absl::FormatTime(absl::RFC3339_full, in, tz);
 | |
|   EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
 | |
|       << s << ": " << err;
 | |
|   EXPECT_EQ(in, out);
 | |
| }
 | |
| 
 | |
| TEST(FormatParse, RoundTripDistantPast) {
 | |
|   const absl::TimeZone tz = absl::UTCTimeZone();
 | |
|   const absl::Time in =
 | |
|       absl::FromUnixSeconds(std::numeric_limits<int64_t>::min());
 | |
|   std::string err;
 | |
| 
 | |
|   absl::Time out;
 | |
|   const std::string s = absl::FormatTime(absl::RFC3339_full, in, tz);
 | |
|   EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
 | |
|       << s << ": " << err;
 | |
|   EXPECT_EQ(in, out);
 | |
| }
 | |
| 
 | |
| }  // namespace
 |