time_zone_format_test.cc
Go to the documentation of this file.
00001 // Copyright 2016 Google Inc. All Rights Reserved.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //   https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 //   Unless required by applicable law or agreed to in writing, software
00010 //   distributed under the License is distributed on an "AS IS" BASIS,
00011 //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 //   See the License for the specific language governing permissions and
00013 //   limitations under the License.
00014 
00015 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
00016 
00017 #include <chrono>
00018 #include <iomanip>
00019 #include <sstream>
00020 #include <string>
00021 
00022 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
00023 #include "gmock/gmock.h"
00024 #include "gtest/gtest.h"
00025 
00026 namespace chrono = std::chrono;
00027 
00028 namespace absl {
00029 namespace time_internal {
00030 namespace cctz {
00031 
00032 namespace {
00033 
00034 // This helper is a macro so that failed expectations show up with the
00035 // correct line numbers.
00036 #define ExpectTime(tp, tz, y, m, d, hh, mm, ss, off, isdst, zone) \
00037   do {                                                            \
00038     time_zone::absolute_lookup al = tz.lookup(tp);                \
00039     EXPECT_EQ(y, al.cs.year());                                   \
00040     EXPECT_EQ(m, al.cs.month());                                  \
00041     EXPECT_EQ(d, al.cs.day());                                    \
00042     EXPECT_EQ(hh, al.cs.hour());                                  \
00043     EXPECT_EQ(mm, al.cs.minute());                                \
00044     EXPECT_EQ(ss, al.cs.second());                                \
00045     EXPECT_EQ(off, al.offset);                                    \
00046     EXPECT_TRUE(isdst == al.is_dst);                              \
00047     EXPECT_STREQ(zone, al.abbr);                                  \
00048   } while (0)
00049 
00050 const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
00051 const char RFC3339_sec[] =  "%Y-%m-%dT%H:%M:%S%Ez";
00052 
00053 const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z";
00054 const char RFC1123_no_wday[] =  "%d %b %Y %H:%M:%S %z";
00055 
00056 // A helper that tests the given format specifier by itself, and with leading
00057 // and trailing characters.  For example: TestFormatSpecifier(tp, "%a", "Thu").
00058 template <typename D>
00059 void TestFormatSpecifier(time_point<D> tp, time_zone tz, const std::string& fmt,
00060                          const std::string& ans) {
00061   EXPECT_EQ(ans, format(fmt, tp, tz)) << fmt;
00062   EXPECT_EQ("xxx " + ans, format("xxx " + fmt, tp, tz));
00063   EXPECT_EQ(ans + " yyy", format(fmt + " yyy", tp, tz));
00064   EXPECT_EQ("xxx " + ans + " yyy", format("xxx " + fmt + " yyy", tp, tz));
00065 }
00066 
00067 }  // namespace
00068 
00069 //
00070 // Testing format()
00071 //
00072 
00073 TEST(Format, TimePointResolution) {
00074   const char kFmt[] = "%H:%M:%E*S";
00075   const time_zone utc = utc_time_zone();
00076   const time_point<chrono::nanoseconds> t0 =
00077       chrono::system_clock::from_time_t(1420167845) +
00078       chrono::milliseconds(123) + chrono::microseconds(456) +
00079       chrono::nanoseconds(789);
00080   EXPECT_EQ(
00081       "03:04:05.123456789",
00082       format(kFmt, chrono::time_point_cast<chrono::nanoseconds>(t0), utc));
00083   EXPECT_EQ(
00084       "03:04:05.123456",
00085       format(kFmt, chrono::time_point_cast<chrono::microseconds>(t0), utc));
00086   EXPECT_EQ(
00087       "03:04:05.123",
00088       format(kFmt, chrono::time_point_cast<chrono::milliseconds>(t0), utc));
00089   EXPECT_EQ("03:04:05",
00090             format(kFmt, chrono::time_point_cast<chrono::seconds>(t0), utc));
00091   EXPECT_EQ("03:04:05",
00092             format(kFmt, chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0), utc));
00093   EXPECT_EQ("03:04:00",
00094             format(kFmt, chrono::time_point_cast<chrono::minutes>(t0), utc));
00095   EXPECT_EQ("03:00:00",
00096             format(kFmt, chrono::time_point_cast<chrono::hours>(t0), utc));
00097 }
00098 
00099 TEST(Format, TimePointExtendedResolution) {
00100   const char kFmt[] = "%H:%M:%E*S";
00101   const time_zone utc = utc_time_zone();
00102   const time_point<absl::time_internal::cctz::seconds> tp =
00103       chrono::time_point_cast<absl::time_internal::cctz::seconds>(
00104           chrono::system_clock::from_time_t(0)) +
00105       chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56);
00106 
00107   EXPECT_EQ(
00108       "12:34:56.123456789012345",
00109       detail::format(kFmt, tp, detail::femtoseconds(123456789012345), utc));
00110   EXPECT_EQ(
00111       "12:34:56.012345678901234",
00112       detail::format(kFmt, tp, detail::femtoseconds(12345678901234), utc));
00113   EXPECT_EQ(
00114       "12:34:56.001234567890123",
00115       detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc));
00116   EXPECT_EQ(
00117       "12:34:56.000123456789012",
00118       detail::format(kFmt, tp, detail::femtoseconds(123456789012), utc));
00119 
00120   EXPECT_EQ("12:34:56.000000000000123",
00121             detail::format(kFmt, tp, detail::femtoseconds(123), utc));
00122   EXPECT_EQ("12:34:56.000000000000012",
00123             detail::format(kFmt, tp, detail::femtoseconds(12), utc));
00124   EXPECT_EQ("12:34:56.000000000000001",
00125             detail::format(kFmt, tp, detail::femtoseconds(1), utc));
00126 }
00127 
00128 TEST(Format, Basics) {
00129   time_zone tz = utc_time_zone();
00130   time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);
00131 
00132   // Starts with a couple basic edge cases.
00133   EXPECT_EQ("", format("", tp, tz));
00134   EXPECT_EQ(" ", format(" ", tp, tz));
00135   EXPECT_EQ("  ", format("  ", tp, tz));
00136   EXPECT_EQ("xxx", format("xxx", tp, tz));
00137   std::string big(128, 'x');
00138   EXPECT_EQ(big, format(big, tp, tz));
00139   // Cause the 1024-byte buffer to grow.
00140   std::string bigger(100000, 'x');
00141   EXPECT_EQ(bigger, format(bigger, tp, tz));
00142 
00143   tp += chrono::hours(13) + chrono::minutes(4) + chrono::seconds(5);
00144   tp += chrono::milliseconds(6) + chrono::microseconds(7) +
00145         chrono::nanoseconds(8);
00146   EXPECT_EQ("1970-01-01", format("%Y-%m-%d", tp, tz));
00147   EXPECT_EQ("13:04:05", format("%H:%M:%S", tp, tz));
00148   EXPECT_EQ("13:04:05.006", format("%H:%M:%E3S", tp, tz));
00149   EXPECT_EQ("13:04:05.006007", format("%H:%M:%E6S", tp, tz));
00150   EXPECT_EQ("13:04:05.006007008", format("%H:%M:%E9S", tp, tz));
00151 }
00152 
00153 TEST(Format, PosixConversions) {
00154   const time_zone tz = utc_time_zone();
00155   auto tp = chrono::system_clock::from_time_t(0);
00156 
00157   TestFormatSpecifier(tp, tz, "%d", "01");
00158   TestFormatSpecifier(tp, tz, "%e", " 1");  // extension but internal support
00159   TestFormatSpecifier(tp, tz, "%H", "00");
00160   TestFormatSpecifier(tp, tz, "%I", "12");
00161   TestFormatSpecifier(tp, tz, "%j", "001");
00162   TestFormatSpecifier(tp, tz, "%m", "01");
00163   TestFormatSpecifier(tp, tz, "%M", "00");
00164   TestFormatSpecifier(tp, tz, "%S", "00");
00165   TestFormatSpecifier(tp, tz, "%U", "00");
00166 #if !defined(__EMSCRIPTEN__)
00167   TestFormatSpecifier(tp, tz, "%w", "4");  // 4=Thursday
00168 #endif
00169   TestFormatSpecifier(tp, tz, "%W", "00");
00170   TestFormatSpecifier(tp, tz, "%y", "70");
00171   TestFormatSpecifier(tp, tz, "%Y", "1970");
00172   TestFormatSpecifier(tp, tz, "%z", "+0000");
00173   TestFormatSpecifier(tp, tz, "%Z", "UTC");
00174   TestFormatSpecifier(tp, tz, "%%", "%");
00175 
00176 #if defined(__linux__)
00177   // SU/C99/TZ extensions
00178   TestFormatSpecifier(tp, tz, "%C", "19");
00179   TestFormatSpecifier(tp, tz, "%D", "01/01/70");
00180   TestFormatSpecifier(tp, tz, "%F", "1970-01-01");
00181   TestFormatSpecifier(tp, tz, "%g", "70");
00182   TestFormatSpecifier(tp, tz, "%G", "1970");
00183   TestFormatSpecifier(tp, tz, "%k", " 0");
00184   TestFormatSpecifier(tp, tz, "%l", "12");
00185   TestFormatSpecifier(tp, tz, "%n", "\n");
00186   TestFormatSpecifier(tp, tz, "%R", "00:00");
00187   TestFormatSpecifier(tp, tz, "%t", "\t");
00188   TestFormatSpecifier(tp, tz, "%T", "00:00:00");
00189   TestFormatSpecifier(tp, tz, "%u", "4");  // 4=Thursday
00190   TestFormatSpecifier(tp, tz, "%V", "01");
00191   TestFormatSpecifier(tp, tz, "%s", "0");
00192 #endif
00193 }
00194 
00195 TEST(Format, LocaleSpecific) {
00196   const time_zone tz = utc_time_zone();
00197   auto tp = chrono::system_clock::from_time_t(0);
00198 
00199   TestFormatSpecifier(tp, tz, "%a", "Thu");
00200   TestFormatSpecifier(tp, tz, "%A", "Thursday");
00201   TestFormatSpecifier(tp, tz, "%b", "Jan");
00202   TestFormatSpecifier(tp, tz, "%B", "January");
00203 
00204   // %c should at least produce the numeric year and time-of-day.
00205   const std::string s = format("%c", tp, utc_time_zone());
00206   EXPECT_THAT(s, testing::HasSubstr("1970"));
00207   EXPECT_THAT(s, testing::HasSubstr("00:00:00"));
00208 
00209   TestFormatSpecifier(tp, tz, "%p", "AM");
00210   TestFormatSpecifier(tp, tz, "%x", "01/01/70");
00211   TestFormatSpecifier(tp, tz, "%X", "00:00:00");
00212 
00213 #if defined(__linux__)
00214   // SU/C99/TZ extensions
00215   TestFormatSpecifier(tp, tz, "%h", "Jan");  // Same as %b
00216   TestFormatSpecifier(tp, tz, "%P", "am");
00217   TestFormatSpecifier(tp, tz, "%r", "12:00:00 AM");
00218 
00219   // Modified conversion specifiers %E_
00220   TestFormatSpecifier(tp, tz, "%Ec", "Thu Jan  1 00:00:00 1970");
00221   TestFormatSpecifier(tp, tz, "%EC", "19");
00222   TestFormatSpecifier(tp, tz, "%Ex", "01/01/70");
00223   TestFormatSpecifier(tp, tz, "%EX", "00:00:00");
00224   TestFormatSpecifier(tp, tz, "%Ey", "70");
00225   TestFormatSpecifier(tp, tz, "%EY", "1970");
00226 
00227   // Modified conversion specifiers %O_
00228   TestFormatSpecifier(tp, tz, "%Od", "01");
00229   TestFormatSpecifier(tp, tz, "%Oe", " 1");
00230   TestFormatSpecifier(tp, tz, "%OH", "00");
00231   TestFormatSpecifier(tp, tz, "%OI", "12");
00232   TestFormatSpecifier(tp, tz, "%Om", "01");
00233   TestFormatSpecifier(tp, tz, "%OM", "00");
00234   TestFormatSpecifier(tp, tz, "%OS", "00");
00235   TestFormatSpecifier(tp, tz, "%Ou", "4");  // 4=Thursday
00236   TestFormatSpecifier(tp, tz, "%OU", "00");
00237   TestFormatSpecifier(tp, tz, "%OV", "01");
00238   TestFormatSpecifier(tp, tz, "%Ow", "4");  // 4=Thursday
00239   TestFormatSpecifier(tp, tz, "%OW", "00");
00240   TestFormatSpecifier(tp, tz, "%Oy", "70");
00241 #endif
00242 }
00243 
00244 TEST(Format, Escaping) {
00245   const time_zone tz = utc_time_zone();
00246   auto tp = chrono::system_clock::from_time_t(0);
00247 
00248   TestFormatSpecifier(tp, tz, "%%", "%");
00249   TestFormatSpecifier(tp, tz, "%%a", "%a");
00250   TestFormatSpecifier(tp, tz, "%%b", "%b");
00251   TestFormatSpecifier(tp, tz, "%%Ea", "%Ea");
00252   TestFormatSpecifier(tp, tz, "%%Es", "%Es");
00253   TestFormatSpecifier(tp, tz, "%%E3S", "%E3S");
00254   TestFormatSpecifier(tp, tz, "%%OS", "%OS");
00255   TestFormatSpecifier(tp, tz, "%%O3S", "%O3S");
00256 
00257   // Multiple levels of escaping.
00258   TestFormatSpecifier(tp, tz, "%%%Y", "%1970");
00259   TestFormatSpecifier(tp, tz, "%%%E3S", "%00.000");
00260   TestFormatSpecifier(tp, tz, "%%%%E3S", "%%E3S");
00261 }
00262 
00263 TEST(Format, ExtendedSeconds) {
00264   const time_zone tz = utc_time_zone();
00265 
00266   // No subseconds.
00267   time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);
00268   tp += chrono::seconds(5);
00269   EXPECT_EQ("05", format("%E*S", tp, tz));
00270   EXPECT_EQ("05", format("%E0S", tp, tz));
00271   EXPECT_EQ("05.0", format("%E1S", tp, tz));
00272   EXPECT_EQ("05.00", format("%E2S", tp, tz));
00273   EXPECT_EQ("05.000", format("%E3S", tp, tz));
00274   EXPECT_EQ("05.0000", format("%E4S", tp, tz));
00275   EXPECT_EQ("05.00000", format("%E5S", tp, tz));
00276   EXPECT_EQ("05.000000", format("%E6S", tp, tz));
00277   EXPECT_EQ("05.0000000", format("%E7S", tp, tz));
00278   EXPECT_EQ("05.00000000", format("%E8S", tp, tz));
00279   EXPECT_EQ("05.000000000", format("%E9S", tp, tz));
00280   EXPECT_EQ("05.0000000000", format("%E10S", tp, tz));
00281   EXPECT_EQ("05.00000000000", format("%E11S", tp, tz));
00282   EXPECT_EQ("05.000000000000", format("%E12S", tp, tz));
00283   EXPECT_EQ("05.0000000000000", format("%E13S", tp, tz));
00284   EXPECT_EQ("05.00000000000000", format("%E14S", tp, tz));
00285   EXPECT_EQ("05.000000000000000", format("%E15S", tp, tz));
00286 
00287   // With subseconds.
00288   tp += chrono::milliseconds(6) + chrono::microseconds(7) +
00289         chrono::nanoseconds(8);
00290   EXPECT_EQ("05.006007008", format("%E*S", tp, tz));
00291   EXPECT_EQ("05", format("%E0S", tp, tz));
00292   EXPECT_EQ("05.0", format("%E1S", tp, tz));
00293   EXPECT_EQ("05.00", format("%E2S", tp, tz));
00294   EXPECT_EQ("05.006", format("%E3S", tp, tz));
00295   EXPECT_EQ("05.0060", format("%E4S", tp, tz));
00296   EXPECT_EQ("05.00600", format("%E5S", tp, tz));
00297   EXPECT_EQ("05.006007", format("%E6S", tp, tz));
00298   EXPECT_EQ("05.0060070", format("%E7S", tp, tz));
00299   EXPECT_EQ("05.00600700", format("%E8S", tp, tz));
00300   EXPECT_EQ("05.006007008", format("%E9S", tp, tz));
00301   EXPECT_EQ("05.0060070080", format("%E10S", tp, tz));
00302   EXPECT_EQ("05.00600700800", format("%E11S", tp, tz));
00303   EXPECT_EQ("05.006007008000", format("%E12S", tp, tz));
00304   EXPECT_EQ("05.0060070080000", format("%E13S", tp, tz));
00305   EXPECT_EQ("05.00600700800000", format("%E14S", tp, tz));
00306   EXPECT_EQ("05.006007008000000", format("%E15S", tp, tz));
00307 
00308   // Times before the Unix epoch.
00309   tp = chrono::system_clock::from_time_t(0) + chrono::microseconds(-1);
00310   EXPECT_EQ("1969-12-31 23:59:59.999999",
00311             format("%Y-%m-%d %H:%M:%E*S", tp, tz));
00312 
00313   // Here is a "%E*S" case we got wrong for a while.  While the first
00314   // instant below is correctly rendered as "...:07.333304", the second
00315   // one used to appear as "...:07.33330499999999999".
00316   tp = chrono::system_clock::from_time_t(0) +
00317        chrono::microseconds(1395024427333304);
00318   EXPECT_EQ("2014-03-17 02:47:07.333304",
00319             format("%Y-%m-%d %H:%M:%E*S", tp, tz));
00320   tp += chrono::microseconds(1);
00321   EXPECT_EQ("2014-03-17 02:47:07.333305",
00322             format("%Y-%m-%d %H:%M:%E*S", tp, tz));
00323 }
00324 
00325 TEST(Format, ExtendedSubeconds) {
00326   const time_zone tz = utc_time_zone();
00327 
00328   // No subseconds.
00329   time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);
00330   tp += chrono::seconds(5);
00331   EXPECT_EQ("0", format("%E*f", tp, tz));
00332   EXPECT_EQ("", format("%E0f", tp, tz));
00333   EXPECT_EQ("0", format("%E1f", tp, tz));
00334   EXPECT_EQ("00", format("%E2f", tp, tz));
00335   EXPECT_EQ("000", format("%E3f", tp, tz));
00336   EXPECT_EQ("0000", format("%E4f", tp, tz));
00337   EXPECT_EQ("00000", format("%E5f", tp, tz));
00338   EXPECT_EQ("000000", format("%E6f", tp, tz));
00339   EXPECT_EQ("0000000", format("%E7f", tp, tz));
00340   EXPECT_EQ("00000000", format("%E8f", tp, tz));
00341   EXPECT_EQ("000000000", format("%E9f", tp, tz));
00342   EXPECT_EQ("0000000000", format("%E10f", tp, tz));
00343   EXPECT_EQ("00000000000", format("%E11f", tp, tz));
00344   EXPECT_EQ("000000000000", format("%E12f", tp, tz));
00345   EXPECT_EQ("0000000000000", format("%E13f", tp, tz));
00346   EXPECT_EQ("00000000000000", format("%E14f", tp, tz));
00347   EXPECT_EQ("000000000000000", format("%E15f", tp, tz));
00348 
00349   // With subseconds.
00350   tp += chrono::milliseconds(6) + chrono::microseconds(7) +
00351         chrono::nanoseconds(8);
00352   EXPECT_EQ("006007008", format("%E*f", tp, tz));
00353   EXPECT_EQ("", format("%E0f", tp, tz));
00354   EXPECT_EQ("0", format("%E1f", tp, tz));
00355   EXPECT_EQ("00", format("%E2f", tp, tz));
00356   EXPECT_EQ("006", format("%E3f", tp, tz));
00357   EXPECT_EQ("0060", format("%E4f", tp, tz));
00358   EXPECT_EQ("00600", format("%E5f", tp, tz));
00359   EXPECT_EQ("006007", format("%E6f", tp, tz));
00360   EXPECT_EQ("0060070", format("%E7f", tp, tz));
00361   EXPECT_EQ("00600700", format("%E8f", tp, tz));
00362   EXPECT_EQ("006007008", format("%E9f", tp, tz));
00363   EXPECT_EQ("0060070080", format("%E10f", tp, tz));
00364   EXPECT_EQ("00600700800", format("%E11f", tp, tz));
00365   EXPECT_EQ("006007008000", format("%E12f", tp, tz));
00366   EXPECT_EQ("0060070080000", format("%E13f", tp, tz));
00367   EXPECT_EQ("00600700800000", format("%E14f", tp, tz));
00368   EXPECT_EQ("006007008000000", format("%E15f", tp, tz));
00369 
00370   // Times before the Unix epoch.
00371   tp = chrono::system_clock::from_time_t(0) + chrono::microseconds(-1);
00372   EXPECT_EQ("1969-12-31 23:59:59.999999",
00373             format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz));
00374 
00375   // Here is a "%E*S" case we got wrong for a while.  While the first
00376   // instant below is correctly rendered as "...:07.333304", the second
00377   // one used to appear as "...:07.33330499999999999".
00378   tp = chrono::system_clock::from_time_t(0) +
00379        chrono::microseconds(1395024427333304);
00380   EXPECT_EQ("2014-03-17 02:47:07.333304",
00381             format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz));
00382   tp += chrono::microseconds(1);
00383   EXPECT_EQ("2014-03-17 02:47:07.333305",
00384             format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz));
00385 }
00386 
00387 TEST(Format, CompareExtendSecondsVsSubseconds) {
00388   const time_zone tz = utc_time_zone();
00389 
00390   // This test case illustrates the differences/similarities between:
00391   //   fmt_A: %E<prec>S
00392   //   fmt_B: %S.%E<prec>f
00393   auto fmt_A = [](const std::string& prec) { return "%E" + prec + "S"; };
00394   auto fmt_B = [](const std::string& prec) { return "%S.%E" + prec + "f"; };
00395 
00396   // No subseconds:
00397   time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);
00398   tp += chrono::seconds(5);
00399   // ... %E*S and %S.%E*f are different.
00400   EXPECT_EQ("05", format(fmt_A("*"), tp, tz));
00401   EXPECT_EQ("05.0", format(fmt_B("*"), tp, tz));
00402   // ... %E0S and %S.%E0f are different.
00403   EXPECT_EQ("05", format(fmt_A("0"), tp, tz));
00404   EXPECT_EQ("05.", format(fmt_B("0"), tp, tz));
00405   // ... %E<prec>S and %S.%E<prec>f are the same for prec in [1:15].
00406   for (int prec = 1; prec <= 15; ++prec) {
00407     const std::string a = format(fmt_A(std::to_string(prec)), tp, tz);
00408     const std::string b = format(fmt_B(std::to_string(prec)), tp, tz);
00409     EXPECT_EQ(a, b) << "prec=" << prec;
00410   }
00411 
00412   // With subseconds:
00413   // ... %E*S and %S.%E*f are the same.
00414   tp += chrono::milliseconds(6) + chrono::microseconds(7) +
00415         chrono::nanoseconds(8);
00416   EXPECT_EQ("05.006007008", format(fmt_A("*"), tp, tz));
00417   EXPECT_EQ("05.006007008", format(fmt_B("*"), tp, tz));
00418   // ... %E0S and %S.%E0f are different.
00419   EXPECT_EQ("05", format(fmt_A("0"), tp, tz));
00420   EXPECT_EQ("05.", format(fmt_B("0"), tp, tz));
00421   // ... %E<prec>S and %S.%E<prec>f are the same for prec in [1:15].
00422   for (int prec = 1; prec <= 15; ++prec) {
00423     const std::string a = format(fmt_A(std::to_string(prec)), tp, tz);
00424     const std::string b = format(fmt_B(std::to_string(prec)), tp, tz);
00425     EXPECT_EQ(a, b) << "prec=" << prec;
00426   }
00427 }
00428 
00429 TEST(Format, ExtendedOffset) {
00430   const auto tp = chrono::system_clock::from_time_t(0);
00431 
00432   auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
00433   TestFormatSpecifier(tp, tz, "%z", "+0000");
00434   TestFormatSpecifier(tp, tz, "%:z", "+00:00");
00435   TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
00436 
00437   tz = fixed_time_zone(chrono::seconds(56));
00438   TestFormatSpecifier(tp, tz, "%z", "+0000");
00439   TestFormatSpecifier(tp, tz, "%:z", "+00:00");
00440   TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
00441 
00442   tz = fixed_time_zone(-chrono::seconds(56));  // NOTE: +00:00
00443   TestFormatSpecifier(tp, tz, "%z", "+0000");
00444   TestFormatSpecifier(tp, tz, "%:z", "+00:00");
00445   TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
00446 
00447   tz = fixed_time_zone(chrono::minutes(34));
00448   TestFormatSpecifier(tp, tz, "%z", "+0034");
00449   TestFormatSpecifier(tp, tz, "%:z", "+00:34");
00450   TestFormatSpecifier(tp, tz, "%Ez", "+00:34");
00451 
00452   tz = fixed_time_zone(-chrono::minutes(34));
00453   TestFormatSpecifier(tp, tz, "%z", "-0034");
00454   TestFormatSpecifier(tp, tz, "%:z", "-00:34");
00455   TestFormatSpecifier(tp, tz, "%Ez", "-00:34");
00456 
00457   tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));
00458   TestFormatSpecifier(tp, tz, "%z", "+0034");
00459   TestFormatSpecifier(tp, tz, "%:z", "+00:34");
00460   TestFormatSpecifier(tp, tz, "%Ez", "+00:34");
00461 
00462   tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));
00463   TestFormatSpecifier(tp, tz, "%z", "-0034");
00464   TestFormatSpecifier(tp, tz, "%:z", "-00:34");
00465   TestFormatSpecifier(tp, tz, "%Ez", "-00:34");
00466 
00467   tz = fixed_time_zone(chrono::hours(12));
00468   TestFormatSpecifier(tp, tz, "%z", "+1200");
00469   TestFormatSpecifier(tp, tz, "%:z", "+12:00");
00470   TestFormatSpecifier(tp, tz, "%Ez", "+12:00");
00471 
00472   tz = fixed_time_zone(-chrono::hours(12));
00473   TestFormatSpecifier(tp, tz, "%z", "-1200");
00474   TestFormatSpecifier(tp, tz, "%:z", "-12:00");
00475   TestFormatSpecifier(tp, tz, "%Ez", "-12:00");
00476 
00477   tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));
00478   TestFormatSpecifier(tp, tz, "%z", "+1200");
00479   TestFormatSpecifier(tp, tz, "%:z", "+12:00");
00480   TestFormatSpecifier(tp, tz, "%Ez", "+12:00");
00481 
00482   tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));
00483   TestFormatSpecifier(tp, tz, "%z", "-1200");
00484   TestFormatSpecifier(tp, tz, "%:z", "-12:00");
00485   TestFormatSpecifier(tp, tz, "%Ez", "-12:00");
00486 
00487   tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));
00488   TestFormatSpecifier(tp, tz, "%z", "+1234");
00489   TestFormatSpecifier(tp, tz, "%:z", "+12:34");
00490   TestFormatSpecifier(tp, tz, "%Ez", "+12:34");
00491 
00492   tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));
00493   TestFormatSpecifier(tp, tz, "%z", "-1234");
00494   TestFormatSpecifier(tp, tz, "%:z", "-12:34");
00495   TestFormatSpecifier(tp, tz, "%Ez", "-12:34");
00496 
00497   tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +
00498                        chrono::seconds(56));
00499   TestFormatSpecifier(tp, tz, "%z", "+1234");
00500   TestFormatSpecifier(tp, tz, "%:z", "+12:34");
00501   TestFormatSpecifier(tp, tz, "%Ez", "+12:34");
00502 
00503   tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -
00504                        chrono::seconds(56));
00505   TestFormatSpecifier(tp, tz, "%z", "-1234");
00506   TestFormatSpecifier(tp, tz, "%:z", "-12:34");
00507   TestFormatSpecifier(tp, tz, "%Ez", "-12:34");
00508 }
00509 
00510 TEST(Format, ExtendedSecondOffset) {
00511   const auto tp = chrono::system_clock::from_time_t(0);
00512 
00513   auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
00514   TestFormatSpecifier(tp, tz, "%E*z", "+00:00:00");
00515   TestFormatSpecifier(tp, tz, "%::z", "+00:00:00");
00516   TestFormatSpecifier(tp, tz, "%:::z", "+00");
00517 
00518   tz = fixed_time_zone(chrono::seconds(56));
00519   TestFormatSpecifier(tp, tz, "%E*z", "+00:00:56");
00520   TestFormatSpecifier(tp, tz, "%::z", "+00:00:56");
00521   TestFormatSpecifier(tp, tz, "%:::z", "+00:00:56");
00522 
00523   tz = fixed_time_zone(-chrono::seconds(56));
00524   TestFormatSpecifier(tp, tz, "%E*z", "-00:00:56");
00525   TestFormatSpecifier(tp, tz, "%::z", "-00:00:56");
00526   TestFormatSpecifier(tp, tz, "%:::z", "-00:00:56");
00527 
00528   tz = fixed_time_zone(chrono::minutes(34));
00529   TestFormatSpecifier(tp, tz, "%E*z", "+00:34:00");
00530   TestFormatSpecifier(tp, tz, "%::z", "+00:34:00");
00531   TestFormatSpecifier(tp, tz, "%:::z", "+00:34");
00532 
00533   tz = fixed_time_zone(-chrono::minutes(34));
00534   TestFormatSpecifier(tp, tz, "%E*z", "-00:34:00");
00535   TestFormatSpecifier(tp, tz, "%::z", "-00:34:00");
00536   TestFormatSpecifier(tp, tz, "%:::z", "-00:34");
00537 
00538   tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));
00539   TestFormatSpecifier(tp, tz, "%E*z", "+00:34:56");
00540   TestFormatSpecifier(tp, tz, "%::z", "+00:34:56");
00541   TestFormatSpecifier(tp, tz, "%:::z", "+00:34:56");
00542 
00543   tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));
00544   TestFormatSpecifier(tp, tz, "%E*z", "-00:34:56");
00545   TestFormatSpecifier(tp, tz, "%::z", "-00:34:56");
00546   TestFormatSpecifier(tp, tz, "%:::z", "-00:34:56");
00547 
00548   tz = fixed_time_zone(chrono::hours(12));
00549   TestFormatSpecifier(tp, tz, "%E*z", "+12:00:00");
00550   TestFormatSpecifier(tp, tz, "%::z", "+12:00:00");
00551   TestFormatSpecifier(tp, tz, "%:::z", "+12");
00552 
00553   tz = fixed_time_zone(-chrono::hours(12));
00554   TestFormatSpecifier(tp, tz, "%E*z", "-12:00:00");
00555   TestFormatSpecifier(tp, tz, "%::z", "-12:00:00");
00556   TestFormatSpecifier(tp, tz, "%:::z", "-12");
00557 
00558   tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));
00559   TestFormatSpecifier(tp, tz, "%E*z", "+12:00:56");
00560   TestFormatSpecifier(tp, tz, "%::z", "+12:00:56");
00561   TestFormatSpecifier(tp, tz, "%:::z", "+12:00:56");
00562 
00563   tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));
00564   TestFormatSpecifier(tp, tz, "%E*z", "-12:00:56");
00565   TestFormatSpecifier(tp, tz, "%::z", "-12:00:56");
00566   TestFormatSpecifier(tp, tz, "%:::z", "-12:00:56");
00567 
00568   tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));
00569   TestFormatSpecifier(tp, tz, "%E*z", "+12:34:00");
00570   TestFormatSpecifier(tp, tz, "%::z", "+12:34:00");
00571   TestFormatSpecifier(tp, tz, "%:::z", "+12:34");
00572 
00573   tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));
00574   TestFormatSpecifier(tp, tz, "%E*z", "-12:34:00");
00575   TestFormatSpecifier(tp, tz, "%::z", "-12:34:00");
00576   TestFormatSpecifier(tp, tz, "%:::z", "-12:34");
00577 
00578   tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +
00579                        chrono::seconds(56));
00580   TestFormatSpecifier(tp, tz, "%E*z", "+12:34:56");
00581   TestFormatSpecifier(tp, tz, "%::z", "+12:34:56");
00582   TestFormatSpecifier(tp, tz, "%:::z", "+12:34:56");
00583 
00584   tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -
00585                        chrono::seconds(56));
00586   TestFormatSpecifier(tp, tz, "%E*z", "-12:34:56");
00587   TestFormatSpecifier(tp, tz, "%::z", "-12:34:56");
00588   TestFormatSpecifier(tp, tz, "%:::z", "-12:34:56");
00589 }
00590 
00591 TEST(Format, ExtendedYears) {
00592   const time_zone utc = utc_time_zone();
00593   const char e4y_fmt[] = "%E4Y%m%d";  // no separators
00594 
00595   // %E4Y zero-pads the year to produce at least 4 chars, including the sign.
00596   auto tp = convert(civil_second(-999, 11, 27, 0, 0, 0), utc);
00597   EXPECT_EQ("-9991127", format(e4y_fmt, tp, utc));
00598   tp = convert(civil_second(-99, 11, 27, 0, 0, 0), utc);
00599   EXPECT_EQ("-0991127", format(e4y_fmt, tp, utc));
00600   tp = convert(civil_second(-9, 11, 27, 0, 0, 0), utc);
00601   EXPECT_EQ("-0091127", format(e4y_fmt, tp, utc));
00602   tp = convert(civil_second(-1, 11, 27, 0, 0, 0), utc);
00603   EXPECT_EQ("-0011127", format(e4y_fmt, tp, utc));
00604   tp = convert(civil_second(0, 11, 27, 0, 0, 0), utc);
00605   EXPECT_EQ("00001127", format(e4y_fmt, tp, utc));
00606   tp = convert(civil_second(1, 11, 27, 0, 0, 0), utc);
00607   EXPECT_EQ("00011127", format(e4y_fmt, tp, utc));
00608   tp = convert(civil_second(9, 11, 27, 0, 0, 0), utc);
00609   EXPECT_EQ("00091127", format(e4y_fmt, tp, utc));
00610   tp = convert(civil_second(99, 11, 27, 0, 0, 0), utc);
00611   EXPECT_EQ("00991127", format(e4y_fmt, tp, utc));
00612   tp = convert(civil_second(999, 11, 27, 0, 0, 0), utc);
00613   EXPECT_EQ("09991127", format(e4y_fmt, tp, utc));
00614   tp = convert(civil_second(9999, 11, 27, 0, 0, 0), utc);
00615   EXPECT_EQ("99991127", format(e4y_fmt, tp, utc));
00616 
00617   // When the year is outside [-999:9999], more than 4 chars are produced.
00618   tp = convert(civil_second(-1000, 11, 27, 0, 0, 0), utc);
00619   EXPECT_EQ("-10001127", format(e4y_fmt, tp, utc));
00620   tp = convert(civil_second(10000, 11, 27, 0, 0, 0), utc);
00621   EXPECT_EQ("100001127", format(e4y_fmt, tp, utc));
00622 }
00623 
00624 TEST(Format, RFC3339Format) {
00625   time_zone tz;
00626   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
00627 
00628   time_point<chrono::nanoseconds> tp =
00629       convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
00630   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_full, tp, tz));
00631   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
00632 
00633   tp += chrono::milliseconds(100);
00634   EXPECT_EQ("1977-06-28T09:08:07.1-07:00", format(RFC3339_full, tp, tz));
00635   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
00636 
00637   tp += chrono::milliseconds(20);
00638   EXPECT_EQ("1977-06-28T09:08:07.12-07:00", format(RFC3339_full, tp, tz));
00639   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
00640 
00641   tp += chrono::milliseconds(3);
00642   EXPECT_EQ("1977-06-28T09:08:07.123-07:00", format(RFC3339_full, tp, tz));
00643   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
00644 
00645   tp += chrono::microseconds(400);
00646   EXPECT_EQ("1977-06-28T09:08:07.1234-07:00", format(RFC3339_full, tp, tz));
00647   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
00648 
00649   tp += chrono::microseconds(50);
00650   EXPECT_EQ("1977-06-28T09:08:07.12345-07:00", format(RFC3339_full, tp, tz));
00651   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
00652 
00653   tp += chrono::microseconds(6);
00654   EXPECT_EQ("1977-06-28T09:08:07.123456-07:00", format(RFC3339_full, tp, tz));
00655   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
00656 
00657   tp += chrono::nanoseconds(700);
00658   EXPECT_EQ("1977-06-28T09:08:07.1234567-07:00", format(RFC3339_full, tp, tz));
00659   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
00660 
00661   tp += chrono::nanoseconds(80);
00662   EXPECT_EQ("1977-06-28T09:08:07.12345678-07:00", format(RFC3339_full, tp, tz));
00663   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
00664 
00665   tp += chrono::nanoseconds(9);
00666   EXPECT_EQ("1977-06-28T09:08:07.123456789-07:00",
00667             format(RFC3339_full, tp, tz));
00668   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
00669 }
00670 
00671 TEST(Format, RFC1123Format) {  // locale specific
00672   time_zone tz;
00673   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
00674 
00675   auto tp = convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
00676   EXPECT_EQ("Tue, 28 Jun 1977 09:08:07 -0700", format(RFC1123_full, tp, tz));
00677   EXPECT_EQ("28 Jun 1977 09:08:07 -0700", format(RFC1123_no_wday, tp, tz));
00678 }
00679 
00680 //
00681 // Testing parse()
00682 //
00683 
00684 TEST(Parse, TimePointResolution) {
00685   const char kFmt[] = "%H:%M:%E*S";
00686   const time_zone utc = utc_time_zone();
00687 
00688   time_point<chrono::nanoseconds> tp_ns;
00689   EXPECT_TRUE(parse(kFmt, "03:04:05.123456789", utc, &tp_ns));
00690   EXPECT_EQ("03:04:05.123456789", format(kFmt, tp_ns, utc));
00691   EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_ns));
00692   EXPECT_EQ("03:04:05.123456", format(kFmt, tp_ns, utc));
00693 
00694   time_point<chrono::microseconds> tp_us;
00695   EXPECT_TRUE(parse(kFmt, "03:04:05.123456789", utc, &tp_us));
00696   EXPECT_EQ("03:04:05.123456", format(kFmt, tp_us, utc));
00697   EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_us));
00698   EXPECT_EQ("03:04:05.123456", format(kFmt, tp_us, utc));
00699   EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_us));
00700   EXPECT_EQ("03:04:05.123", format(kFmt, tp_us, utc));
00701 
00702   time_point<chrono::milliseconds> tp_ms;
00703   EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_ms));
00704   EXPECT_EQ("03:04:05.123", format(kFmt, tp_ms, utc));
00705   EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_ms));
00706   EXPECT_EQ("03:04:05.123", format(kFmt, tp_ms, utc));
00707   EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_ms));
00708   EXPECT_EQ("03:04:05", format(kFmt, tp_ms, utc));
00709 
00710   time_point<chrono::seconds> tp_s;
00711   EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_s));
00712   EXPECT_EQ("03:04:05", format(kFmt, tp_s, utc));
00713   EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_s));
00714   EXPECT_EQ("03:04:05", format(kFmt, tp_s, utc));
00715 
00716   time_point<chrono::minutes> tp_m;
00717   EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_m));
00718   EXPECT_EQ("03:04:00", format(kFmt, tp_m, utc));
00719 
00720   time_point<chrono::hours> tp_h;
00721   EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_h));
00722   EXPECT_EQ("03:00:00", format(kFmt, tp_h, utc));
00723 }
00724 
00725 TEST(Parse, TimePointExtendedResolution) {
00726   const char kFmt[] = "%H:%M:%E*S";
00727   const time_zone utc = utc_time_zone();
00728 
00729   time_point<absl::time_internal::cctz::seconds> tp;
00730   detail::femtoseconds fs;
00731   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.123456789012345", utc, &tp, &fs));
00732   EXPECT_EQ("12:34:56.123456789012345", detail::format(kFmt, tp, fs, utc));
00733   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.012345678901234", utc, &tp, &fs));
00734   EXPECT_EQ("12:34:56.012345678901234", detail::format(kFmt, tp, fs, utc));
00735   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.001234567890123", utc, &tp, &fs));
00736   EXPECT_EQ("12:34:56.001234567890123", detail::format(kFmt, tp, fs, utc));
00737   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000123", utc, &tp, &fs));
00738   EXPECT_EQ("12:34:56.000000000000123", detail::format(kFmt, tp, fs, utc));
00739   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000012", utc, &tp, &fs));
00740   EXPECT_EQ("12:34:56.000000000000012", detail::format(kFmt, tp, fs, utc));
00741   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000001", utc, &tp, &fs));
00742   EXPECT_EQ("12:34:56.000000000000001", detail::format(kFmt, tp, fs, utc));
00743 }
00744 
00745 TEST(Parse, Basics) {
00746   time_zone tz = utc_time_zone();
00747   time_point<chrono::nanoseconds> tp =
00748       chrono::system_clock::from_time_t(1234567890);
00749 
00750   // Simple edge cases.
00751   EXPECT_TRUE(parse("", "", tz, &tp));
00752   EXPECT_EQ(chrono::system_clock::from_time_t(0), tp);  // everything defaulted
00753   EXPECT_TRUE(parse(" ", " ", tz, &tp));
00754   EXPECT_TRUE(parse("  ", "  ", tz, &tp));
00755   EXPECT_TRUE(parse("x", "x", tz, &tp));
00756   EXPECT_TRUE(parse("xxx", "xxx", tz, &tp));
00757 
00758   EXPECT_TRUE(
00759       parse("%Y-%m-%d %H:%M:%S %z", "2013-06-28 19:08:09 -0800", tz, &tp));
00760   ExpectTime(tp, tz, 2013, 6, 29, 3, 8, 9, 0, false, "UTC");
00761 }
00762 
00763 TEST(Parse, WithTimeZone) {
00764   time_zone tz;
00765   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
00766   time_point<chrono::nanoseconds> tp;
00767 
00768   // We can parse a std::string without a UTC offset if we supply a timezone.
00769   EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &tp));
00770   ExpectTime(tp, tz, 2013, 6, 28, 19, 8, 9, -7 * 60 * 60, true, "PDT");
00771 
00772   // But the timezone is ignored when a UTC offset is present.
00773   EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S %z", "2013-06-28 19:08:09 +0800",
00774                     utc_time_zone(), &tp));
00775   ExpectTime(tp, tz, 2013, 6, 28, 19 - 8 - 7, 8, 9, -7 * 60 * 60, true, "PDT");
00776 
00777   // Check a skipped time (a Spring DST transition). parse() uses the
00778   // pre-transition offset.
00779   EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2011-03-13 02:15:00", tz, &tp));
00780   ExpectTime(tp, tz, 2011, 3, 13, 3, 15, 0, -7 * 60 * 60, true, "PDT");
00781 
00782   // Check a repeated time (a Fall DST transition).  parse() uses the
00783   // pre-transition offset.
00784   EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2011-11-06 01:15:00", tz, &tp));
00785   ExpectTime(tp, tz, 2011, 11, 6, 1, 15, 0, -7 * 60 * 60, true, "PDT");
00786 }
00787 
00788 TEST(Parse, LeapSecond) {
00789   time_zone tz;
00790   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
00791   time_point<chrono::nanoseconds> tp;
00792 
00793   // ":59" -> ":59"
00794   EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:59-08:00", tz, &tp));
00795   ExpectTime(tp, tz, 2013, 6, 28, 8, 8, 59, -7 * 60 * 60, true, "PDT");
00796 
00797   // ":59.5" -> ":59.5"
00798   EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:59.5-08:00", tz, &tp));
00799   ExpectTime(tp, tz, 2013, 6, 28, 8, 8, 59, -7 * 60 * 60, true, "PDT");
00800 
00801   // ":60" -> ":00"
00802   EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:60-08:00", tz, &tp));
00803   ExpectTime(tp, tz, 2013, 6, 28, 8, 9, 0, -7 * 60 * 60, true, "PDT");
00804 
00805   // ":60.5" -> ":00.0"
00806   EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:60.5-08:00", tz, &tp));
00807   ExpectTime(tp, tz, 2013, 6, 28, 8, 9, 0, -7 * 60 * 60, true, "PDT");
00808 
00809   // ":61" -> error
00810   EXPECT_FALSE(parse(RFC3339_full, "2013-06-28T07:08:61-08:00", tz, &tp));
00811 }
00812 
00813 TEST(Parse, ErrorCases) {
00814   const time_zone tz = utc_time_zone();
00815   auto tp = chrono::system_clock::from_time_t(0);
00816 
00817   // Illegal trailing data.
00818   EXPECT_FALSE(parse("%S", "123", tz, &tp));
00819 
00820   // Can't parse an illegal format specifier.
00821   EXPECT_FALSE(parse("%Q", "x", tz, &tp));
00822 
00823   // Fails because of trailing, unparsed data "blah".
00824   EXPECT_FALSE(parse("%m-%d", "2-3 blah", tz, &tp));
00825 
00826   // Trailing whitespace is allowed.
00827   EXPECT_TRUE(parse("%m-%d", "2-3  ", tz, &tp));
00828   EXPECT_EQ(2, convert(tp, utc_time_zone()).month());
00829   EXPECT_EQ(3, convert(tp, utc_time_zone()).day());
00830 
00831   // Feb 31 requires normalization.
00832   EXPECT_FALSE(parse("%m-%d", "2-31", tz, &tp));
00833 
00834   // Check that we cannot have spaces in UTC offsets.
00835   EXPECT_TRUE(parse("%z", "-0203", tz, &tp));
00836   EXPECT_FALSE(parse("%z", "- 2 3", tz, &tp));
00837   EXPECT_TRUE(parse("%Ez", "-02:03", tz, &tp));
00838   EXPECT_FALSE(parse("%Ez", "- 2: 3", tz, &tp));
00839 
00840   // Check that we reject other malformed UTC offsets.
00841   EXPECT_FALSE(parse("%Ez", "+-08:00", tz, &tp));
00842   EXPECT_FALSE(parse("%Ez", "-+08:00", tz, &tp));
00843 
00844   // Check that we do not accept "-0" in fields that allow zero.
00845   EXPECT_FALSE(parse("%Y", "-0", tz, &tp));
00846   EXPECT_FALSE(parse("%E4Y", "-0", tz, &tp));
00847   EXPECT_FALSE(parse("%H", "-0", tz, &tp));
00848   EXPECT_FALSE(parse("%M", "-0", tz, &tp));
00849   EXPECT_FALSE(parse("%S", "-0", tz, &tp));
00850   EXPECT_FALSE(parse("%z", "+-000", tz, &tp));
00851   EXPECT_FALSE(parse("%Ez", "+-0:00", tz, &tp));
00852   EXPECT_FALSE(parse("%z", "-00-0", tz, &tp));
00853   EXPECT_FALSE(parse("%Ez", "-00:-0", tz, &tp));
00854 }
00855 
00856 TEST(Parse, PosixConversions) {
00857   time_zone tz = utc_time_zone();
00858   auto tp = chrono::system_clock::from_time_t(0);
00859   const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
00860 
00861   tp = reset;
00862   EXPECT_TRUE(parse("%d", "15", tz, &tp));
00863   EXPECT_EQ(15, convert(tp, tz).day());
00864 
00865   // %e is an extension, but is supported internally.
00866   tp = reset;
00867   EXPECT_TRUE(parse("%e", "15", tz, &tp));
00868   EXPECT_EQ(15, convert(tp, tz).day());  // Equivalent to %d
00869 
00870   tp = reset;
00871   EXPECT_TRUE(parse("%H", "17", tz, &tp));
00872   EXPECT_EQ(17, convert(tp, tz).hour());
00873 
00874   tp = reset;
00875   EXPECT_TRUE(parse("%I", "5", tz, &tp));
00876   EXPECT_EQ(5, convert(tp, tz).hour());
00877 
00878   // %j is parsed but ignored.
00879   EXPECT_TRUE(parse("%j", "32", tz, &tp));
00880 
00881   tp = reset;
00882   EXPECT_TRUE(parse("%m", "11", tz, &tp));
00883   EXPECT_EQ(11, convert(tp, tz).month());
00884 
00885   tp = reset;
00886   EXPECT_TRUE(parse("%M", "33", tz, &tp));
00887   EXPECT_EQ(33, convert(tp, tz).minute());
00888 
00889   tp = reset;
00890   EXPECT_TRUE(parse("%S", "55", tz, &tp));
00891   EXPECT_EQ(55, convert(tp, tz).second());
00892 
00893   // %U is parsed but ignored.
00894   EXPECT_TRUE(parse("%U", "15", tz, &tp));
00895 
00896   // %w is parsed but ignored.
00897   EXPECT_TRUE(parse("%w", "2", tz, &tp));
00898 
00899   // %W is parsed but ignored.
00900   EXPECT_TRUE(parse("%W", "22", tz, &tp));
00901 
00902   tp = reset;
00903   EXPECT_TRUE(parse("%y", "04", tz, &tp));
00904   EXPECT_EQ(2004, convert(tp, tz).year());
00905 
00906   tp = reset;
00907   EXPECT_TRUE(parse("%Y", "2004", tz, &tp));
00908   EXPECT_EQ(2004, convert(tp, tz).year());
00909 
00910   EXPECT_TRUE(parse("%%", "%", tz, &tp));
00911 
00912 #if defined(__linux__)
00913   // SU/C99/TZ extensions
00914 
00915   // Because we handle each (non-internal) specifier in a separate call
00916   // to strptime(), there is no way to group %C and %y together.  So we
00917   // just skip the %C/%y case.
00918 #if 0
00919   tp = reset;
00920   EXPECT_TRUE(parse("%C %y", "20 04", tz, &tp));
00921   EXPECT_EQ(2004, convert(tp, tz).year());
00922 #endif
00923 
00924   tp = reset;
00925   EXPECT_TRUE(parse("%D", "02/03/04", tz, &tp));
00926   EXPECT_EQ(2, convert(tp, tz).month());
00927   EXPECT_EQ(3, convert(tp, tz).day());
00928   EXPECT_EQ(2004, convert(tp, tz).year());
00929 
00930   EXPECT_TRUE(parse("%n", "\n", tz, &tp));
00931 
00932   tp = reset;
00933   EXPECT_TRUE(parse("%R", "03:44", tz, &tp));
00934   EXPECT_EQ(3, convert(tp, tz).hour());
00935   EXPECT_EQ(44, convert(tp, tz).minute());
00936 
00937   EXPECT_TRUE(parse("%t", "\t\v\f\n\r ", tz, &tp));
00938 
00939   tp = reset;
00940   EXPECT_TRUE(parse("%T", "03:44:55", tz, &tp));
00941   EXPECT_EQ(3, convert(tp, tz).hour());
00942   EXPECT_EQ(44, convert(tp, tz).minute());
00943   EXPECT_EQ(55, convert(tp, tz).second());
00944 
00945   tp = reset;
00946   EXPECT_TRUE(parse("%s", "1234567890", tz, &tp));
00947   EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp);
00948 
00949   // %s conversion, like %z/%Ez, pays no heed to the optional zone.
00950   time_zone lax;
00951   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &lax));
00952   tp = reset;
00953   EXPECT_TRUE(parse("%s", "1234567890", lax, &tp));
00954   EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp);
00955 
00956   // This is most important when the time has the same YMDhms
00957   // breakdown in the zone as some other time.  For example, ...
00958   //  1414917000 in US/Pacific -> Sun Nov 2 01:30:00 2014 (PDT)
00959   //  1414920600 in US/Pacific -> Sun Nov 2 01:30:00 2014 (PST)
00960   tp = reset;
00961   EXPECT_TRUE(parse("%s", "1414917000", lax, &tp));
00962   EXPECT_EQ(chrono::system_clock::from_time_t(1414917000), tp);
00963   tp = reset;
00964   EXPECT_TRUE(parse("%s", "1414920600", lax, &tp));
00965   EXPECT_EQ(chrono::system_clock::from_time_t(1414920600), tp);
00966 #endif
00967 }
00968 
00969 TEST(Parse, LocaleSpecific) {
00970   time_zone tz = utc_time_zone();
00971   auto tp = chrono::system_clock::from_time_t(0);
00972   const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
00973 
00974   // %a is parsed but ignored.
00975   EXPECT_TRUE(parse("%a", "Mon", tz, &tp));
00976 
00977   // %A is parsed but ignored.
00978   EXPECT_TRUE(parse("%A", "Monday", tz, &tp));
00979 
00980   tp = reset;
00981   EXPECT_TRUE(parse("%b", "Feb", tz, &tp));
00982   EXPECT_EQ(2, convert(tp, tz).month());
00983 
00984   tp = reset;
00985   EXPECT_TRUE(parse("%B", "February", tz, &tp));
00986   EXPECT_EQ(2, convert(tp, tz).month());
00987 
00988   // %p is parsed but ignored if it's alone.  But it's used with %I.
00989   EXPECT_TRUE(parse("%p", "AM", tz, &tp));
00990   tp = reset;
00991   EXPECT_TRUE(parse("%I %p", "5 PM", tz, &tp));
00992   EXPECT_EQ(17, convert(tp, tz).hour());
00993 
00994   tp = reset;
00995   EXPECT_TRUE(parse("%x", "02/03/04", tz, &tp));
00996   if (convert(tp, tz).month() == 2) {
00997     EXPECT_EQ(3, convert(tp, tz).day());
00998   } else {
00999     EXPECT_EQ(2, convert(tp, tz).day());
01000     EXPECT_EQ(3, convert(tp, tz).month());
01001   }
01002   EXPECT_EQ(2004, convert(tp, tz).year());
01003 
01004   tp = reset;
01005   EXPECT_TRUE(parse("%X", "15:44:55", tz, &tp));
01006   EXPECT_EQ(15, convert(tp, tz).hour());
01007   EXPECT_EQ(44, convert(tp, tz).minute());
01008   EXPECT_EQ(55, convert(tp, tz).second());
01009 
01010 #if defined(__linux__)
01011   // SU/C99/TZ extensions
01012 
01013   tp = reset;
01014   EXPECT_TRUE(parse("%h", "Feb", tz, &tp));
01015   EXPECT_EQ(2, convert(tp, tz).month());  // Equivalent to %b
01016 
01017   tp = reset;
01018   EXPECT_TRUE(parse("%l %p", "5 PM", tz, &tp));
01019   EXPECT_EQ(17, convert(tp, tz).hour());
01020 
01021   tp = reset;
01022   EXPECT_TRUE(parse("%r", "03:44:55 PM", tz, &tp));
01023   EXPECT_EQ(15, convert(tp, tz).hour());
01024   EXPECT_EQ(44, convert(tp, tz).minute());
01025   EXPECT_EQ(55, convert(tp, tz).second());
01026 
01027   tp = reset;
01028   EXPECT_TRUE(parse("%Ec", "Tue Nov 19 05:06:07 2013", tz, &tp));
01029   EXPECT_EQ(convert(civil_second(2013, 11, 19, 5, 6, 7), tz), tp);
01030 
01031   // Modified conversion specifiers %E_
01032 
01033   tp = reset;
01034   EXPECT_TRUE(parse("%Ex", "02/03/04", tz, &tp));
01035   EXPECT_EQ(2, convert(tp, tz).month());
01036   EXPECT_EQ(3, convert(tp, tz).day());
01037   EXPECT_EQ(2004, convert(tp, tz).year());
01038 
01039   tp = reset;
01040   EXPECT_TRUE(parse("%EX", "15:44:55", tz, &tp));
01041   EXPECT_EQ(15, convert(tp, tz).hour());
01042   EXPECT_EQ(44, convert(tp, tz).minute());
01043   EXPECT_EQ(55, convert(tp, tz).second());
01044 
01045   // %Ey, the year offset from %EC, doesn't really make sense alone as there
01046   // is no way to represent it in tm_year (%EC is not simply the century).
01047   // Yet, because we handle each (non-internal) specifier in a separate call
01048   // to strptime(), there is no way to group %EC and %Ey either.  So we just
01049   // skip the %EC and %Ey cases.
01050 
01051   tp = reset;
01052   EXPECT_TRUE(parse("%EY", "2004", tz, &tp));
01053   EXPECT_EQ(2004, convert(tp, tz).year());
01054 
01055   // Modified conversion specifiers %O_
01056 
01057   tp = reset;
01058   EXPECT_TRUE(parse("%Od", "15", tz, &tp));
01059   EXPECT_EQ(15, convert(tp, tz).day());
01060 
01061   tp = reset;
01062   EXPECT_TRUE(parse("%Oe", "15", tz, &tp));
01063   EXPECT_EQ(15, convert(tp, tz).day());  // Equivalent to %d
01064 
01065   tp = reset;
01066   EXPECT_TRUE(parse("%OH", "17", tz, &tp));
01067   EXPECT_EQ(17, convert(tp, tz).hour());
01068 
01069   tp = reset;
01070   EXPECT_TRUE(parse("%OI", "5", tz, &tp));
01071   EXPECT_EQ(5, convert(tp, tz).hour());
01072 
01073   tp = reset;
01074   EXPECT_TRUE(parse("%Om", "11", tz, &tp));
01075   EXPECT_EQ(11, convert(tp, tz).month());
01076 
01077   tp = reset;
01078   EXPECT_TRUE(parse("%OM", "33", tz, &tp));
01079   EXPECT_EQ(33, convert(tp, tz).minute());
01080 
01081   tp = reset;
01082   EXPECT_TRUE(parse("%OS", "55", tz, &tp));
01083   EXPECT_EQ(55, convert(tp, tz).second());
01084 
01085   // %OU is parsed but ignored.
01086   EXPECT_TRUE(parse("%OU", "15", tz, &tp));
01087 
01088   // %Ow is parsed but ignored.
01089   EXPECT_TRUE(parse("%Ow", "2", tz, &tp));
01090 
01091   // %OW is parsed but ignored.
01092   EXPECT_TRUE(parse("%OW", "22", tz, &tp));
01093 
01094   tp = reset;
01095   EXPECT_TRUE(parse("%Oy", "04", tz, &tp));
01096   EXPECT_EQ(2004, convert(tp, tz).year());
01097 #endif
01098 }
01099 
01100 TEST(Parse, ExtendedSeconds) {
01101   const time_zone tz = utc_time_zone();
01102   const time_point<chrono::nanoseconds> unix_epoch =
01103       chrono::system_clock::from_time_t(0);
01104 
01105   // All %E<prec>S cases are treated the same as %E*S on input.
01106   auto precisions = {"*", "0", "1",  "2",  "3",  "4",  "5",  "6", "7",
01107                      "8", "9", "10", "11", "12", "13", "14", "15"};
01108   for (const std::string& prec : precisions) {
01109     const std::string fmt = "%E" + prec + "S";
01110     SCOPED_TRACE(fmt);
01111     time_point<chrono::nanoseconds> tp = unix_epoch;
01112     EXPECT_TRUE(parse(fmt, "5", tz, &tp));
01113     EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);
01114     tp = unix_epoch;
01115     EXPECT_TRUE(parse(fmt, "05", tz, &tp));
01116     EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);
01117     tp = unix_epoch;
01118     EXPECT_TRUE(parse(fmt, "05.0", tz, &tp));
01119     EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);
01120     tp = unix_epoch;
01121     EXPECT_TRUE(parse(fmt, "05.00", tz, &tp));
01122     EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);
01123     tp = unix_epoch;
01124     EXPECT_TRUE(parse(fmt, "05.6", tz, &tp));
01125     EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp);
01126     tp = unix_epoch;
01127     EXPECT_TRUE(parse(fmt, "05.60", tz, &tp));
01128     EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp);
01129     tp = unix_epoch;
01130     EXPECT_TRUE(parse(fmt, "05.600", tz, &tp));
01131     EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp);
01132     tp = unix_epoch;
01133     EXPECT_TRUE(parse(fmt, "05.67", tz, &tp));
01134     EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(670), tp);
01135     tp = unix_epoch;
01136     EXPECT_TRUE(parse(fmt, "05.670", tz, &tp));
01137     EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(670), tp);
01138     tp = unix_epoch;
01139     EXPECT_TRUE(parse(fmt, "05.678", tz, &tp));
01140     EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(678), tp);
01141   }
01142 
01143   // Here is a "%E*S" case we got wrong for a while.  The fractional
01144   // part of the first instant is less than 2^31 and was correctly
01145   // parsed, while the second (and any subsecond field >=2^31) failed.
01146   time_point<chrono::nanoseconds> tp = unix_epoch;
01147   EXPECT_TRUE(parse("%E*S", "0.2147483647", tz, &tp));
01148   EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
01149   tp = unix_epoch;
01150   EXPECT_TRUE(parse("%E*S", "0.2147483648", tz, &tp));
01151   EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
01152 
01153   // We should also be able to specify long strings of digits far
01154   // beyond the current resolution and have them convert the same way.
01155   tp = unix_epoch;
01156   EXPECT_TRUE(parse(
01157       "%E*S", "0.214748364801234567890123456789012345678901234567890123456789",
01158       tz, &tp));
01159   EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
01160 }
01161 
01162 TEST(Parse, ExtendedSecondsScan) {
01163   const time_zone tz = utc_time_zone();
01164   time_point<chrono::nanoseconds> tp;
01165   for (int ms = 0; ms < 1000; ms += 111) {
01166     for (int us = 0; us < 1000; us += 27) {
01167       const int micros = ms * 1000 + us;
01168       for (int ns = 0; ns < 1000; ns += 9) {
01169         const auto expected = chrono::system_clock::from_time_t(0) +
01170                               chrono::nanoseconds(micros * 1000 + ns);
01171         std::ostringstream oss;
01172         oss << "0." << std::setfill('0') << std::setw(3);
01173         oss << ms << std::setw(3) << us << std::setw(3) << ns;
01174         const std::string input = oss.str();
01175         EXPECT_TRUE(parse("%E*S", input, tz, &tp));
01176         EXPECT_EQ(expected, tp) << input;
01177       }
01178     }
01179   }
01180 }
01181 
01182 TEST(Parse, ExtendedSubeconds) {
01183   const time_zone tz = utc_time_zone();
01184   const time_point<chrono::nanoseconds> unix_epoch =
01185       chrono::system_clock::from_time_t(0);
01186 
01187   // All %E<prec>f cases are treated the same as %E*f on input.
01188   auto precisions = {"*", "0", "1",  "2",  "3",  "4",  "5",  "6", "7",
01189                      "8", "9", "10", "11", "12", "13", "14", "15"};
01190   for (const std::string& prec : precisions) {
01191     const std::string fmt = "%E" + prec + "f";
01192     SCOPED_TRACE(fmt);
01193     time_point<chrono::nanoseconds> tp = unix_epoch - chrono::seconds(1);
01194     EXPECT_TRUE(parse(fmt, "", tz, &tp));
01195     EXPECT_EQ(unix_epoch, tp);
01196     tp = unix_epoch;
01197     EXPECT_TRUE(parse(fmt, "6", tz, &tp));
01198     EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp);
01199     tp = unix_epoch;
01200     EXPECT_TRUE(parse(fmt, "60", tz, &tp));
01201     EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp);
01202     tp = unix_epoch;
01203     EXPECT_TRUE(parse(fmt, "600", tz, &tp));
01204     EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp);
01205     tp = unix_epoch;
01206     EXPECT_TRUE(parse(fmt, "67", tz, &tp));
01207     EXPECT_EQ(unix_epoch + chrono::milliseconds(670), tp);
01208     tp = unix_epoch;
01209     EXPECT_TRUE(parse(fmt, "670", tz, &tp));
01210     EXPECT_EQ(unix_epoch + chrono::milliseconds(670), tp);
01211     tp = unix_epoch;
01212     EXPECT_TRUE(parse(fmt, "678", tz, &tp));
01213     EXPECT_EQ(unix_epoch + chrono::milliseconds(678), tp);
01214     tp = unix_epoch;
01215     EXPECT_TRUE(parse(fmt, "6789", tz, &tp));
01216     EXPECT_EQ(
01217         unix_epoch + chrono::milliseconds(678) + chrono::microseconds(900), tp);
01218   }
01219 
01220   // Here is a "%E*f" case we got wrong for a while.  The fractional
01221   // part of the first instant is less than 2^31 and was correctly
01222   // parsed, while the second (and any subsecond field >=2^31) failed.
01223   time_point<chrono::nanoseconds> tp = unix_epoch;
01224   EXPECT_TRUE(parse("%E*f", "2147483647", tz, &tp));
01225   EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
01226   tp = unix_epoch;
01227   EXPECT_TRUE(parse("%E*f", "2147483648", tz, &tp));
01228   EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
01229 
01230   // We should also be able to specify long strings of digits far
01231   // beyond the current resolution and have them convert the same way.
01232   tp = unix_epoch;
01233   EXPECT_TRUE(parse(
01234       "%E*f", "214748364801234567890123456789012345678901234567890123456789",
01235       tz, &tp));
01236   EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
01237 }
01238 
01239 TEST(Parse, ExtendedSubecondsScan) {
01240   time_point<chrono::nanoseconds> tp;
01241   const time_zone tz = utc_time_zone();
01242   for (int ms = 0; ms < 1000; ms += 111) {
01243     for (int us = 0; us < 1000; us += 27) {
01244       const int micros = ms * 1000 + us;
01245       for (int ns = 0; ns < 1000; ns += 9) {
01246         std::ostringstream oss;
01247         oss << std::setfill('0') << std::setw(3) << ms;
01248         oss << std::setw(3) << us << std::setw(3) << ns;
01249         const std::string nanos = oss.str();
01250         const auto expected = chrono::system_clock::from_time_t(0) +
01251                               chrono::nanoseconds(micros * 1000 + ns);
01252         for (int ps = 0; ps < 1000; ps += 250) {
01253           std::ostringstream oss;
01254           oss << std::setfill('0') << std::setw(3) << ps;
01255           const std::string input = nanos + oss.str() + "999";
01256           EXPECT_TRUE(parse("%E*f", input, tz, &tp));
01257           EXPECT_EQ(expected + chrono::nanoseconds(ps) / 1000, tp) << input;
01258         }
01259       }
01260     }
01261   }
01262 }
01263 
01264 TEST(Parse, ExtendedOffset) {
01265   const time_zone utc = utc_time_zone();
01266   time_point<absl::time_internal::cctz::seconds> tp;
01267 
01268   EXPECT_TRUE(parse("%Ez", "+00:00", utc, &tp));
01269   EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
01270   EXPECT_TRUE(parse("%Ez", "-12:34", utc, &tp));
01271   EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
01272   EXPECT_TRUE(parse("%Ez", "+12:34", utc, &tp));
01273   EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
01274   EXPECT_FALSE(parse("%Ez", "-12:3", utc, &tp));
01275 
01276   for (auto fmt : {"%Ez", "%z"}) {
01277     EXPECT_TRUE(parse(fmt, "+0000", utc, &tp));
01278     EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
01279     EXPECT_TRUE(parse(fmt, "-1234", utc, &tp));
01280     EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
01281     EXPECT_TRUE(parse(fmt, "+1234", utc, &tp));
01282     EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
01283     EXPECT_FALSE(parse(fmt, "-123", utc, &tp));
01284 
01285     EXPECT_TRUE(parse(fmt, "+00", utc, &tp));
01286     EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
01287     EXPECT_TRUE(parse(fmt, "-12", utc, &tp));
01288     EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
01289     EXPECT_TRUE(parse(fmt, "+12", utc, &tp));
01290     EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
01291     EXPECT_FALSE(parse(fmt, "-1", utc, &tp));
01292   }
01293 }
01294 
01295 TEST(Parse, ExtendedSecondOffset) {
01296   const time_zone utc = utc_time_zone();
01297   time_point<absl::time_internal::cctz::seconds> tp;
01298 
01299   for (auto fmt : {"%Ez", "%E*z", "%:z", "%::z", "%:::z"}) {
01300     EXPECT_TRUE(parse(fmt, "+00:00:00", utc, &tp));
01301     EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
01302     EXPECT_TRUE(parse(fmt, "-12:34:56", utc, &tp));
01303     EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
01304     EXPECT_TRUE(parse(fmt, "+12:34:56", utc, &tp));
01305     EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
01306     EXPECT_FALSE(parse(fmt, "-12:34:5", utc, &tp));
01307 
01308     EXPECT_TRUE(parse(fmt, "+000000", utc, &tp));
01309     EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
01310     EXPECT_TRUE(parse(fmt, "-123456", utc, &tp));
01311     EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
01312     EXPECT_TRUE(parse(fmt, "+123456", utc, &tp));
01313     EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
01314     EXPECT_FALSE(parse(fmt, "-12345", utc, &tp));
01315 
01316     EXPECT_TRUE(parse(fmt, "+00:00", utc, &tp));
01317     EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
01318     EXPECT_TRUE(parse(fmt, "-12:34", utc, &tp));
01319     EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
01320     EXPECT_TRUE(parse(fmt, "+12:34", utc, &tp));
01321     EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
01322     EXPECT_FALSE(parse(fmt, "-12:3", utc, &tp));
01323 
01324     EXPECT_TRUE(parse(fmt, "+0000", utc, &tp));
01325     EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
01326     EXPECT_TRUE(parse(fmt, "-1234", utc, &tp));
01327     EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
01328     EXPECT_TRUE(parse(fmt, "+1234", utc, &tp));
01329     EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
01330     EXPECT_FALSE(parse(fmt, "-123", utc, &tp));
01331 
01332     EXPECT_TRUE(parse(fmt, "+00", utc, &tp));
01333     EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
01334     EXPECT_TRUE(parse(fmt, "-12", utc, &tp));
01335     EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
01336     EXPECT_TRUE(parse(fmt, "+12", utc, &tp));
01337     EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
01338     EXPECT_FALSE(parse(fmt, "-1", utc, &tp));
01339   }
01340 }
01341 
01342 TEST(Parse, ExtendedYears) {
01343   const time_zone utc = utc_time_zone();
01344   const char e4y_fmt[] = "%E4Y%m%d";  // no separators
01345   time_point<absl::time_internal::cctz::seconds> tp;
01346 
01347   // %E4Y consumes exactly four chars, including any sign.
01348   EXPECT_TRUE(parse(e4y_fmt, "-9991127", utc, &tp));
01349   EXPECT_EQ(convert(civil_second(-999, 11, 27, 0, 0, 0), utc), tp);
01350   EXPECT_TRUE(parse(e4y_fmt, "-0991127", utc, &tp));
01351   EXPECT_EQ(convert(civil_second(-99, 11, 27, 0, 0, 0), utc), tp);
01352   EXPECT_TRUE(parse(e4y_fmt, "-0091127", utc, &tp));
01353   EXPECT_EQ(convert(civil_second(-9, 11, 27, 0, 0, 0), utc), tp);
01354   EXPECT_TRUE(parse(e4y_fmt, "-0011127", utc, &tp));
01355   EXPECT_EQ(convert(civil_second(-1, 11, 27, 0, 0, 0), utc), tp);
01356   EXPECT_TRUE(parse(e4y_fmt, "00001127", utc, &tp));
01357   EXPECT_EQ(convert(civil_second(0, 11, 27, 0, 0, 0), utc), tp);
01358   EXPECT_TRUE(parse(e4y_fmt, "00011127", utc, &tp));
01359   EXPECT_EQ(convert(civil_second(1, 11, 27, 0, 0, 0), utc), tp);
01360   EXPECT_TRUE(parse(e4y_fmt, "00091127", utc, &tp));
01361   EXPECT_EQ(convert(civil_second(9, 11, 27, 0, 0, 0), utc), tp);
01362   EXPECT_TRUE(parse(e4y_fmt, "00991127", utc, &tp));
01363   EXPECT_EQ(convert(civil_second(99, 11, 27, 0, 0, 0), utc), tp);
01364   EXPECT_TRUE(parse(e4y_fmt, "09991127", utc, &tp));
01365   EXPECT_EQ(convert(civil_second(999, 11, 27, 0, 0, 0), utc), tp);
01366   EXPECT_TRUE(parse(e4y_fmt, "99991127", utc, &tp));
01367   EXPECT_EQ(convert(civil_second(9999, 11, 27, 0, 0, 0), utc), tp);
01368 
01369   // When the year is outside [-999:9999], the parse fails.
01370   EXPECT_FALSE(parse(e4y_fmt, "-10001127", utc, &tp));
01371   EXPECT_FALSE(parse(e4y_fmt, "100001127", utc, &tp));
01372 }
01373 
01374 TEST(Parse, RFC3339Format) {
01375   const time_zone tz = utc_time_zone();
01376   time_point<chrono::nanoseconds> tp;
01377   EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00+00:00", tz, &tp));
01378   ExpectTime(tp, tz, 2014, 2, 12, 20, 21, 0, 0, false, "UTC");
01379 
01380   // Check that %Ez also accepts "Z" as a synonym for "+00:00".
01381   time_point<chrono::nanoseconds> tp2;
01382   EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00Z", tz, &tp2));
01383   EXPECT_EQ(tp, tp2);
01384 }
01385 
01386 TEST(Parse, MaxRange) {
01387   const time_zone utc = utc_time_zone();
01388   time_point<absl::time_internal::cctz::seconds> tp;
01389 
01390   // tests the upper limit using +00:00 offset
01391   EXPECT_TRUE(
01392       parse(RFC3339_sec, "292277026596-12-04T15:30:07+00:00", utc, &tp));
01393   EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::max());
01394   EXPECT_FALSE(
01395       parse(RFC3339_sec, "292277026596-12-04T15:30:08+00:00", utc, &tp));
01396 
01397   // tests the upper limit using -01:00 offset
01398   EXPECT_TRUE(
01399       parse(RFC3339_sec, "292277026596-12-04T14:30:07-01:00", utc, &tp));
01400   EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::max());
01401   EXPECT_FALSE(
01402       parse(RFC3339_sec, "292277026596-12-04T15:30:07-01:00", utc, &tp));
01403 
01404   // tests the lower limit using +00:00 offset
01405   EXPECT_TRUE(
01406       parse(RFC3339_sec, "-292277022657-01-27T08:29:52+00:00", utc, &tp));
01407   EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::min());
01408   EXPECT_FALSE(
01409       parse(RFC3339_sec, "-292277022657-01-27T08:29:51+00:00", utc, &tp));
01410 
01411   // tests the lower limit using +01:00 offset
01412   EXPECT_TRUE(
01413       parse(RFC3339_sec, "-292277022657-01-27T09:29:52+01:00", utc, &tp));
01414   EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::min());
01415   EXPECT_FALSE(
01416       parse(RFC3339_sec, "-292277022657-01-27T08:29:51+01:00", utc, &tp));
01417 
01418   // tests max/min civil-second overflow
01419   EXPECT_FALSE(parse(RFC3339_sec, "9223372036854775807-12-31T23:59:59-00:01",
01420                      utc, &tp));
01421   EXPECT_FALSE(parse(RFC3339_sec, "-9223372036854775808-01-01T00:00:00+00:01",
01422                      utc, &tp));
01423 
01424   // TODO: Add tests that parsing times with fractional seconds overflow
01425   // appropriately. This can't be done until cctz::parse() properly detects
01426   // overflow when combining the chrono seconds and femto.
01427 }
01428 
01429 //
01430 // Roundtrip test for format()/parse().
01431 //
01432 
01433 TEST(FormatParse, RoundTrip) {
01434   time_zone lax;
01435   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &lax));
01436   const auto in = convert(civil_second(1977, 6, 28, 9, 8, 7), lax);
01437   const auto subseconds = chrono::nanoseconds(654321);
01438 
01439   // RFC3339, which renders subseconds.
01440   {
01441     time_point<chrono::nanoseconds> out;
01442     const std::string s = format(RFC3339_full, in + subseconds, lax);
01443     EXPECT_TRUE(parse(RFC3339_full, s, lax, &out)) << s;
01444     EXPECT_EQ(in + subseconds, out);  // RFC3339_full includes %Ez
01445   }
01446 
01447   // RFC1123, which only does whole seconds.
01448   {
01449     time_point<chrono::nanoseconds> out;
01450     const std::string s = format(RFC1123_full, in, lax);
01451     EXPECT_TRUE(parse(RFC1123_full, s, lax, &out)) << s;
01452     EXPECT_EQ(in, out);  // RFC1123_full includes %z
01453   }
01454 
01455 #if defined(_WIN32) || defined(_WIN64)
01456   // Initial investigations indicate the %c does not roundtrip on Windows.
01457   // TODO: Figure out what is going on here (perhaps a locale problem).
01458 #elif defined(__EMSCRIPTEN__)
01459   // strftime() and strptime() use different defintions for "%c" under
01460   // emscripten (see https://github.com/kripken/emscripten/pull/7491),
01461   // causing its round-trip test to fail.
01462 #else
01463   // Even though we don't know what %c will produce, it should roundtrip,
01464   // but only in the 0-offset timezone.
01465   {
01466     time_point<chrono::nanoseconds> out;
01467     time_zone utc = utc_time_zone();
01468     const std::string s = format("%c", in, utc);
01469     EXPECT_TRUE(parse("%c", s, utc, &out)) << s;
01470     EXPECT_EQ(in, out);
01471   }
01472 #endif
01473 }
01474 
01475 TEST(FormatParse, RoundTripDistantFuture) {
01476   const time_zone utc = utc_time_zone();
01477   const time_point<absl::time_internal::cctz::seconds> in = time_point<absl::time_internal::cctz::seconds>::max();
01478   const std::string s = format(RFC3339_full, in, utc);
01479   time_point<absl::time_internal::cctz::seconds> out;
01480   EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;
01481   EXPECT_EQ(in, out);
01482 }
01483 
01484 TEST(FormatParse, RoundTripDistantPast) {
01485   const time_zone utc = utc_time_zone();
01486   const time_point<absl::time_internal::cctz::seconds> in = time_point<absl::time_internal::cctz::seconds>::min();
01487   const std::string s = format(RFC3339_full, in, utc);
01488   time_point<absl::time_internal::cctz::seconds> out;
01489   EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;
01490   EXPECT_EQ(in, out);
01491 }
01492 
01493 }  // namespace cctz
01494 }  // namespace time_internal
01495 }  // namespace absl


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:15