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)));