1 // Copyright 2016 Google Inc. All Rights Reserved.
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 //   http://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 #include "cctz/time_zone.h"
16 
17 #include <chrono>
18 #include <iomanip>
19 #include <sstream>
20 #include <string>
21 
22 #include "cctz/civil_time.h"
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 
26 using std::chrono::time_point_cast;
27 using std::chrono::system_clock;
28 using std::chrono::nanoseconds;
29 using std::chrono::microseconds;
30 using std::chrono::milliseconds;
31 using std::chrono::seconds;
32 using std::chrono::minutes;
33 using std::chrono::hours;
34 using testing::HasSubstr;
35 
36 namespace cctz {
37 
38 namespace {
39 
40 // This helper is a macro so that failed expectations show up with the
41 // correct line numbers.
42 #define ExpectTime(tp, tz, y, m, d, hh, mm, ss, off, isdst, zone) \
43   do {                                                            \
44     time_zone::absolute_lookup al = tz.lookup(tp);                \
45     EXPECT_EQ(y, al.cs.year());                                   \
46     EXPECT_EQ(m, al.cs.month());                                  \
47     EXPECT_EQ(d, al.cs.day());                                    \
48     EXPECT_EQ(hh, al.cs.hour());                                  \
49     EXPECT_EQ(mm, al.cs.minute());                                \
50     EXPECT_EQ(ss, al.cs.second());                                \
51     EXPECT_EQ(off, al.offset);                                    \
52     EXPECT_TRUE(isdst == al.is_dst);                              \
53     EXPECT_STREQ(zone, al.abbr);                                  \
54   } while (0)
55 
56 const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
57 const char RFC3339_sec[] =  "%Y-%m-%dT%H:%M:%S%Ez";
58 
59 const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z";
60 const char RFC1123_no_wday[] =  "%d %b %Y %H:%M:%S %z";
61 
62 // A helper that tests the given format specifier by itself, and with leading
63 // and trailing characters.  For example: TestFormatSpecifier(tp, "%a", "Thu").
64 template <typename D>
TestFormatSpecifier(time_point<D> tp,time_zone tz,const std::string & fmt,const std::string & ans)65 void TestFormatSpecifier(time_point<D> tp, time_zone tz, const std::string& fmt,
66                          const std::string& ans) {
67   EXPECT_EQ(ans, format(fmt, tp, tz)) << fmt;
68   EXPECT_EQ("xxx " + ans, format("xxx " + fmt, tp, tz));
69   EXPECT_EQ(ans + " yyy", format(fmt + " yyy", tp, tz));
70   EXPECT_EQ("xxx " + ans + " yyy", format("xxx " + fmt + " yyy", tp, tz));
71 }
72 
73 }  // namespace
74 
75 //
76 // Testing format()
77 //
78 
TEST(Format,TimePointResolution)79 TEST(Format, TimePointResolution) {
80   const char kFmt[] = "%H:%M:%E*S";
81   const time_zone utc = utc_time_zone();
82   const time_point<nanoseconds> t0 = system_clock::from_time_t(1420167845) +
83                                      milliseconds(123) + microseconds(456) +
84                                      nanoseconds(789);
85   EXPECT_EQ("03:04:05.123456789",
86             format(kFmt, time_point_cast<nanoseconds>(t0), utc));
87   EXPECT_EQ("03:04:05.123456",
88             format(kFmt, time_point_cast<microseconds>(t0), utc));
89   EXPECT_EQ("03:04:05.123",
90             format(kFmt, time_point_cast<milliseconds>(t0), utc));
91   EXPECT_EQ("03:04:05",
92             format(kFmt, time_point_cast<seconds>(t0), utc));
93   EXPECT_EQ("03:04:05",
94             format(kFmt, time_point_cast<sys_seconds>(t0), utc));
95   EXPECT_EQ("03:04:00",
96             format(kFmt, time_point_cast<minutes>(t0), utc));
97   EXPECT_EQ("03:00:00",
98             format(kFmt, time_point_cast<hours>(t0), utc));
99 }
100 
TEST(Format,TimePointExtendedResolution)101 TEST(Format, TimePointExtendedResolution) {
102   const char kFmt[] = "%H:%M:%E*S";
103   const time_zone utc = utc_time_zone();
104   const time_point<sys_seconds> tp =
105       std::chrono::time_point_cast<sys_seconds>(
106           std::chrono::system_clock::from_time_t(0)) +
107       std::chrono::hours(12) + std::chrono::minutes(34) +
108       std::chrono::seconds(56);
109 
110   EXPECT_EQ(
111       "12:34:56.123456789012345",
112       detail::format(kFmt, tp, detail::femtoseconds(123456789012345), utc));
113   EXPECT_EQ(
114       "12:34:56.012345678901234",
115       detail::format(kFmt, tp, detail::femtoseconds(12345678901234), utc));
116   EXPECT_EQ(
117       "12:34:56.001234567890123",
118       detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc));
119   EXPECT_EQ(
120       "12:34:56.000123456789012",
121       detail::format(kFmt, tp, detail::femtoseconds(123456789012), utc));
122 
123   EXPECT_EQ("12:34:56.000000000000123",
124             detail::format(kFmt, tp, detail::femtoseconds(123), utc));
125   EXPECT_EQ("12:34:56.000000000000012",
126             detail::format(kFmt, tp, detail::femtoseconds(12), utc));
127   EXPECT_EQ("12:34:56.000000000000001",
128             detail::format(kFmt, tp, detail::femtoseconds(1), utc));
129 }
130 
TEST(Format,Basics)131 TEST(Format, Basics) {
132   time_zone tz = utc_time_zone();
133   time_point<nanoseconds> tp = system_clock::from_time_t(0);
134 
135   // Starts with a couple basic edge cases.
136   EXPECT_EQ("", format("", tp, tz));
137   EXPECT_EQ(" ", format(" ", tp, tz));
138   EXPECT_EQ("  ", format("  ", tp, tz));
139   EXPECT_EQ("xxx", format("xxx", tp, tz));
140   std::string big(128, 'x');
141   EXPECT_EQ(big, format(big, tp, tz));
142   // Cause the 1024-byte buffer to grow.
143   std::string bigger(100000, 'x');
144   EXPECT_EQ(bigger, format(bigger, tp, tz));
145 
146   tp += hours(13) + minutes(4) + seconds(5);
147   tp += milliseconds(6) + microseconds(7) + nanoseconds(8);
148   EXPECT_EQ("1970-01-01", format("%Y-%m-%d", tp, tz));
149   EXPECT_EQ("13:04:05", format("%H:%M:%S", tp, tz));
150   EXPECT_EQ("13:04:05.006", format("%H:%M:%E3S", tp, tz));
151   EXPECT_EQ("13:04:05.006007", format("%H:%M:%E6S", tp, tz));
152   EXPECT_EQ("13:04:05.006007008", format("%H:%M:%E9S", tp, tz));
153 }
154 
TEST(Format,PosixConversions)155 TEST(Format, PosixConversions) {
156   const time_zone tz = utc_time_zone();
157   auto tp = system_clock::from_time_t(0);
158 
159   TestFormatSpecifier(tp, tz, "%d", "01");
160   TestFormatSpecifier(tp, tz, "%e", " 1");  // extension but internal support
161   TestFormatSpecifier(tp, tz, "%H", "00");
162   TestFormatSpecifier(tp, tz, "%I", "12");
163   TestFormatSpecifier(tp, tz, "%j", "001");
164   TestFormatSpecifier(tp, tz, "%m", "01");
165   TestFormatSpecifier(tp, tz, "%M", "00");
166   TestFormatSpecifier(tp, tz, "%S", "00");
167   TestFormatSpecifier(tp, tz, "%U", "00");
168   TestFormatSpecifier(tp, tz, "%w", "4");  // 4=Thursday
169   TestFormatSpecifier(tp, tz, "%W", "00");
170   TestFormatSpecifier(tp, tz, "%y", "70");
171   TestFormatSpecifier(tp, tz, "%Y", "1970");
172   TestFormatSpecifier(tp, tz, "%z", "+0000");
173   TestFormatSpecifier(tp, tz, "%Z", "UTC");
174   TestFormatSpecifier(tp, tz, "%%", "%");
175 
176 #if defined(__linux__)
177   // SU/C99/TZ extensions
178   TestFormatSpecifier(tp, tz, "%C", "19");
179   TestFormatSpecifier(tp, tz, "%D", "01/01/70");
180   TestFormatSpecifier(tp, tz, "%F", "1970-01-01");
181   TestFormatSpecifier(tp, tz, "%g", "70");
182   TestFormatSpecifier(tp, tz, "%G", "1970");
183   TestFormatSpecifier(tp, tz, "%k", " 0");
184   TestFormatSpecifier(tp, tz, "%l", "12");
185   TestFormatSpecifier(tp, tz, "%n", "\n");
186   TestFormatSpecifier(tp, tz, "%R", "00:00");
187   TestFormatSpecifier(tp, tz, "%t", "\t");
188   TestFormatSpecifier(tp, tz, "%T", "00:00:00");
189   TestFormatSpecifier(tp, tz, "%u", "4");  // 4=Thursday
190   TestFormatSpecifier(tp, tz, "%V", "01");
191   TestFormatSpecifier(tp, tz, "%s", "0");
192 #endif
193 }
194 
TEST(Format,LocaleSpecific)195 TEST(Format, LocaleSpecific) {
196   const time_zone tz = utc_time_zone();
197   auto tp = system_clock::from_time_t(0);
198 
199   TestFormatSpecifier(tp, tz, "%a", "Thu");
200   TestFormatSpecifier(tp, tz, "%A", "Thursday");
201   TestFormatSpecifier(tp, tz, "%b", "Jan");
202   TestFormatSpecifier(tp, tz, "%B", "January");
203 
204   // %c should at least produce the numeric year and time-of-day.
205   const std::string s = format("%c", tp, utc_time_zone());
206   EXPECT_THAT(s, HasSubstr("1970"));
207   EXPECT_THAT(s, HasSubstr("00:00:00"));
208 
209   TestFormatSpecifier(tp, tz, "%p", "AM");
210   TestFormatSpecifier(tp, tz, "%x", "01/01/70");
211   TestFormatSpecifier(tp, tz, "%X", "00:00:00");
212 
213 #if defined(__linux__)
214   // SU/C99/TZ extensions
215   TestFormatSpecifier(tp, tz, "%h", "Jan");  // Same as %b
216   TestFormatSpecifier(tp, tz, "%P", "am");
217   TestFormatSpecifier(tp, tz, "%r", "12:00:00 AM");
218 
219   // Modified conversion specifiers %E_
220   TestFormatSpecifier(tp, tz, "%Ec", "Thu Jan  1 00:00:00 1970");
221   TestFormatSpecifier(tp, tz, "%EC", "19");
222   TestFormatSpecifier(tp, tz, "%Ex", "01/01/70");
223   TestFormatSpecifier(tp, tz, "%EX", "00:00:00");
224   TestFormatSpecifier(tp, tz, "%Ey", "70");
225   TestFormatSpecifier(tp, tz, "%EY", "1970");
226 
227   // Modified conversion specifiers %O_
228   TestFormatSpecifier(tp, tz, "%Od", "01");
229   TestFormatSpecifier(tp, tz, "%Oe", " 1");
230   TestFormatSpecifier(tp, tz, "%OH", "00");
231   TestFormatSpecifier(tp, tz, "%OI", "12");
232   TestFormatSpecifier(tp, tz, "%Om", "01");
233   TestFormatSpecifier(tp, tz, "%OM", "00");
234   TestFormatSpecifier(tp, tz, "%OS", "00");
235   TestFormatSpecifier(tp, tz, "%Ou", "4");  // 4=Thursday
236   TestFormatSpecifier(tp, tz, "%OU", "00");
237   TestFormatSpecifier(tp, tz, "%OV", "01");
238   TestFormatSpecifier(tp, tz, "%Ow", "4");  // 4=Thursday
239   TestFormatSpecifier(tp, tz, "%OW", "00");
240   TestFormatSpecifier(tp, tz, "%Oy", "70");
241 #endif
242 }
243 
TEST(Format,Escaping)244 TEST(Format, Escaping) {
245   const time_zone tz = utc_time_zone();
246   auto tp = system_clock::from_time_t(0);
247 
248   TestFormatSpecifier(tp, tz, "%%", "%");
249   TestFormatSpecifier(tp, tz, "%%a", "%a");
250   TestFormatSpecifier(tp, tz, "%%b", "%b");
251   TestFormatSpecifier(tp, tz, "%%Ea", "%Ea");
252   TestFormatSpecifier(tp, tz, "%%Es", "%Es");
253   TestFormatSpecifier(tp, tz, "%%E3S", "%E3S");
254   TestFormatSpecifier(tp, tz, "%%OS", "%OS");
255   TestFormatSpecifier(tp, tz, "%%O3S", "%O3S");
256 
257   // Multiple levels of escaping.
258   TestFormatSpecifier(tp, tz, "%%%Y", "%1970");
259   TestFormatSpecifier(tp, tz, "%%%E3S", "%00.000");
260   TestFormatSpecifier(tp, tz, "%%%%E3S", "%%E3S");
261 }
262 
TEST(Format,ExtendedSeconds)263 TEST(Format, ExtendedSeconds) {
264   const time_zone tz = utc_time_zone();
265 
266   // No subseconds.
267   time_point<nanoseconds> tp = system_clock::from_time_t(0);
268   tp += seconds(5);
269   EXPECT_EQ("05", format("%E*S", tp, tz));
270   EXPECT_EQ("05", format("%E0S", tp, tz));
271   EXPECT_EQ("05.0", format("%E1S", tp, tz));
272   EXPECT_EQ("05.00", format("%E2S", tp, tz));
273   EXPECT_EQ("05.000", format("%E3S", tp, tz));
274   EXPECT_EQ("05.0000", format("%E4S", tp, tz));
275   EXPECT_EQ("05.00000", format("%E5S", tp, tz));
276   EXPECT_EQ("05.000000", format("%E6S", tp, tz));
277   EXPECT_EQ("05.0000000", format("%E7S", tp, tz));
278   EXPECT_EQ("05.00000000", format("%E8S", tp, tz));
279   EXPECT_EQ("05.000000000", format("%E9S", tp, tz));
280   EXPECT_EQ("05.0000000000", format("%E10S", tp, tz));
281   EXPECT_EQ("05.00000000000", format("%E11S", tp, tz));
282   EXPECT_EQ("05.000000000000", format("%E12S", tp, tz));
283   EXPECT_EQ("05.0000000000000", format("%E13S", tp, tz));
284   EXPECT_EQ("05.00000000000000", format("%E14S", tp, tz));
285   EXPECT_EQ("05.000000000000000", format("%E15S", tp, tz));
286 
287   // With subseconds.
288   tp += milliseconds(6) + microseconds(7) + nanoseconds(8);
289   EXPECT_EQ("05.006007008", format("%E*S", tp, tz));
290   EXPECT_EQ("05", format("%E0S", tp, tz));
291   EXPECT_EQ("05.0", format("%E1S", tp, tz));
292   EXPECT_EQ("05.00", format("%E2S", tp, tz));
293   EXPECT_EQ("05.006", format("%E3S", tp, tz));
294   EXPECT_EQ("05.0060", format("%E4S", tp, tz));
295   EXPECT_EQ("05.00600", format("%E5S", tp, tz));
296   EXPECT_EQ("05.006007", format("%E6S", tp, tz));
297   EXPECT_EQ("05.0060070", format("%E7S", tp, tz));
298   EXPECT_EQ("05.00600700", format("%E8S", tp, tz));
299   EXPECT_EQ("05.006007008", format("%E9S", tp, tz));
300   EXPECT_EQ("05.0060070080", format("%E10S", tp, tz));
301   EXPECT_EQ("05.00600700800", format("%E11S", tp, tz));
302   EXPECT_EQ("05.006007008000", format("%E12S", tp, tz));
303   EXPECT_EQ("05.0060070080000", format("%E13S", tp, tz));
304   EXPECT_EQ("05.00600700800000", format("%E14S", tp, tz));
305   EXPECT_EQ("05.006007008000000", format("%E15S", tp, tz));
306 
307   // Times before the Unix epoch.
308   tp = system_clock::from_time_t(0) + microseconds(-1);
309   EXPECT_EQ("1969-12-31 23:59:59.999999",
310             format("%Y-%m-%d %H:%M:%E*S", tp, tz));
311 
312   // Here is a "%E*S" case we got wrong for a while.  While the first
313   // instant below is correctly rendered as "...:07.333304", the second
314   // one used to appear as "...:07.33330499999999999".
315   tp = system_clock::from_time_t(0) + microseconds(1395024427333304);
316   EXPECT_EQ("2014-03-17 02:47:07.333304",
317             format("%Y-%m-%d %H:%M:%E*S", tp, tz));
318   tp += microseconds(1);
319   EXPECT_EQ("2014-03-17 02:47:07.333305",
320             format("%Y-%m-%d %H:%M:%E*S", tp, tz));
321 }
322 
TEST(Format,ExtendedSubeconds)323 TEST(Format, ExtendedSubeconds) {
324   const time_zone tz = utc_time_zone();
325 
326   // No subseconds.
327   time_point<nanoseconds> tp = system_clock::from_time_t(0);
328   tp += seconds(5);
329   EXPECT_EQ("0", format("%E*f", tp, tz));
330   EXPECT_EQ("", format("%E0f", tp, tz));
331   EXPECT_EQ("0", format("%E1f", tp, tz));
332   EXPECT_EQ("00", format("%E2f", tp, tz));
333   EXPECT_EQ("000", format("%E3f", tp, tz));
334   EXPECT_EQ("0000", format("%E4f", tp, tz));
335   EXPECT_EQ("00000", format("%E5f", tp, tz));
336   EXPECT_EQ("000000", format("%E6f", tp, tz));
337   EXPECT_EQ("0000000", format("%E7f", tp, tz));
338   EXPECT_EQ("00000000", format("%E8f", tp, tz));
339   EXPECT_EQ("000000000", format("%E9f", tp, tz));
340   EXPECT_EQ("0000000000", format("%E10f", tp, tz));
341   EXPECT_EQ("00000000000", format("%E11f", tp, tz));
342   EXPECT_EQ("000000000000", format("%E12f", tp, tz));
343   EXPECT_EQ("0000000000000", format("%E13f", tp, tz));
344   EXPECT_EQ("00000000000000", format("%E14f", tp, tz));
345   EXPECT_EQ("000000000000000", format("%E15f", tp, tz));
346 
347   // With subseconds.
348   tp += milliseconds(6) + microseconds(7) + nanoseconds(8);
349   EXPECT_EQ("006007008", format("%E*f", tp, tz));
350   EXPECT_EQ("", format("%E0f", tp, tz));
351   EXPECT_EQ("0", format("%E1f", tp, tz));
352   EXPECT_EQ("00", format("%E2f", tp, tz));
353   EXPECT_EQ("006", format("%E3f", tp, tz));
354   EXPECT_EQ("0060", format("%E4f", tp, tz));
355   EXPECT_EQ("00600", format("%E5f", tp, tz));
356   EXPECT_EQ("006007", format("%E6f", tp, tz));
357   EXPECT_EQ("0060070", format("%E7f", tp, tz));
358   EXPECT_EQ("00600700", format("%E8f", tp, tz));
359   EXPECT_EQ("006007008", format("%E9f", tp, tz));
360   EXPECT_EQ("0060070080", format("%E10f", tp, tz));
361   EXPECT_EQ("00600700800", format("%E11f", tp, tz));
362   EXPECT_EQ("006007008000", format("%E12f", tp, tz));
363   EXPECT_EQ("0060070080000", format("%E13f", tp, tz));
364   EXPECT_EQ("00600700800000", format("%E14f", tp, tz));
365   EXPECT_EQ("006007008000000", format("%E15f", tp, tz));
366 
367   // Times before the Unix epoch.
368   tp = system_clock::from_time_t(0) + microseconds(-1);
369   EXPECT_EQ("1969-12-31 23:59:59.999999",
370             format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz));
371 
372   // Here is a "%E*S" case we got wrong for a while.  While the first
373   // instant below is correctly rendered as "...:07.333304", the second
374   // one used to appear as "...:07.33330499999999999".
375   tp = system_clock::from_time_t(0) + microseconds(1395024427333304);
376   EXPECT_EQ("2014-03-17 02:47:07.333304",
377             format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz));
378   tp += microseconds(1);
379   EXPECT_EQ("2014-03-17 02:47:07.333305",
380             format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz));
381 }
382 
TEST(Format,CompareExtendSecondsVsSubseconds)383 TEST(Format, CompareExtendSecondsVsSubseconds) {
384   const time_zone tz = utc_time_zone();
385 
386   // This test case illustrates the differences/similarities between:
387   //   fmt_A: %E<prec>S
388   //   fmt_B: %S.%E<prec>f
389   auto fmt_A = [](const std::string& prec) { return "%E" + prec + "S"; };
390   auto fmt_B = [](const std::string& prec) { return "%S.%E" + prec + "f"; };
391 
392   // No subseconds:
393   time_point<nanoseconds> tp = system_clock::from_time_t(0);
394   tp += seconds(5);
395   // ... %E*S and %S.%E*f are different.
396   EXPECT_EQ("05", format(fmt_A("*"), tp, tz));
397   EXPECT_EQ("05.0", format(fmt_B("*"), tp, tz));
398   // ... %E0S and %S.%E0f are different.
399   EXPECT_EQ("05", format(fmt_A("0"), tp, tz));
400   EXPECT_EQ("05.", format(fmt_B("0"), tp, tz));
401   // ... %E<prec>S and %S.%E<prec>f are the same for prec in [1:15].
402   for (int prec = 1; prec <= 15; ++prec) {
403     const std::string a = format(fmt_A(std::to_string(prec)), tp, tz);
404     const std::string b = format(fmt_B(std::to_string(prec)), tp, tz);
405     EXPECT_EQ(a, b) << "prec=" << prec;
406   }
407 
408   // With subseconds:
409   // ... %E*S and %S.%E*f are the same.
410   tp += milliseconds(6) + microseconds(7) + nanoseconds(8);
411   EXPECT_EQ("05.006007008", format(fmt_A("*"), tp, tz));
412   EXPECT_EQ("05.006007008", format(fmt_B("*"), tp, tz));
413   // ... %E0S and %S.%E0f are different.
414   EXPECT_EQ("05", format(fmt_A("0"), tp, tz));
415   EXPECT_EQ("05.", format(fmt_B("0"), tp, tz));
416   // ... %E<prec>S and %S.%E<prec>f are the same for prec in [1:15].
417   for (int prec = 1; prec <= 15; ++prec) {
418     const std::string a = format(fmt_A(std::to_string(prec)), tp, tz);
419     const std::string b = format(fmt_B(std::to_string(prec)), tp, tz);
420     EXPECT_EQ(a, b) << "prec=" << prec;
421   }
422 }
423 
TEST(Format,ExtendedOffset)424 TEST(Format, ExtendedOffset) {
425   auto tp = system_clock::from_time_t(0);
426 
427   time_zone tz = utc_time_zone();
428   TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
429 
430   EXPECT_TRUE(load_time_zone("America/New_York", &tz));
431   TestFormatSpecifier(tp, tz, "%Ez", "-05:00");
432 
433   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
434   TestFormatSpecifier(tp, tz, "%Ez", "-08:00");
435 
436   EXPECT_TRUE(load_time_zone("Australia/Sydney", &tz));
437   TestFormatSpecifier(tp, tz, "%Ez", "+10:00");
438 
439   EXPECT_TRUE(load_time_zone("Africa/Monrovia", &tz));
440   // The true offset is -00:44:30 but %z only gives (truncated) minutes.
441   TestFormatSpecifier(tp, tz, "%z", "-0044");
442   TestFormatSpecifier(tp, tz, "%Ez", "-00:44");
443 }
444 
TEST(Format,ExtendedYears)445 TEST(Format, ExtendedYears) {
446   const time_zone utc = utc_time_zone();
447   const char e4y_fmt[] = "%E4Y%m%d";  // no separators
448 
449   // %E4Y zero-pads the year to produce at least 4 chars, including the sign.
450   auto tp = convert(civil_second(-999, 11, 27, 0, 0, 0), utc);
451   EXPECT_EQ("-9991127", format(e4y_fmt, tp, utc));
452   tp = convert(civil_second(-99, 11, 27, 0, 0, 0), utc);
453   EXPECT_EQ("-0991127", format(e4y_fmt, tp, utc));
454   tp = convert(civil_second(-9, 11, 27, 0, 0, 0), utc);
455   EXPECT_EQ("-0091127", format(e4y_fmt, tp, utc));
456   tp = convert(civil_second(-1, 11, 27, 0, 0, 0), utc);
457   EXPECT_EQ("-0011127", format(e4y_fmt, tp, utc));
458   tp = convert(civil_second(0, 11, 27, 0, 0, 0), utc);
459   EXPECT_EQ("00001127", format(e4y_fmt, tp, utc));
460   tp = convert(civil_second(1, 11, 27, 0, 0, 0), utc);
461   EXPECT_EQ("00011127", format(e4y_fmt, tp, utc));
462   tp = convert(civil_second(9, 11, 27, 0, 0, 0), utc);
463   EXPECT_EQ("00091127", format(e4y_fmt, tp, utc));
464   tp = convert(civil_second(99, 11, 27, 0, 0, 0), utc);
465   EXPECT_EQ("00991127", format(e4y_fmt, tp, utc));
466   tp = convert(civil_second(999, 11, 27, 0, 0, 0), utc);
467   EXPECT_EQ("09991127", format(e4y_fmt, tp, utc));
468   tp = convert(civil_second(9999, 11, 27, 0, 0, 0), utc);
469   EXPECT_EQ("99991127", format(e4y_fmt, tp, utc));
470 
471   // When the year is outside [-999:9999], more than 4 chars are produced.
472   tp = convert(civil_second(-1000, 11, 27, 0, 0, 0), utc);
473   EXPECT_EQ("-10001127", format(e4y_fmt, tp, utc));
474   tp = convert(civil_second(10000, 11, 27, 0, 0, 0), utc);
475   EXPECT_EQ("100001127", format(e4y_fmt, tp, utc));
476 }
477 
TEST(Format,RFC3339Format)478 TEST(Format, RFC3339Format) {
479   time_zone tz;
480   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
481 
482   time_point<nanoseconds> tp =
483       convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
484   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_full, tp, tz));
485   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
486 
487   tp += milliseconds(100);
488   EXPECT_EQ("1977-06-28T09:08:07.1-07:00", format(RFC3339_full, tp, tz));
489   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
490 
491   tp += milliseconds(20);
492   EXPECT_EQ("1977-06-28T09:08:07.12-07:00", format(RFC3339_full, tp, tz));
493   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
494 
495   tp += milliseconds(3);
496   EXPECT_EQ("1977-06-28T09:08:07.123-07:00", format(RFC3339_full, tp, tz));
497   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
498 
499   tp += microseconds(400);
500   EXPECT_EQ("1977-06-28T09:08:07.1234-07:00", format(RFC3339_full, tp, tz));
501   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
502 
503   tp += microseconds(50);
504   EXPECT_EQ("1977-06-28T09:08:07.12345-07:00", format(RFC3339_full, tp, tz));
505   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
506 
507   tp += microseconds(6);
508   EXPECT_EQ("1977-06-28T09:08:07.123456-07:00", format(RFC3339_full, tp, tz));
509   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
510 
511   tp += nanoseconds(700);
512   EXPECT_EQ("1977-06-28T09:08:07.1234567-07:00", format(RFC3339_full, tp, tz));
513   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
514 
515   tp += nanoseconds(80);
516   EXPECT_EQ("1977-06-28T09:08:07.12345678-07:00", format(RFC3339_full, tp, tz));
517   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
518 
519   tp += nanoseconds(9);
520   EXPECT_EQ("1977-06-28T09:08:07.123456789-07:00",
521             format(RFC3339_full, tp, tz));
522   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
523 }
524 
TEST(Format,RFC1123Format)525 TEST(Format, RFC1123Format) {  // locale specific
526   time_zone tz;
527   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
528 
529   auto tp = convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
530   EXPECT_EQ("Tue, 28 Jun 1977 09:08:07 -0700", format(RFC1123_full, tp, tz));
531   EXPECT_EQ("28 Jun 1977 09:08:07 -0700", format(RFC1123_no_wday, tp, tz));
532 }
533 
534 //
535 // Testing parse()
536 //
537 
TEST(Parse,TimePointResolution)538 TEST(Parse, TimePointResolution) {
539   const char kFmt[] = "%H:%M:%E*S";
540   const time_zone utc = utc_time_zone();
541 
542   time_point<nanoseconds> tp_ns;
543   EXPECT_TRUE(parse(kFmt, "03:04:05.123456789", utc, &tp_ns));
544   EXPECT_EQ("03:04:05.123456789", format(kFmt, tp_ns, utc));
545   EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_ns));
546   EXPECT_EQ("03:04:05.123456", format(kFmt, tp_ns, utc));
547 
548   time_point<microseconds> tp_us;
549   EXPECT_TRUE(parse(kFmt, "03:04:05.123456789", utc, &tp_us));
550   EXPECT_EQ("03:04:05.123456", format(kFmt, tp_us, utc));
551   EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_us));
552   EXPECT_EQ("03:04:05.123456", format(kFmt, tp_us, utc));
553   EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_us));
554   EXPECT_EQ("03:04:05.123", format(kFmt, tp_us, utc));
555 
556   time_point<milliseconds> tp_ms;
557   EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_ms));
558   EXPECT_EQ("03:04:05.123", format(kFmt, tp_ms, utc));
559   EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_ms));
560   EXPECT_EQ("03:04:05.123", format(kFmt, tp_ms, utc));
561   EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_ms));
562   EXPECT_EQ("03:04:05", format(kFmt, tp_ms, utc));
563 
564   time_point<seconds> tp_s;
565   EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_s));
566   EXPECT_EQ("03:04:05", format(kFmt, tp_s, utc));
567   EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_s));
568   EXPECT_EQ("03:04:05", format(kFmt, tp_s, utc));
569 
570   time_point<minutes> tp_m;
571   EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_m));
572   EXPECT_EQ("03:04:00", format(kFmt, tp_m, utc));
573 
574   time_point<hours> tp_h;
575   EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_h));
576   EXPECT_EQ("03:00:00", format(kFmt, tp_h, utc));
577 }
578 
TEST(Parse,TimePointExtendedResolution)579 TEST(Parse, TimePointExtendedResolution) {
580   const char kFmt[] = "%H:%M:%E*S";
581   const time_zone utc = utc_time_zone();
582 
583   time_point<sys_seconds> tp;
584   detail::femtoseconds fs;
585   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.123456789012345", utc, &tp, &fs));
586   EXPECT_EQ("12:34:56.123456789012345", detail::format(kFmt, tp, fs, utc));
587   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.012345678901234", utc, &tp, &fs));
588   EXPECT_EQ("12:34:56.012345678901234", detail::format(kFmt, tp, fs, utc));
589   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.001234567890123", utc, &tp, &fs));
590   EXPECT_EQ("12:34:56.001234567890123", detail::format(kFmt, tp, fs, utc));
591   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000123", utc, &tp, &fs));
592   EXPECT_EQ("12:34:56.000000000000123", detail::format(kFmt, tp, fs, utc));
593   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000012", utc, &tp, &fs));
594   EXPECT_EQ("12:34:56.000000000000012", detail::format(kFmt, tp, fs, utc));
595   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000001", utc, &tp, &fs));
596   EXPECT_EQ("12:34:56.000000000000001", detail::format(kFmt, tp, fs, utc));
597 }
598 
TEST(Parse,Basics)599 TEST(Parse, Basics) {
600   time_zone tz = utc_time_zone();
601   time_point<nanoseconds> tp = system_clock::from_time_t(1234567890);
602 
603   // Simple edge cases.
604   EXPECT_TRUE(parse("", "", tz, &tp));
605   EXPECT_EQ(system_clock::from_time_t(0), tp);  // everything defaulted
606   EXPECT_TRUE(parse(" ", " ", tz, &tp));
607   EXPECT_TRUE(parse("  ", "  ", tz, &tp));
608   EXPECT_TRUE(parse("x", "x", tz, &tp));
609   EXPECT_TRUE(parse("xxx", "xxx", tz, &tp));
610 
611   EXPECT_TRUE(
612       parse("%Y-%m-%d %H:%M:%S %z", "2013-06-28 19:08:09 -0800", tz, &tp));
613   ExpectTime(tp, tz, 2013, 6, 29, 3, 8, 9, 0, false, "UTC");
614 }
615 
TEST(Parse,WithTimeZone)616 TEST(Parse, WithTimeZone) {
617   time_zone tz;
618   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
619   time_point<nanoseconds> tp;
620 
621   // We can parse a string without a UTC offset if we supply a timezone.
622   EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &tp));
623   ExpectTime(tp, tz, 2013, 6, 28, 19, 8, 9, -7 * 60 * 60, true, "PDT");
624 
625   // But the timezone is ignored when a UTC offset is present.
626   EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S %z", "2013-06-28 19:08:09 +0800",
627                     utc_time_zone(), &tp));
628   ExpectTime(tp, tz, 2013, 6, 28, 19 - 8 - 7, 8, 9, -7 * 60 * 60, true, "PDT");
629 
630   // Check a skipped time (a Spring DST transition).  parse() returns
631   // the preferred-offset result, as defined for ConvertDateTime().
632   EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2011-03-13 02:15:00", tz, &tp));
633   ExpectTime(tp, tz, 2011, 3, 13, 3, 15, 0, -7 * 60 * 60, true, "PDT");
634 
635   // Check a repeated time (a Fall DST transition).  parse() returns
636   // the preferred-offset result, as defined for ConvertDateTime().
637   EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2011-11-06 01:15:00", tz, &tp));
638   ExpectTime(tp, tz, 2011, 11, 6, 1, 15, 0, -7 * 60 * 60, true, "PDT");
639 }
640 
TEST(Parse,LeapSecond)641 TEST(Parse, LeapSecond) {
642   time_zone tz;
643   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
644   time_point<nanoseconds> tp;
645 
646   // ":59" -> ":59"
647   EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:59-08:00", tz, &tp));
648   ExpectTime(tp, tz, 2013, 6, 28, 8, 8, 59, -7 * 60 * 60, true, "PDT");
649 
650   // ":59.5" -> ":59.5"
651   EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:59.5-08:00", tz, &tp));
652   ExpectTime(tp, tz, 2013, 6, 28, 8, 8, 59, -7 * 60 * 60, true, "PDT");
653 
654   // ":60" -> ":00"
655   EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:60-08:00", tz, &tp));
656   ExpectTime(tp, tz, 2013, 6, 28, 8, 9, 0, -7 * 60 * 60, true, "PDT");
657 
658   // ":60.5" -> ":00.0"
659   EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:60.5-08:00", tz, &tp));
660   ExpectTime(tp, tz, 2013, 6, 28, 8, 9, 0, -7 * 60 * 60, true, "PDT");
661 
662   // ":61" -> error
663   EXPECT_FALSE(parse(RFC3339_full, "2013-06-28T07:08:61-08:00", tz, &tp));
664 }
665 
TEST(Parse,ErrorCases)666 TEST(Parse, ErrorCases) {
667   const time_zone tz = utc_time_zone();
668   auto tp = system_clock::from_time_t(0);
669 
670   // Illegal trailing data.
671   EXPECT_FALSE(parse("%S", "123", tz, &tp));
672 
673   // Can't parse an illegal format specifier.
674   EXPECT_FALSE(parse("%Q", "x", tz, &tp));
675 
676   // Fails because of trailing, unparsed data "blah".
677   EXPECT_FALSE(parse("%m-%d", "2-3 blah", tz, &tp));
678 
679   // Trailing whitespace is allowed.
680   EXPECT_TRUE(parse("%m-%d", "2-3  ", tz, &tp));
681   EXPECT_EQ(2, convert(tp, utc_time_zone()).month());
682   EXPECT_EQ(3, convert(tp, utc_time_zone()).day());
683 
684   // Feb 31 requires normalization.
685   EXPECT_FALSE(parse("%m-%d", "2-31", tz, &tp));
686 
687   // Check that we cannot have spaces in UTC offsets.
688   EXPECT_TRUE(parse("%z", "-0203", tz, &tp));
689   EXPECT_FALSE(parse("%z", "- 2 3", tz, &tp));
690   EXPECT_TRUE(parse("%Ez", "-02:03", tz, &tp));
691   EXPECT_FALSE(parse("%Ez", "- 2: 3", tz, &tp));
692 
693   // Check that we reject other malformed UTC offsets.
694   EXPECT_FALSE(parse("%Ez", "+-08:00", tz, &tp));
695   EXPECT_FALSE(parse("%Ez", "-+08:00", tz, &tp));
696 
697   // Check that we do not accept "-0" in fields that allow zero.
698   EXPECT_FALSE(parse("%Y", "-0", tz, &tp));
699   EXPECT_FALSE(parse("%E4Y", "-0", tz, &tp));
700   EXPECT_FALSE(parse("%H", "-0", tz, &tp));
701   EXPECT_FALSE(parse("%M", "-0", tz, &tp));
702   EXPECT_FALSE(parse("%S", "-0", tz, &tp));
703   EXPECT_FALSE(parse("%z", "+-000", tz, &tp));
704   EXPECT_FALSE(parse("%Ez", "+-0:00", tz, &tp));
705   EXPECT_FALSE(parse("%z", "-00-0", tz, &tp));
706   EXPECT_FALSE(parse("%Ez", "-00:-0", tz, &tp));
707 }
708 
TEST(Parse,PosixConversions)709 TEST(Parse, PosixConversions) {
710   time_zone tz = utc_time_zone();
711   auto tp = system_clock::from_time_t(0);
712   const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
713 
714   tp = reset;
715   EXPECT_TRUE(parse("%d", "15", tz, &tp));
716   EXPECT_EQ(15, convert(tp, tz).day());
717 
718   // %e is an extension, but is supported internally.
719   tp = reset;
720   EXPECT_TRUE(parse("%e", "15", tz, &tp));
721   EXPECT_EQ(15, convert(tp, tz).day());  // Equivalent to %d
722 
723   tp = reset;
724   EXPECT_TRUE(parse("%H", "17", tz, &tp));
725   EXPECT_EQ(17, convert(tp, tz).hour());
726 
727   tp = reset;
728   EXPECT_TRUE(parse("%I", "5", tz, &tp));
729   EXPECT_EQ(5, convert(tp, tz).hour());
730 
731   // %j is parsed but ignored.
732   EXPECT_TRUE(parse("%j", "32", tz, &tp));
733 
734   tp = reset;
735   EXPECT_TRUE(parse("%m", "11", tz, &tp));
736   EXPECT_EQ(11, convert(tp, tz).month());
737 
738   tp = reset;
739   EXPECT_TRUE(parse("%M", "33", tz, &tp));
740   EXPECT_EQ(33, convert(tp, tz).minute());
741 
742   tp = reset;
743   EXPECT_TRUE(parse("%S", "55", tz, &tp));
744   EXPECT_EQ(55, convert(tp, tz).second());
745 
746   // %U is parsed but ignored.
747   EXPECT_TRUE(parse("%U", "15", tz, &tp));
748 
749   // %w is parsed but ignored.
750   EXPECT_TRUE(parse("%w", "2", tz, &tp));
751 
752   // %W is parsed but ignored.
753   EXPECT_TRUE(parse("%W", "22", tz, &tp));
754 
755   tp = reset;
756   EXPECT_TRUE(parse("%y", "04", tz, &tp));
757   EXPECT_EQ(2004, convert(tp, tz).year());
758 
759   tp = reset;
760   EXPECT_TRUE(parse("%Y", "2004", tz, &tp));
761   EXPECT_EQ(2004, convert(tp, tz).year());
762 
763   EXPECT_TRUE(parse("%%", "%", tz, &tp));
764 
765 #if defined(__linux__)
766   // SU/C99/TZ extensions
767 
768   // Because we handle each (non-internal) specifier in a separate call
769   // to strptime(), there is no way to group %C and %y together.  So we
770   // just skip the %C/%y case.
771 #if 0
772   tp = reset;
773   EXPECT_TRUE(parse("%C %y", "20 04", tz, &tp));
774   EXPECT_EQ(2004, convert(tp, tz).year());
775 #endif
776 
777   tp = reset;
778   EXPECT_TRUE(parse("%D", "02/03/04", tz, &tp));
779   EXPECT_EQ(2, convert(tp, tz).month());
780   EXPECT_EQ(3, convert(tp, tz).day());
781   EXPECT_EQ(2004, convert(tp, tz).year());
782 
783   EXPECT_TRUE(parse("%n", "\n", tz, &tp));
784 
785   tp = reset;
786   EXPECT_TRUE(parse("%R", "03:44", tz, &tp));
787   EXPECT_EQ(3, convert(tp, tz).hour());
788   EXPECT_EQ(44, convert(tp, tz).minute());
789 
790   EXPECT_TRUE(parse("%t", "\t\v\f\n\r ", tz, &tp));
791 
792   tp = reset;
793   EXPECT_TRUE(parse("%T", "03:44:55", tz, &tp));
794   EXPECT_EQ(3, convert(tp, tz).hour());
795   EXPECT_EQ(44, convert(tp, tz).minute());
796   EXPECT_EQ(55, convert(tp, tz).second());
797 
798   tp = reset;
799   EXPECT_TRUE(parse("%s", "1234567890", tz, &tp));
800   EXPECT_EQ(system_clock::from_time_t(1234567890), tp);
801 
802   // %s conversion, like %z/%Ez, pays no heed to the optional zone.
803   time_zone lax;
804   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &lax));
805   tp = reset;
806   EXPECT_TRUE(parse("%s", "1234567890", lax, &tp));
807   EXPECT_EQ(system_clock::from_time_t(1234567890), tp);
808 
809   // This is most important when the time has the same YMDhms
810   // breakdown in the zone as some other time.  For example, ...
811   //  1414917000 in US/Pacific -> Sun Nov 2 01:30:00 2014 (PDT)
812   //  1414920600 in US/Pacific -> Sun Nov 2 01:30:00 2014 (PST)
813   tp = reset;
814   EXPECT_TRUE(parse("%s", "1414917000", lax, &tp));
815   EXPECT_EQ(system_clock::from_time_t(1414917000), tp);
816   tp = reset;
817   EXPECT_TRUE(parse("%s", "1414920600", lax, &tp));
818   EXPECT_EQ(system_clock::from_time_t(1414920600), tp);
819 #endif
820 }
821 
TEST(Parse,LocaleSpecific)822 TEST(Parse, LocaleSpecific) {
823   time_zone tz = utc_time_zone();
824   auto tp = system_clock::from_time_t(0);
825   const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
826 
827   // %a is parsed but ignored.
828   EXPECT_TRUE(parse("%a", "Mon", tz, &tp));
829 
830   // %A is parsed but ignored.
831   EXPECT_TRUE(parse("%A", "Monday", tz, &tp));
832 
833   tp = reset;
834   EXPECT_TRUE(parse("%b", "Feb", tz, &tp));
835   EXPECT_EQ(2, convert(tp, tz).month());
836 
837   tp = reset;
838   EXPECT_TRUE(parse("%B", "February", tz, &tp));
839   EXPECT_EQ(2, convert(tp, tz).month());
840 
841   // %p is parsed but ignored if it's alone.  But it's used with %I.
842   EXPECT_TRUE(parse("%p", "AM", tz, &tp));
843   tp = reset;
844   EXPECT_TRUE(parse("%I %p", "5 PM", tz, &tp));
845   EXPECT_EQ(17, convert(tp, tz).hour());
846 
847   tp = reset;
848   EXPECT_TRUE(parse("%x", "02/03/04", tz, &tp));
849   if (convert(tp, tz).month() == 2) {
850     EXPECT_EQ(3, convert(tp, tz).day());
851   } else {
852     EXPECT_EQ(2, convert(tp, tz).day());
853     EXPECT_EQ(3, convert(tp, tz).month());
854   }
855   EXPECT_EQ(2004, convert(tp, tz).year());
856 
857   tp = reset;
858   EXPECT_TRUE(parse("%X", "15:44:55", tz, &tp));
859   EXPECT_EQ(15, convert(tp, tz).hour());
860   EXPECT_EQ(44, convert(tp, tz).minute());
861   EXPECT_EQ(55, convert(tp, tz).second());
862 
863 #if defined(__linux__)
864   // SU/C99/TZ extensions
865 
866   tp = reset;
867   EXPECT_TRUE(parse("%h", "Feb", tz, &tp));
868   EXPECT_EQ(2, convert(tp, tz).month());  // Equivalent to %b
869 
870   tp = reset;
871   EXPECT_TRUE(parse("%l %p", "5 PM", tz, &tp));
872   EXPECT_EQ(17, convert(tp, tz).hour());
873 
874   tp = reset;
875   EXPECT_TRUE(parse("%r", "03:44:55 PM", tz, &tp));
876   EXPECT_EQ(15, convert(tp, tz).hour());
877   EXPECT_EQ(44, convert(tp, tz).minute());
878   EXPECT_EQ(55, convert(tp, tz).second());
879 
880   tp = reset;
881   EXPECT_TRUE(parse("%Ec", "Tue Nov 19 05:06:07 2013", tz, &tp));
882   EXPECT_EQ(convert(civil_second(2013, 11, 19, 5, 6, 7), tz), tp);
883 
884   // Modified conversion specifiers %E_
885 
886   tp = reset;
887   EXPECT_TRUE(parse("%Ex", "02/03/04", tz, &tp));
888   EXPECT_EQ(2, convert(tp, tz).month());
889   EXPECT_EQ(3, convert(tp, tz).day());
890   EXPECT_EQ(2004, convert(tp, tz).year());
891 
892   tp = reset;
893   EXPECT_TRUE(parse("%EX", "15:44:55", tz, &tp));
894   EXPECT_EQ(15, convert(tp, tz).hour());
895   EXPECT_EQ(44, convert(tp, tz).minute());
896   EXPECT_EQ(55, convert(tp, tz).second());
897 
898   // %Ey, the year offset from %EC, doesn't really make sense alone as there
899   // is no way to represent it in tm_year (%EC is not simply the century).
900   // Yet, because we handle each (non-internal) specifier in a separate call
901   // to strptime(), there is no way to group %EC and %Ey either.  So we just
902   // skip the %EC and %Ey cases.
903 
904   tp = reset;
905   EXPECT_TRUE(parse("%EY", "2004", tz, &tp));
906   EXPECT_EQ(2004, convert(tp, tz).year());
907 
908   // Modified conversion specifiers %O_
909 
910   tp = reset;
911   EXPECT_TRUE(parse("%Od", "15", tz, &tp));
912   EXPECT_EQ(15, convert(tp, tz).day());
913 
914   tp = reset;
915   EXPECT_TRUE(parse("%Oe", "15", tz, &tp));
916   EXPECT_EQ(15, convert(tp, tz).day());  // Equivalent to %d
917 
918   tp = reset;
919   EXPECT_TRUE(parse("%OH", "17", tz, &tp));
920   EXPECT_EQ(17, convert(tp, tz).hour());
921 
922   tp = reset;
923   EXPECT_TRUE(parse("%OI", "5", tz, &tp));
924   EXPECT_EQ(5, convert(tp, tz).hour());
925 
926   tp = reset;
927   EXPECT_TRUE(parse("%Om", "11", tz, &tp));
928   EXPECT_EQ(11, convert(tp, tz).month());
929 
930   tp = reset;
931   EXPECT_TRUE(parse("%OM", "33", tz, &tp));
932   EXPECT_EQ(33, convert(tp, tz).minute());
933 
934   tp = reset;
935   EXPECT_TRUE(parse("%OS", "55", tz, &tp));
936   EXPECT_EQ(55, convert(tp, tz).second());
937 
938   // %OU is parsed but ignored.
939   EXPECT_TRUE(parse("%OU", "15", tz, &tp));
940 
941   // %Ow is parsed but ignored.
942   EXPECT_TRUE(parse("%Ow", "2", tz, &tp));
943 
944   // %OW is parsed but ignored.
945   EXPECT_TRUE(parse("%OW", "22", tz, &tp));
946 
947   tp = reset;
948   EXPECT_TRUE(parse("%Oy", "04", tz, &tp));
949   EXPECT_EQ(2004, convert(tp, tz).year());
950 #endif
951 }
952 
TEST(Parse,ExtendedSeconds)953 TEST(Parse, ExtendedSeconds) {
954   const time_zone tz = utc_time_zone();
955   const time_point<nanoseconds> unix_epoch = system_clock::from_time_t(0);
956 
957   // All %E<prec>S cases are treated the same as %E*S on input.
958   auto precisions = {"*", "0", "1",  "2",  "3",  "4",  "5",  "6", "7",
959                      "8", "9", "10", "11", "12", "13", "14", "15"};
960   for (const std::string& prec : precisions) {
961     const std::string fmt = "%E" + prec + "S";
962     SCOPED_TRACE(fmt);
963     time_point<nanoseconds> tp = unix_epoch;
964     EXPECT_TRUE(parse(fmt, "5", tz, &tp));
965     EXPECT_EQ(unix_epoch + seconds(5), tp);
966     tp = unix_epoch;
967     EXPECT_TRUE(parse(fmt, "05", tz, &tp));
968     EXPECT_EQ(unix_epoch + seconds(5), tp);
969     tp = unix_epoch;
970     EXPECT_TRUE(parse(fmt, "05.0", tz, &tp));
971     EXPECT_EQ(unix_epoch + seconds(5), tp);
972     tp = unix_epoch;
973     EXPECT_TRUE(parse(fmt, "05.00", tz, &tp));
974     EXPECT_EQ(unix_epoch + seconds(5), tp);
975     tp = unix_epoch;
976     EXPECT_TRUE(parse(fmt, "05.6", tz, &tp));
977     EXPECT_EQ(unix_epoch + seconds(5) + milliseconds(600), tp);
978     tp = unix_epoch;
979     EXPECT_TRUE(parse(fmt, "05.60", tz, &tp));
980     EXPECT_EQ(unix_epoch + seconds(5) + milliseconds(600), tp);
981     tp = unix_epoch;
982     EXPECT_TRUE(parse(fmt, "05.600", tz, &tp));
983     EXPECT_EQ(unix_epoch + seconds(5) + milliseconds(600), tp);
984     tp = unix_epoch;
985     EXPECT_TRUE(parse(fmt, "05.67", tz, &tp));
986     EXPECT_EQ(unix_epoch + seconds(5) + milliseconds(670), tp);
987     tp = unix_epoch;
988     EXPECT_TRUE(parse(fmt, "05.670", tz, &tp));
989     EXPECT_EQ(unix_epoch + seconds(5) + milliseconds(670), tp);
990     tp = unix_epoch;
991     EXPECT_TRUE(parse(fmt, "05.678", tz, &tp));
992     EXPECT_EQ(unix_epoch + seconds(5) + milliseconds(678), tp);
993   }
994 
995   // Here is a "%E*S" case we got wrong for a while.  The fractional
996   // part of the first instant is less than 2^31 and was correctly
997   // parsed, while the second (and any subsecond field >=2^31) failed.
998   time_point<nanoseconds> tp = unix_epoch;
999   EXPECT_TRUE(parse("%E*S", "0.2147483647", tz, &tp));
1000   EXPECT_EQ(unix_epoch + nanoseconds(214748364), tp);
1001   tp = unix_epoch;
1002   EXPECT_TRUE(parse("%E*S", "0.2147483648", tz, &tp));
1003   EXPECT_EQ(unix_epoch + nanoseconds(214748364), tp);
1004 
1005   // We should also be able to specify long strings of digits far
1006   // beyond the current resolution and have them convert the same way.
1007   tp = unix_epoch;
1008   EXPECT_TRUE(parse(
1009       "%E*S", "0.214748364801234567890123456789012345678901234567890123456789",
1010       tz, &tp));
1011   EXPECT_EQ(unix_epoch + nanoseconds(214748364), tp);
1012 }
1013 
TEST(Parse,ExtendedSecondsScan)1014 TEST(Parse, ExtendedSecondsScan) {
1015   const time_zone tz = utc_time_zone();
1016   time_point<nanoseconds> tp;
1017   for (int ms = 0; ms < 1000; ms += 111) {
1018     for (int us = 0; us < 1000; us += 27) {
1019       const int micros = ms * 1000 + us;
1020       for (int ns = 0; ns < 1000; ns += 9) {
1021         const auto expected =
1022             system_clock::from_time_t(0) + nanoseconds(micros * 1000 + ns);
1023         std::ostringstream oss;
1024         oss << "0." << std::setfill('0') << std::setw(3);
1025         oss << ms << std::setw(3) << us << std::setw(3) << ns;
1026         const std::string input = oss.str();
1027         EXPECT_TRUE(parse("%E*S", input, tz, &tp));
1028         EXPECT_EQ(expected, tp) << input;
1029       }
1030     }
1031   }
1032 }
1033 
TEST(Parse,ExtendedSubeconds)1034 TEST(Parse, ExtendedSubeconds) {
1035   const time_zone tz = utc_time_zone();
1036   const time_point<nanoseconds> unix_epoch = system_clock::from_time_t(0);
1037 
1038   // All %E<prec>f cases are treated the same as %E*f on input.
1039   auto precisions = {"*", "0", "1",  "2",  "3",  "4",  "5",  "6", "7",
1040                      "8", "9", "10", "11", "12", "13", "14", "15"};
1041   for (const std::string& prec : precisions) {
1042     const std::string fmt = "%E" + prec + "f";
1043     SCOPED_TRACE(fmt);
1044     time_point<nanoseconds> tp = unix_epoch - seconds(1);
1045     EXPECT_TRUE(parse(fmt, "", tz, &tp));
1046     EXPECT_EQ(unix_epoch, tp);
1047     tp = unix_epoch;
1048     EXPECT_TRUE(parse(fmt, "6", tz, &tp));
1049     EXPECT_EQ(unix_epoch + milliseconds(600), tp);
1050     tp = unix_epoch;
1051     EXPECT_TRUE(parse(fmt, "60", tz, &tp));
1052     EXPECT_EQ(unix_epoch + milliseconds(600), tp);
1053     tp = unix_epoch;
1054     EXPECT_TRUE(parse(fmt, "600", tz, &tp));
1055     EXPECT_EQ(unix_epoch + milliseconds(600), tp);
1056     tp = unix_epoch;
1057     EXPECT_TRUE(parse(fmt, "67", tz, &tp));
1058     EXPECT_EQ(unix_epoch + milliseconds(670), tp);
1059     tp = unix_epoch;
1060     EXPECT_TRUE(parse(fmt, "670", tz, &tp));
1061     EXPECT_EQ(unix_epoch + milliseconds(670), tp);
1062     tp = unix_epoch;
1063     EXPECT_TRUE(parse(fmt, "678", tz, &tp));
1064     EXPECT_EQ(unix_epoch + milliseconds(678), tp);
1065     tp = unix_epoch;
1066     EXPECT_TRUE(parse(fmt, "6789", tz, &tp));
1067     EXPECT_EQ(unix_epoch + milliseconds(678) + microseconds(900), tp);
1068   }
1069 
1070   // Here is a "%E*f" case we got wrong for a while.  The fractional
1071   // part of the first instant is less than 2^31 and was correctly
1072   // parsed, while the second (and any subsecond field >=2^31) failed.
1073   time_point<nanoseconds> tp = unix_epoch;
1074   EXPECT_TRUE(parse("%E*f", "2147483647", tz, &tp));
1075   EXPECT_EQ(unix_epoch + nanoseconds(214748364), tp);
1076   tp = unix_epoch;
1077   EXPECT_TRUE(parse("%E*f", "2147483648", tz, &tp));
1078   EXPECT_EQ(unix_epoch + nanoseconds(214748364), tp);
1079 
1080   // We should also be able to specify long strings of digits far
1081   // beyond the current resolution and have them convert the same way.
1082   tp = unix_epoch;
1083   EXPECT_TRUE(parse(
1084       "%E*f", "214748364801234567890123456789012345678901234567890123456789",
1085       tz, &tp));
1086   EXPECT_EQ(unix_epoch + nanoseconds(214748364), tp);
1087 }
1088 
TEST(Parse,ExtendedSubecondsScan)1089 TEST(Parse, ExtendedSubecondsScan) {
1090   time_point<nanoseconds> tp;
1091   const time_zone tz = utc_time_zone();
1092   for (int ms = 0; ms < 1000; ms += 111) {
1093     for (int us = 0; us < 1000; us += 27) {
1094       const int micros = ms * 1000 + us;
1095       for (int ns = 0; ns < 1000; ns += 9) {
1096         std::ostringstream oss;
1097         oss << std::setfill('0') << std::setw(3) << ms;
1098         oss << std::setw(3) << us << std::setw(3) << ns;
1099         const std::string nanos = oss.str();
1100         const auto expected =
1101             system_clock::from_time_t(0) + nanoseconds(micros * 1000 + ns);
1102         for (int ps = 0; ps < 1000; ps += 250) {
1103           std::ostringstream oss;
1104           oss << std::setfill('0') << std::setw(3) << ps;
1105           const std::string input = nanos + oss.str() + "999";
1106           EXPECT_TRUE(parse("%E*f", input, tz, &tp));
1107           EXPECT_EQ(expected + nanoseconds(ps) / 1000, tp) << input;
1108         }
1109       }
1110     }
1111   }
1112 }
1113 
TEST(Parse,ExtendedOffset)1114 TEST(Parse, ExtendedOffset) {
1115   const time_zone utc = utc_time_zone();
1116   time_point<sys_seconds> tp;
1117 
1118   // %z against +-HHMM.
1119   EXPECT_TRUE(parse("%z", "+0000", utc, &tp));
1120   EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
1121   EXPECT_TRUE(parse("%z", "-1234", utc, &tp));
1122   EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
1123   EXPECT_TRUE(parse("%z", "+1234", utc, &tp));
1124   EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
1125   EXPECT_FALSE(parse("%z", "-123", utc, &tp));
1126 
1127   // %z against +-HH.
1128   EXPECT_TRUE(parse("%z", "+00", utc, &tp));
1129   EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
1130   EXPECT_TRUE(parse("%z", "-12", utc, &tp));
1131   EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
1132   EXPECT_TRUE(parse("%z", "+12", utc, &tp));
1133   EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
1134   EXPECT_FALSE(parse("%z", "-1", utc, &tp));
1135 
1136   // %Ez against +-HH:MM.
1137   EXPECT_TRUE(parse("%Ez", "+00:00", utc, &tp));
1138   EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
1139   EXPECT_TRUE(parse("%Ez", "-12:34", utc, &tp));
1140   EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
1141   EXPECT_TRUE(parse("%Ez", "+12:34", utc, &tp));
1142   EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
1143   EXPECT_FALSE(parse("%Ez", "-12:3", utc, &tp));
1144 
1145   // %Ez against +-HHMM.
1146   EXPECT_TRUE(parse("%Ez", "+0000", utc, &tp));
1147   EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
1148   EXPECT_TRUE(parse("%Ez", "-1234", utc, &tp));
1149   EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
1150   EXPECT_TRUE(parse("%Ez", "+1234", utc, &tp));
1151   EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
1152   EXPECT_FALSE(parse("%Ez", "-123", utc, &tp));
1153 
1154   // %Ez against +-HH.
1155   EXPECT_TRUE(parse("%Ez", "+00", utc, &tp));
1156   EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
1157   EXPECT_TRUE(parse("%Ez", "-12", utc, &tp));
1158   EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
1159   EXPECT_TRUE(parse("%Ez", "+12", utc, &tp));
1160   EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
1161   EXPECT_FALSE(parse("%Ez", "-1", utc, &tp));
1162 }
1163 
TEST(Parse,ExtendedYears)1164 TEST(Parse, ExtendedYears) {
1165   const time_zone utc = utc_time_zone();
1166   const char e4y_fmt[] = "%E4Y%m%d";  // no separators
1167   time_point<sys_seconds> tp;
1168 
1169   // %E4Y consumes exactly four chars, including any sign.
1170   EXPECT_TRUE(parse(e4y_fmt, "-9991127", utc, &tp));
1171   EXPECT_EQ(convert(civil_second(-999, 11, 27, 0, 0, 0), utc), tp);
1172   EXPECT_TRUE(parse(e4y_fmt, "-0991127", utc, &tp));
1173   EXPECT_EQ(convert(civil_second(-99, 11, 27, 0, 0, 0), utc), tp);
1174   EXPECT_TRUE(parse(e4y_fmt, "-0091127", utc, &tp));
1175   EXPECT_EQ(convert(civil_second(-9, 11, 27, 0, 0, 0), utc), tp);
1176   EXPECT_TRUE(parse(e4y_fmt, "-0011127", utc, &tp));
1177   EXPECT_EQ(convert(civil_second(-1, 11, 27, 0, 0, 0), utc), tp);
1178   EXPECT_TRUE(parse(e4y_fmt, "00001127", utc, &tp));
1179   EXPECT_EQ(convert(civil_second(0, 11, 27, 0, 0, 0), utc), tp);
1180   EXPECT_TRUE(parse(e4y_fmt, "00011127", utc, &tp));
1181   EXPECT_EQ(convert(civil_second(1, 11, 27, 0, 0, 0), utc), tp);
1182   EXPECT_TRUE(parse(e4y_fmt, "00091127", utc, &tp));
1183   EXPECT_EQ(convert(civil_second(9, 11, 27, 0, 0, 0), utc), tp);
1184   EXPECT_TRUE(parse(e4y_fmt, "00991127", utc, &tp));
1185   EXPECT_EQ(convert(civil_second(99, 11, 27, 0, 0, 0), utc), tp);
1186   EXPECT_TRUE(parse(e4y_fmt, "09991127", utc, &tp));
1187   EXPECT_EQ(convert(civil_second(999, 11, 27, 0, 0, 0), utc), tp);
1188   EXPECT_TRUE(parse(e4y_fmt, "99991127", utc, &tp));
1189   EXPECT_EQ(convert(civil_second(9999, 11, 27, 0, 0, 0), utc), tp);
1190 
1191   // When the year is outside [-999:9999], the parse fails.
1192   EXPECT_FALSE(parse(e4y_fmt, "-10001127", utc, &tp));
1193   EXPECT_FALSE(parse(e4y_fmt, "100001127", utc, &tp));
1194 }
1195 
TEST(Parse,RFC3339Format)1196 TEST(Parse, RFC3339Format) {
1197   const time_zone tz = utc_time_zone();
1198   time_point<nanoseconds> tp;
1199   EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00+00:00", tz, &tp));
1200   ExpectTime(tp, tz, 2014, 2, 12, 20, 21, 0, 0, false, "UTC");
1201 
1202   // Check that %Ez also accepts "Z" as a synonym for "+00:00".
1203   time_point<nanoseconds> tp2;
1204   EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00Z", tz, &tp2));
1205   EXPECT_EQ(tp, tp2);
1206 }
1207 
TEST(Parse,MaxRange)1208 TEST(Parse, MaxRange) {
1209   const time_zone utc = utc_time_zone();
1210   time_point<sys_seconds> tp;
1211 
1212   // tests the upper limit using +00:00 offset
1213   EXPECT_TRUE(
1214       parse(RFC3339_sec, "292277026596-12-04T15:30:07+00:00", utc, &tp));
1215   EXPECT_EQ(tp, time_point<sys_seconds>::max());
1216   EXPECT_FALSE(
1217       parse(RFC3339_sec, "292277026596-12-04T15:30:08+00:00", utc, &tp));
1218 
1219   // tests the upper limit using -01:00 offset
1220   EXPECT_TRUE(
1221       parse(RFC3339_sec, "292277026596-12-04T14:30:07-01:00", utc, &tp));
1222   EXPECT_EQ(tp, time_point<sys_seconds>::max());
1223   EXPECT_FALSE(
1224       parse(RFC3339_sec, "292277026596-12-04T15:30:07-01:00", utc, &tp));
1225 
1226   // tests the lower limit using +00:00 offset
1227   EXPECT_TRUE(
1228       parse(RFC3339_sec, "-292277022657-01-27T08:29:52+00:00", utc, &tp));
1229   EXPECT_EQ(tp, time_point<sys_seconds>::min());
1230   EXPECT_FALSE(
1231       parse(RFC3339_sec, "-292277022657-01-27T08:29:51+00:00", utc, &tp));
1232 
1233   // tests the lower limit using +01:00 offset
1234   EXPECT_TRUE(
1235       parse(RFC3339_sec, "-292277022657-01-27T09:29:52+01:00", utc, &tp));
1236   EXPECT_EQ(tp, time_point<sys_seconds>::min());
1237   EXPECT_FALSE(
1238       parse(RFC3339_sec, "-292277022657-01-27T08:29:51+01:00", utc, &tp));
1239 
1240   // tests max/min civil-second overflow
1241   EXPECT_FALSE(parse(RFC3339_sec, "9223372036854775807-12-31T23:59:59-00:01",
1242                      utc, &tp));
1243   EXPECT_FALSE(parse(RFC3339_sec, "-9223372036854775808-01-01T00:00:00+00:01",
1244                      utc, &tp));
1245 
1246   // TODO: Add tests that parsing times with fractional seconds overflow
1247   // appropriately. This can't be done until cctz::parse() properly detects
1248   // overflow when combining the chrono seconds and femto.
1249 }
1250 
1251 //
1252 // Roundtrip test for format()/parse().
1253 //
1254 
TEST(FormatParse,RoundTrip)1255 TEST(FormatParse, RoundTrip) {
1256   time_zone lax;
1257   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &lax));
1258   const auto in = convert(civil_second(1977, 6, 28, 9, 8, 7), lax);
1259   const auto subseconds = nanoseconds(654321);
1260 
1261   // RFC3339, which renders subseconds.
1262   {
1263     time_point<nanoseconds> out;
1264     const std::string s = format(RFC3339_full, in + subseconds, lax);
1265     EXPECT_TRUE(parse(RFC3339_full, s, lax, &out)) << s;
1266     EXPECT_EQ(in + subseconds, out);  // RFC3339_full includes %Ez
1267   }
1268 
1269   // RFC1123, which only does whole seconds.
1270   {
1271     time_point<nanoseconds> out;
1272     const std::string s = format(RFC1123_full, in, lax);
1273     EXPECT_TRUE(parse(RFC1123_full, s, lax, &out)) << s;
1274     EXPECT_EQ(in, out);  // RFC1123_full includes %z
1275   }
1276 
1277 #if defined(_WIN32) || defined(_WIN64)
1278   // Initial investigations indicate the %c does not roundtrip on Windows.
1279   // TODO: Figure out what is going on here (perhaps a locale problem).
1280 #else
1281   // Even though we don't know what %c will produce, it should roundtrip,
1282   // but only in the 0-offset timezone.
1283   {
1284     time_point<nanoseconds> out;
1285     time_zone utc = utc_time_zone();
1286     const std::string s = format("%c", in, utc);
1287     EXPECT_TRUE(parse("%c", s, utc, &out)) << s;
1288     EXPECT_EQ(in, out);
1289   }
1290 #endif
1291 }
1292 
TEST(FormatParse,RoundTripDistantFuture)1293 TEST(FormatParse, RoundTripDistantFuture) {
1294   const time_zone utc = utc_time_zone();
1295   const time_point<sys_seconds> in = time_point<sys_seconds>::max();
1296   const std::string s = format(RFC3339_full, in, utc);
1297   time_point<sys_seconds> out;
1298   EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;
1299   EXPECT_EQ(in, out);
1300 }
1301 
TEST(FormatParse,RoundTripDistantPast)1302 TEST(FormatParse, RoundTripDistantPast) {
1303   const time_zone utc = utc_time_zone();
1304   const time_point<sys_seconds> in = time_point<sys_seconds>::min();
1305   const std::string s = format(RFC3339_full, in, utc);
1306   time_point<sys_seconds> out;
1307   EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;
1308   EXPECT_EQ(in, out);
1309 }
1310 
1311 }  // namespace cctz
1312