Clarify formatting rules in absl::ParseCivilTime() PiperOrigin-RevId: 943928226 Change-Id: Ib19cfff23254e90d92bb97f34c11363c774c5cb6
diff --git a/absl/time/civil_time.h b/absl/time/civil_time.h index d198eba..d1d0d95 100644 --- a/absl/time/civil_time.h +++ b/absl/time/civil_time.h
@@ -509,6 +509,13 @@ // absl::CivilDay d; // bool ok = absl::ParseCivilTime("2018-01-02", &d); // OK // +// Parsing tolerates the following variations from the standard format: +// * Leading and trailing whitespace is ignored. +// * The year component may be negative (prefixed with '-') and may contain +// an arbitrary number of digits. +// * Sub-year components (month, day, hour, minute, second) may consist of +// either one or two digits. +// // Note that parsing will fail if the string's format does not match the // expected type exactly. `ParseLenientCivilTime()` below is more lenient. // @@ -521,9 +528,12 @@ // ParseLenientCivilTime() // -// Parses any of the formats accepted by `absl::ParseCivilTime()`, but is more -// lenient if the format of the string does not exactly match the associated -// type. +// Parses any of the formats accepted by `absl::ParseCivilTime()`. Unlike +// `ParseCivilTime()`, the input string format does not need to match the +// target civil-time type. Discrepancies are resolved as follows: +// * Extra components in the input string are ignored. +// * Missing components are defaulted to their minimum valid values. +// This behavior is consistent with civil-time converting constructors. // // Example: //
diff --git a/absl/time/civil_time_test.cc b/absl/time/civil_time_test.cc index 59c04d3..b1e1f39 100644 --- a/absl/time/civil_time_test.cc +++ b/absl/time/civil_time_test.cc
@@ -749,7 +749,7 @@ EXPECT_EQ("2015", absl::FormatCivilTime(y)); } -TEST(CivilTime, ParseEdgeCases) { +TEST(CivilTime, ParseLenientEdgeCases) { absl::CivilSecond ss; EXPECT_TRUE( absl::ParseLenientCivilTime("9223372036854775807-12-31T23:59:59", &ss)); @@ -825,6 +825,33 @@ EXPECT_FALSE(absl::ParseLenientCivilTime("9223372036854775808", &y)) << y; } +TEST(CivilTime, ParseEdgeCases) { + absl::CivilYear y; + absl::CivilMonth m; + absl::CivilDay d; + absl::CivilSecond ss; + EXPECT_TRUE(absl::ParseCivilTime("0", &y)) << y; + EXPECT_EQ(absl::CivilYear(0), y); + EXPECT_TRUE(absl::ParseCivilTime("0-1", &m)) << m; + EXPECT_EQ(absl::CivilMonth(0, 1), m); + EXPECT_TRUE(absl::ParseCivilTime(" 2015 ", &y)) << y; + EXPECT_EQ(absl::CivilYear(2015), y); + EXPECT_TRUE(absl::ParseCivilTime( + "000000000000000000000000000000000000000000000000000000000000002015", &y)) + << y; + EXPECT_EQ(absl::CivilYear(2015), y); + EXPECT_TRUE(absl::ParseCivilTime(" 2015-6 ", &m)) << m; + EXPECT_EQ(absl::CivilMonth(2015, 6), m); + EXPECT_TRUE(absl::ParseCivilTime("0002015-6-7", &d)) << d; + EXPECT_EQ(absl::CivilDay(2015, 6, 7), d); + EXPECT_TRUE(absl::ParseCivilTime("2015-06-07T10:11:12 ", &ss)) << ss; + EXPECT_EQ(absl::CivilSecond(2015, 6, 7, 10, 11, 12), ss); + EXPECT_TRUE(absl::ParseCivilTime(" 2015-06-07T10:11:1 ", &ss)) << ss; + EXPECT_EQ(absl::CivilSecond(2015, 6, 7, 10, 11, 1), ss); + EXPECT_TRUE(absl::ParseCivilTime("-01-01", &m)) << m; + EXPECT_EQ(absl::CivilMonth(-1, 1), m); +} + TEST(CivilTime, AbslStringify) { EXPECT_EQ("2015-01-02T03:04:05", absl::StrFormat("%v", absl::CivilSecond(2015, 1, 2, 3, 4, 5)));