civil_time.h (22736B)
1 // Copyright 2018 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // ----------------------------------------------------------------------------- 16 // File: civil_time.h 17 // ----------------------------------------------------------------------------- 18 // 19 // This header file defines abstractions for computing with "civil time". 20 // The term "civil time" refers to the legally recognized human-scale time 21 // that is represented by the six fields `YYYY-MM-DD hh:mm:ss`. A "date" 22 // is perhaps the most common example of a civil time (represented here as 23 // an `absl::CivilDay`). 24 // 25 // Modern-day civil time follows the Gregorian Calendar and is a 26 // time-zone-independent concept: a civil time of "2015-06-01 12:00:00", for 27 // example, is not tied to a time zone. Put another way, a civil time does not 28 // map to a unique point in time; a civil time must be mapped to an absolute 29 // time *through* a time zone. 30 // 31 // Because a civil time is what most people think of as "time," it is common to 32 // map absolute times to civil times to present to users. 33 // 34 // Time zones define the relationship between absolute and civil times. Given an 35 // absolute or civil time and a time zone, you can compute the other time: 36 // 37 // Civil Time = F(Absolute Time, Time Zone) 38 // Absolute Time = G(Civil Time, Time Zone) 39 // 40 // The Abseil time library allows you to construct such civil times from 41 // absolute times; consult time.h for such functionality. 42 // 43 // This library provides six classes for constructing civil-time objects, and 44 // provides several helper functions for rounding, iterating, and performing 45 // arithmetic on civil-time objects, while avoiding complications like 46 // daylight-saving time (DST): 47 // 48 // * `absl::CivilSecond` 49 // * `absl::CivilMinute` 50 // * `absl::CivilHour` 51 // * `absl::CivilDay` 52 // * `absl::CivilMonth` 53 // * `absl::CivilYear` 54 // 55 // Example: 56 // 57 // // Construct a civil-time object for a specific day 58 // const absl::CivilDay cd(1969, 7, 20); 59 // 60 // // Construct a civil-time object for a specific second 61 // const absl::CivilSecond cd(2018, 8, 1, 12, 0, 1); 62 // 63 // Note: In C++14 and later, this library is usable in a constexpr context. 64 // 65 // Example: 66 // 67 // // Valid in C++14 68 // constexpr absl::CivilDay cd(1969, 7, 20); 69 70 #ifndef ABSL_TIME_CIVIL_TIME_H_ 71 #define ABSL_TIME_CIVIL_TIME_H_ 72 73 #include <iosfwd> 74 #include <string> 75 76 #include "absl/base/config.h" 77 #include "absl/strings/string_view.h" 78 #include "absl/time/internal/cctz/include/cctz/civil_time.h" 79 80 namespace absl { 81 ABSL_NAMESPACE_BEGIN 82 83 namespace time_internal { 84 struct second_tag : cctz::detail::second_tag {}; 85 struct minute_tag : second_tag, cctz::detail::minute_tag {}; 86 struct hour_tag : minute_tag, cctz::detail::hour_tag {}; 87 struct day_tag : hour_tag, cctz::detail::day_tag {}; 88 struct month_tag : day_tag, cctz::detail::month_tag {}; 89 struct year_tag : month_tag, cctz::detail::year_tag {}; 90 } // namespace time_internal 91 92 // ----------------------------------------------------------------------------- 93 // CivilSecond, CivilMinute, CivilHour, CivilDay, CivilMonth, CivilYear 94 // ----------------------------------------------------------------------------- 95 // 96 // Each of these civil-time types is a simple value type with the same 97 // interface for construction and the same six accessors for each of the civil 98 // time fields (year, month, day, hour, minute, and second, aka YMDHMS). These 99 // classes differ only in their alignment, which is indicated by the type name 100 // and specifies the field on which arithmetic operates. 101 // 102 // CONSTRUCTION 103 // 104 // Each of the civil-time types can be constructed in two ways: by directly 105 // passing to the constructor up to six integers representing the YMDHMS fields, 106 // or by copying the YMDHMS fields from a differently aligned civil-time type. 107 // Omitted fields are assigned their minimum valid value. Hours, minutes, and 108 // seconds will be set to 0, month and day will be set to 1. Since there is no 109 // minimum year, the default is 1970. 110 // 111 // Examples: 112 // 113 // absl::CivilDay default_value; // 1970-01-01 00:00:00 114 // 115 // absl::CivilDay a(2015, 2, 3); // 2015-02-03 00:00:00 116 // absl::CivilDay b(2015, 2, 3, 4, 5, 6); // 2015-02-03 00:00:00 117 // absl::CivilDay c(2015); // 2015-01-01 00:00:00 118 // 119 // absl::CivilSecond ss(2015, 2, 3, 4, 5, 6); // 2015-02-03 04:05:06 120 // absl::CivilMinute mm(ss); // 2015-02-03 04:05:00 121 // absl::CivilHour hh(mm); // 2015-02-03 04:00:00 122 // absl::CivilDay d(hh); // 2015-02-03 00:00:00 123 // absl::CivilMonth m(d); // 2015-02-01 00:00:00 124 // absl::CivilYear y(m); // 2015-01-01 00:00:00 125 // 126 // m = absl::CivilMonth(y); // 2015-01-01 00:00:00 127 // d = absl::CivilDay(m); // 2015-01-01 00:00:00 128 // hh = absl::CivilHour(d); // 2015-01-01 00:00:00 129 // mm = absl::CivilMinute(hh); // 2015-01-01 00:00:00 130 // ss = absl::CivilSecond(mm); // 2015-01-01 00:00:00 131 // 132 // Each civil-time class is aligned to the civil-time field indicated in the 133 // class's name after normalization. Alignment is performed by setting all the 134 // inferior fields to their minimum valid value (as described above). The 135 // following are examples of how each of the six types would align the fields 136 // representing November 22, 2015 at 12:34:56 in the afternoon. (Note: the 137 // string format used here is not important; it's just a shorthand way of 138 // showing the six YMDHMS fields.) 139 // 140 // absl::CivilSecond : 2015-11-22 12:34:56 141 // absl::CivilMinute : 2015-11-22 12:34:00 142 // absl::CivilHour : 2015-11-22 12:00:00 143 // absl::CivilDay : 2015-11-22 00:00:00 144 // absl::CivilMonth : 2015-11-01 00:00:00 145 // absl::CivilYear : 2015-01-01 00:00:00 146 // 147 // Each civil-time type performs arithmetic on the field to which it is 148 // aligned. This means that adding 1 to an absl::CivilDay increments the day 149 // field (normalizing as necessary), and subtracting 7 from an absl::CivilMonth 150 // operates on the month field (normalizing as necessary). All arithmetic 151 // produces a valid civil time. Difference requires two similarly aligned 152 // civil-time objects and returns the scalar answer in units of the objects' 153 // alignment. For example, the difference between two absl::CivilHour objects 154 // will give an answer in units of civil hours. 155 // 156 // ALIGNMENT CONVERSION 157 // 158 // The alignment of a civil-time object cannot change, but the object may be 159 // used to construct a new object with a different alignment. This is referred 160 // to as "realigning". When realigning to a type with the same or more 161 // precision (e.g., absl::CivilDay -> absl::CivilSecond), the conversion may be 162 // performed implicitly since no information is lost. However, if information 163 // could be discarded (e.g., CivilSecond -> CivilDay), the conversion must 164 // be explicit at the call site. 165 // 166 // Examples: 167 // 168 // void UseDay(absl::CivilDay day); 169 // 170 // absl::CivilSecond cs; 171 // UseDay(cs); // Won't compile because data may be discarded 172 // UseDay(absl::CivilDay(cs)); // OK: explicit conversion 173 // 174 // absl::CivilDay cd; 175 // UseDay(cd); // OK: no conversion needed 176 // 177 // absl::CivilMonth cm; 178 // UseDay(cm); // OK: implicit conversion to absl::CivilDay 179 // 180 // NORMALIZATION 181 // 182 // Normalization takes invalid values and adjusts them to produce valid values. 183 // Within the civil-time library, integer arguments passed to the Civil* 184 // constructors may be out-of-range, in which case they are normalized by 185 // carrying overflow into a field of courser granularity to produce valid 186 // civil-time objects. This normalization enables natural arithmetic on 187 // constructor arguments without worrying about the field's range. 188 // 189 // Examples: 190 // 191 // // Out-of-range; normalized to 2016-11-01 192 // absl::CivilDay d(2016, 10, 32); 193 // // Out-of-range, negative: normalized to 2016-10-30T23 194 // absl::CivilHour h1(2016, 10, 31, -1); 195 // // Normalization is cumulative: normalized to 2016-10-30T23 196 // absl::CivilHour h2(2016, 10, 32, -25); 197 // 198 // Note: If normalization is undesired, you can signal an error by comparing 199 // the constructor arguments to the normalized values returned by the YMDHMS 200 // properties. 201 // 202 // COMPARISON 203 // 204 // Comparison between civil-time objects considers all six YMDHMS fields, 205 // regardless of the type's alignment. Comparison between differently aligned 206 // civil-time types is allowed. 207 // 208 // Examples: 209 // 210 // absl::CivilDay feb_3(2015, 2, 3); // 2015-02-03 00:00:00 211 // absl::CivilDay mar_4(2015, 3, 4); // 2015-03-04 00:00:00 212 // // feb_3 < mar_4 213 // // absl::CivilYear(feb_3) == absl::CivilYear(mar_4) 214 // 215 // absl::CivilSecond feb_3_noon(2015, 2, 3, 12, 0, 0); // 2015-02-03 12:00:00 216 // // feb_3 < feb_3_noon 217 // // feb_3 == absl::CivilDay(feb_3_noon) 218 // 219 // // Iterates all the days of February 2015. 220 // for (absl::CivilDay d(2015, 2, 1); d < absl::CivilMonth(2015, 3); ++d) { 221 // // ... 222 // } 223 // 224 // ARITHMETIC 225 // 226 // Civil-time types support natural arithmetic operators such as addition, 227 // subtraction, and difference. Arithmetic operates on the civil-time field 228 // indicated in the type's name. Difference operators require arguments with 229 // the same alignment and return the answer in units of the alignment. 230 // 231 // Example: 232 // 233 // absl::CivilDay a(2015, 2, 3); 234 // ++a; // 2015-02-04 00:00:00 235 // --a; // 2015-02-03 00:00:00 236 // absl::CivilDay b = a + 1; // 2015-02-04 00:00:00 237 // absl::CivilDay c = 1 + b; // 2015-02-05 00:00:00 238 // int n = c - a; // n = 2 (civil days) 239 // int m = c - absl::CivilMonth(c); // Won't compile: different types. 240 // 241 // ACCESSORS 242 // 243 // Each civil-time type has accessors for all six of the civil-time fields: 244 // year, month, day, hour, minute, and second. 245 // 246 // civil_year_t year() 247 // int month() 248 // int day() 249 // int hour() 250 // int minute() 251 // int second() 252 // 253 // Recall that fields inferior to the type's alignment will be set to their 254 // minimum valid value. 255 // 256 // Example: 257 // 258 // absl::CivilDay d(2015, 6, 28); 259 // // d.year() == 2015 260 // // d.month() == 6 261 // // d.day() == 28 262 // // d.hour() == 0 263 // // d.minute() == 0 264 // // d.second() == 0 265 // 266 // CASE STUDY: Adding a month to January 31. 267 // 268 // One of the classic questions that arises when considering a civil time 269 // library (or a date library or a date/time library) is this: 270 // "What is the result of adding a month to January 31?" 271 // This is an interesting question because it is unclear what is meant by a 272 // "month", and several different answers are possible, depending on context: 273 // 274 // 1. March 3 (or 2 if a leap year), if "add a month" means to add a month to 275 // the current month, and adjust the date to overflow the extra days into 276 // March. In this case the result of "February 31" would be normalized as 277 // within the civil-time library. 278 // 2. February 28 (or 29 if a leap year), if "add a month" means to add a 279 // month, and adjust the date while holding the resulting month constant. 280 // In this case, the result of "February 31" would be truncated to the last 281 // day in February. 282 // 3. An error. The caller may get some error, an exception, an invalid date 283 // object, or perhaps return `false`. This may make sense because there is 284 // no single unambiguously correct answer to the question. 285 // 286 // Practically speaking, any answer that is not what the programmer intended 287 // is the wrong answer. 288 // 289 // The Abseil time library avoids this problem by making it impossible to 290 // ask ambiguous questions. All civil-time objects are aligned to a particular 291 // civil-field boundary (such as aligned to a year, month, day, hour, minute, 292 // or second), and arithmetic operates on the field to which the object is 293 // aligned. This means that in order to "add a month" the object must first be 294 // aligned to a month boundary, which is equivalent to the first day of that 295 // month. 296 // 297 // Of course, there are ways to compute an answer the question at hand using 298 // this Abseil time library, but they require the programmer to be explicit 299 // about the answer they expect. To illustrate, let's see how to compute all 300 // three of the above possible answers to the question of "Jan 31 plus 1 301 // month": 302 // 303 // Example: 304 // 305 // const absl::CivilDay d(2015, 1, 31); 306 // 307 // // Answer 1: 308 // // Add 1 to the month field in the constructor, and rely on normalization. 309 // const auto normalized = absl::CivilDay(d.year(), d.month() + 1, d.day()); 310 // // normalized == 2015-03-03 (aka Feb 31) 311 // 312 // // Answer 2: 313 // // Add 1 to month field, capping to the end of next month. 314 // const auto next_month = absl::CivilMonth(d) + 1; 315 // const auto last_day_of_next_month = absl::CivilDay(next_month + 1) - 1; 316 // const auto capped = std::min(normalized, last_day_of_next_month); 317 // // capped == 2015-02-28 318 // 319 // // Answer 3: 320 // // Signal an error if the normalized answer is not in next month. 321 // if (absl::CivilMonth(normalized) != next_month) { 322 // // error, month overflow 323 // } 324 // 325 using CivilSecond = 326 time_internal::cctz::detail::civil_time<time_internal::second_tag>; 327 using CivilMinute = 328 time_internal::cctz::detail::civil_time<time_internal::minute_tag>; 329 using CivilHour = 330 time_internal::cctz::detail::civil_time<time_internal::hour_tag>; 331 using CivilDay = 332 time_internal::cctz::detail::civil_time<time_internal::day_tag>; 333 using CivilMonth = 334 time_internal::cctz::detail::civil_time<time_internal::month_tag>; 335 using CivilYear = 336 time_internal::cctz::detail::civil_time<time_internal::year_tag>; 337 338 // civil_year_t 339 // 340 // Type alias of a civil-time year value. This type is guaranteed to (at least) 341 // support any year value supported by `time_t`. 342 // 343 // Example: 344 // 345 // absl::CivilSecond cs = ...; 346 // absl::civil_year_t y = cs.year(); 347 // cs = absl::CivilSecond(y, 1, 1, 0, 0, 0); // CivilSecond(CivilYear(cs)) 348 // 349 using civil_year_t = time_internal::cctz::year_t; 350 351 // civil_diff_t 352 // 353 // Type alias of the difference between two civil-time values. 354 // This type is used to indicate arguments that are not 355 // normalized (such as parameters to the civil-time constructors), the results 356 // of civil-time subtraction, or the operand to civil-time addition. 357 // 358 // Example: 359 // 360 // absl::civil_diff_t n_sec = cs1 - cs2; // cs1 == cs2 + n_sec; 361 // 362 using civil_diff_t = time_internal::cctz::diff_t; 363 364 // Weekday::monday, Weekday::tuesday, Weekday::wednesday, Weekday::thursday, 365 // Weekday::friday, Weekday::saturday, Weekday::sunday 366 // 367 // The Weekday enum class represents the civil-time concept of a "weekday" with 368 // members for all days of the week. 369 // 370 // absl::Weekday wd = absl::Weekday::thursday; 371 // 372 using Weekday = time_internal::cctz::weekday; 373 374 // GetWeekday() 375 // 376 // Returns the absl::Weekday for the given (realigned) civil-time value. 377 // 378 // Example: 379 // 380 // absl::CivilDay a(2015, 8, 13); 381 // absl::Weekday wd = absl::GetWeekday(a); // wd == absl::Weekday::thursday 382 // 383 inline Weekday GetWeekday(CivilSecond cs) { 384 return time_internal::cctz::get_weekday(cs); 385 } 386 387 // NextWeekday() 388 // PrevWeekday() 389 // 390 // Returns the absl::CivilDay that strictly follows or precedes a given 391 // absl::CivilDay, and that falls on the given absl::Weekday. 392 // 393 // Example, given the following month: 394 // 395 // August 2015 396 // Su Mo Tu We Th Fr Sa 397 // 1 398 // 2 3 4 5 6 7 8 399 // 9 10 11 12 13 14 15 400 // 16 17 18 19 20 21 22 401 // 23 24 25 26 27 28 29 402 // 30 31 403 // 404 // absl::CivilDay a(2015, 8, 13); 405 // // absl::GetWeekday(a) == absl::Weekday::thursday 406 // absl::CivilDay b = absl::NextWeekday(a, absl::Weekday::thursday); 407 // // b = 2015-08-20 408 // absl::CivilDay c = absl::PrevWeekday(a, absl::Weekday::thursday); 409 // // c = 2015-08-06 410 // 411 // absl::CivilDay d = ... 412 // // Gets the following Thursday if d is not already Thursday 413 // absl::CivilDay thurs1 = absl::NextWeekday(d - 1, absl::Weekday::thursday); 414 // // Gets the previous Thursday if d is not already Thursday 415 // absl::CivilDay thurs2 = absl::PrevWeekday(d + 1, absl::Weekday::thursday); 416 // 417 inline CivilDay NextWeekday(CivilDay cd, Weekday wd) { 418 return CivilDay(time_internal::cctz::next_weekday(cd, wd)); 419 } 420 inline CivilDay PrevWeekday(CivilDay cd, Weekday wd) { 421 return CivilDay(time_internal::cctz::prev_weekday(cd, wd)); 422 } 423 424 // GetYearDay() 425 // 426 // Returns the day-of-year for the given (realigned) civil-time value. 427 // 428 // Example: 429 // 430 // absl::CivilDay a(2015, 1, 1); 431 // int yd_jan_1 = absl::GetYearDay(a); // yd_jan_1 = 1 432 // absl::CivilDay b(2015, 12, 31); 433 // int yd_dec_31 = absl::GetYearDay(b); // yd_dec_31 = 365 434 // 435 inline int GetYearDay(CivilSecond cs) { 436 return time_internal::cctz::get_yearday(cs); 437 } 438 439 // FormatCivilTime() 440 // 441 // Formats the given civil-time value into a string value of the following 442 // format: 443 // 444 // Type | Format 445 // --------------------------------- 446 // CivilSecond | YYYY-MM-DDTHH:MM:SS 447 // CivilMinute | YYYY-MM-DDTHH:MM 448 // CivilHour | YYYY-MM-DDTHH 449 // CivilDay | YYYY-MM-DD 450 // CivilMonth | YYYY-MM 451 // CivilYear | YYYY 452 // 453 // Example: 454 // 455 // absl::CivilDay d = absl::CivilDay(1969, 7, 20); 456 // std::string day_string = absl::FormatCivilTime(d); // "1969-07-20" 457 // 458 std::string FormatCivilTime(CivilSecond c); 459 std::string FormatCivilTime(CivilMinute c); 460 std::string FormatCivilTime(CivilHour c); 461 std::string FormatCivilTime(CivilDay c); 462 std::string FormatCivilTime(CivilMonth c); 463 std::string FormatCivilTime(CivilYear c); 464 465 // Support for StrFormat(), StrCat(), etc 466 template <typename Sink> 467 void AbslStringify(Sink& sink, CivilSecond c) { 468 sink.Append(FormatCivilTime(c)); 469 } 470 template <typename Sink> 471 void AbslStringify(Sink& sink, CivilMinute c) { 472 sink.Append(FormatCivilTime(c)); 473 } 474 template <typename Sink> 475 void AbslStringify(Sink& sink, CivilHour c) { 476 sink.Append(FormatCivilTime(c)); 477 } 478 template <typename Sink> 479 void AbslStringify(Sink& sink, CivilDay c) { 480 sink.Append(FormatCivilTime(c)); 481 } 482 template <typename Sink> 483 void AbslStringify(Sink& sink, CivilMonth c) { 484 sink.Append(FormatCivilTime(c)); 485 } 486 template <typename Sink> 487 void AbslStringify(Sink& sink, CivilYear c) { 488 sink.Append(FormatCivilTime(c)); 489 } 490 491 // absl::ParseCivilTime() 492 // 493 // Parses a civil-time value from the specified `absl::string_view` into the 494 // passed output parameter. Returns `true` upon successful parsing. 495 // 496 // The expected form of the input string is as follows: 497 // 498 // Type | Format 499 // --------------------------------- 500 // CivilSecond | YYYY-MM-DDTHH:MM:SS 501 // CivilMinute | YYYY-MM-DDTHH:MM 502 // CivilHour | YYYY-MM-DDTHH 503 // CivilDay | YYYY-MM-DD 504 // CivilMonth | YYYY-MM 505 // CivilYear | YYYY 506 // 507 // Example: 508 // 509 // absl::CivilDay d; 510 // bool ok = absl::ParseCivilTime("2018-01-02", &d); // OK 511 // 512 // Note that parsing will fail if the string's format does not match the 513 // expected type exactly. `ParseLenientCivilTime()` below is more lenient. 514 // 515 bool ParseCivilTime(absl::string_view s, CivilSecond* c); 516 bool ParseCivilTime(absl::string_view s, CivilMinute* c); 517 bool ParseCivilTime(absl::string_view s, CivilHour* c); 518 bool ParseCivilTime(absl::string_view s, CivilDay* c); 519 bool ParseCivilTime(absl::string_view s, CivilMonth* c); 520 bool ParseCivilTime(absl::string_view s, CivilYear* c); 521 522 // ParseLenientCivilTime() 523 // 524 // Parses any of the formats accepted by `absl::ParseCivilTime()`, but is more 525 // lenient if the format of the string does not exactly match the associated 526 // type. 527 // 528 // Example: 529 // 530 // absl::CivilDay d; 531 // bool ok = absl::ParseLenientCivilTime("1969-07-20", &d); // OK 532 // ok = absl::ParseLenientCivilTime("1969-07-20T10", &d); // OK: T10 floored 533 // ok = absl::ParseLenientCivilTime("1969-07", &d); // OK: day defaults to 1 534 // 535 bool ParseLenientCivilTime(absl::string_view s, CivilSecond* c); 536 bool ParseLenientCivilTime(absl::string_view s, CivilMinute* c); 537 bool ParseLenientCivilTime(absl::string_view s, CivilHour* c); 538 bool ParseLenientCivilTime(absl::string_view s, CivilDay* c); 539 bool ParseLenientCivilTime(absl::string_view s, CivilMonth* c); 540 bool ParseLenientCivilTime(absl::string_view s, CivilYear* c); 541 542 namespace time_internal { // For functions found via ADL on civil-time tags. 543 544 // Streaming Operators 545 // 546 // Each civil-time type may be sent to an output stream using operator<<(). 547 // The result matches the string produced by `FormatCivilTime()`. 548 // 549 // Example: 550 // 551 // absl::CivilDay d = absl::CivilDay(1969, 7, 20); 552 // std::cout << "Date is: " << d << "\n"; 553 // 554 std::ostream& operator<<(std::ostream& os, CivilYear y); 555 std::ostream& operator<<(std::ostream& os, CivilMonth m); 556 std::ostream& operator<<(std::ostream& os, CivilDay d); 557 std::ostream& operator<<(std::ostream& os, CivilHour h); 558 std::ostream& operator<<(std::ostream& os, CivilMinute m); 559 std::ostream& operator<<(std::ostream& os, CivilSecond s); 560 561 // AbslParseFlag() 562 // 563 // Parses the command-line flag string representation `s` into a civil-time 564 // value. Flags must be specified in a format that is valid for 565 // `absl::ParseLenientCivilTime()`. 566 bool AbslParseFlag(absl::string_view s, CivilSecond* c, std::string* error); 567 bool AbslParseFlag(absl::string_view s, CivilMinute* c, std::string* error); 568 bool AbslParseFlag(absl::string_view s, CivilHour* c, std::string* error); 569 bool AbslParseFlag(absl::string_view s, CivilDay* c, std::string* error); 570 bool AbslParseFlag(absl::string_view s, CivilMonth* c, std::string* error); 571 bool AbslParseFlag(absl::string_view s, CivilYear* c, std::string* error); 572 573 // AbslUnparseFlag() 574 // 575 // Unparses a civil-time value into a command-line string representation using 576 // the format specified by `absl::ParseCivilTime()`. 577 std::string AbslUnparseFlag(CivilSecond c); 578 std::string AbslUnparseFlag(CivilMinute c); 579 std::string AbslUnparseFlag(CivilHour c); 580 std::string AbslUnparseFlag(CivilDay c); 581 std::string AbslUnparseFlag(CivilMonth c); 582 std::string AbslUnparseFlag(CivilYear c); 583 584 } // namespace time_internal 585 586 ABSL_NAMESPACE_END 587 } // namespace absl 588 589 #endif // ABSL_TIME_CIVIL_TIME_H_