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 //   https://www.apache.org/licenses/LICENSE-2.0
8 //
9 //   Unless required by applicable law or agreed to in writing, software
10 //   distributed under the License is distributed on an "AS IS" BASIS,
11 //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 //   See the License for the specific language governing permissions and
13 //   limitations under the License.
14 
15 #include <chrono>
16 #include <cstdint>
17 #include <iomanip>
18 #include <sstream>
19 #include <string>
20 
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 #include "absl/base/config.h"
24 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
25 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
26 
27 namespace chrono = std::chrono;
28 
29 namespace absl {
30 ABSL_NAMESPACE_BEGIN
31 namespace time_internal {
32 namespace cctz {
33 
34 namespace {
35 
36 // This helper is a macro so that failed expectations show up with the
37 // correct line numbers.
38 #define ExpectTime(tp, tz, y, m, d, hh, mm, ss, off, isdst, zone) \
39   do {                                                            \
40     time_zone::absolute_lookup al = tz.lookup(tp);                \
41     EXPECT_EQ(y, al.cs.year());                                   \
42     EXPECT_EQ(m, al.cs.month());                                  \
43     EXPECT_EQ(d, al.cs.day());                                    \
44     EXPECT_EQ(hh, al.cs.hour());                                  \
45     EXPECT_EQ(mm, al.cs.minute());                                \
46     EXPECT_EQ(ss, al.cs.second());                                \
47     EXPECT_EQ(off, al.offset);                                    \
48     EXPECT_TRUE(isdst == al.is_dst);                              \
49     EXPECT_STREQ(zone, al.abbr);                                  \
50   } while (0)
51 
52 const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez";
53 const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez";
54 
55 const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z";
56 const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z";
57 
58 // A helper that tests the given format specifier by itself, and with leading
59 // and trailing characters.  For example: TestFormatSpecifier(tp, "%a", "Thu").
60 template <typename D>
TestFormatSpecifier(time_point<D> tp,time_zone tz,const std::string & fmt,const std::string & ans)61 void TestFormatSpecifier(time_point<D> tp, time_zone tz, const std::string& fmt,
62                          const std::string& ans) {
63   EXPECT_EQ(ans, format(fmt, tp, tz)) << fmt;
64   EXPECT_EQ("xxx " + ans, format("xxx " + fmt, tp, tz));
65   EXPECT_EQ(ans + " yyy", format(fmt + " yyy", tp, tz));
66   EXPECT_EQ("xxx " + ans + " yyy", format("xxx " + fmt + " yyy", tp, tz));
67 }
68 
69 }  // namespace
70 
71 //
72 // Testing format()
73 //
74 
TEST(Format,TimePointResolution)75 TEST(Format, TimePointResolution) {
76   const char kFmt[] = "%H:%M:%E*S";
77   const time_zone utc = utc_time_zone();
78   const time_point<chrono::nanoseconds> t0 =
79       chrono::system_clock::from_time_t(1420167845) +
80       chrono::milliseconds(123) + chrono::microseconds(456) +
81       chrono::nanoseconds(789);
82   EXPECT_EQ(
83       "03:04:05.123456789",
84       format(kFmt, chrono::time_point_cast<chrono::nanoseconds>(t0), utc));
85   EXPECT_EQ(
86       "03:04:05.123456",
87       format(kFmt, chrono::time_point_cast<chrono::microseconds>(t0), utc));
88   EXPECT_EQ(
89       "03:04:05.123",
90       format(kFmt, chrono::time_point_cast<chrono::milliseconds>(t0), utc));
91   EXPECT_EQ("03:04:05",
92             format(kFmt, chrono::time_point_cast<chrono::seconds>(t0), utc));
93   EXPECT_EQ(
94       "03:04:05",
95       format(kFmt,
96              chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0),
97              utc));
98   EXPECT_EQ("03:04:00",
99             format(kFmt, chrono::time_point_cast<chrono::minutes>(t0), utc));
100   EXPECT_EQ("03:00:00",
101             format(kFmt, chrono::time_point_cast<chrono::hours>(t0), utc));
102 }
103 
TEST(Format,TimePointExtendedResolution)104 TEST(Format, TimePointExtendedResolution) {
105   const char kFmt[] = "%H:%M:%E*S";
106   const time_zone utc = utc_time_zone();
107   const time_point<absl::time_internal::cctz::seconds> tp =
108       chrono::time_point_cast<absl::time_internal::cctz::seconds>(
109           chrono::system_clock::from_time_t(0)) +
110       chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56);
111 
112   EXPECT_EQ(
113       "12:34:56.123456789012345",
114       detail::format(kFmt, tp, detail::femtoseconds(123456789012345), utc));
115   EXPECT_EQ(
116       "12:34:56.012345678901234",
117       detail::format(kFmt, tp, detail::femtoseconds(12345678901234), utc));
118   EXPECT_EQ("12:34:56.001234567890123",
119             detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc));
120   EXPECT_EQ("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<chrono::nanoseconds> tp = chrono::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 += chrono::hours(13) + chrono::minutes(4) + chrono::seconds(5);
147   tp += chrono::milliseconds(6) + chrono::microseconds(7) +
148         chrono::nanoseconds(8);
149   EXPECT_EQ("1970-01-01", format("%Y-%m-%d", tp, tz));
150   EXPECT_EQ("13:04:05", format("%H:%M:%S", tp, tz));
151   EXPECT_EQ("13:04:05.006", format("%H:%M:%E3S", tp, tz));
152   EXPECT_EQ("13:04:05.006007", format("%H:%M:%E6S", tp, tz));
153   EXPECT_EQ("13:04:05.006007008", format("%H:%M:%E9S", tp, tz));
154 }
155 
TEST(Format,PosixConversions)156 TEST(Format, PosixConversions) {
157   const time_zone tz = utc_time_zone();
158   auto tp = chrono::system_clock::from_time_t(0);
159 
160   TestFormatSpecifier(tp, tz, "%d", "01");
161   TestFormatSpecifier(tp, tz, "%e", " 1");  // extension but internal support
162   TestFormatSpecifier(tp, tz, "%H", "00");
163   TestFormatSpecifier(tp, tz, "%I", "12");
164   TestFormatSpecifier(tp, tz, "%j", "001");
165   TestFormatSpecifier(tp, tz, "%m", "01");
166   TestFormatSpecifier(tp, tz, "%M", "00");
167   TestFormatSpecifier(tp, tz, "%S", "00");
168   TestFormatSpecifier(tp, tz, "%U", "00");
169 #if !defined(__EMSCRIPTEN__)
170   TestFormatSpecifier(tp, tz, "%w", "4");  // 4=Thursday
171 #endif
172   TestFormatSpecifier(tp, tz, "%W", "00");
173   TestFormatSpecifier(tp, tz, "%y", "70");
174   TestFormatSpecifier(tp, tz, "%Y", "1970");
175   TestFormatSpecifier(tp, tz, "%z", "+0000");
176   TestFormatSpecifier(tp, tz, "%Z", "UTC");
177   TestFormatSpecifier(tp, tz, "%%", "%");
178 
179 #if defined(__linux__)
180   // SU/C99/TZ extensions
181   TestFormatSpecifier(tp, tz, "%C", "19");
182   TestFormatSpecifier(tp, tz, "%D", "01/01/70");
183   TestFormatSpecifier(tp, tz, "%F", "1970-01-01");
184   TestFormatSpecifier(tp, tz, "%g", "70");
185   TestFormatSpecifier(tp, tz, "%G", "1970");
186   TestFormatSpecifier(tp, tz, "%k", " 0");
187   TestFormatSpecifier(tp, tz, "%l", "12");
188   TestFormatSpecifier(tp, tz, "%n", "\n");
189   TestFormatSpecifier(tp, tz, "%R", "00:00");
190   TestFormatSpecifier(tp, tz, "%t", "\t");
191   TestFormatSpecifier(tp, tz, "%T", "00:00:00");
192   TestFormatSpecifier(tp, tz, "%u", "4");  // 4=Thursday
193   TestFormatSpecifier(tp, tz, "%V", "01");
194   TestFormatSpecifier(tp, tz, "%s", "0");
195 #endif
196 }
197 
TEST(Format,LocaleSpecific)198 TEST(Format, LocaleSpecific) {
199   const time_zone tz = utc_time_zone();
200   auto tp = chrono::system_clock::from_time_t(0);
201 
202   TestFormatSpecifier(tp, tz, "%a", "Thu");
203   TestFormatSpecifier(tp, tz, "%A", "Thursday");
204   TestFormatSpecifier(tp, tz, "%b", "Jan");
205   TestFormatSpecifier(tp, tz, "%B", "January");
206 
207   // %c should at least produce the numeric year and time-of-day.
208   const std::string s = format("%c", tp, utc_time_zone());
209   EXPECT_THAT(s, testing::HasSubstr("1970"));
210   EXPECT_THAT(s, testing::HasSubstr("00:00:00"));
211 
212   TestFormatSpecifier(tp, tz, "%p", "AM");
213   TestFormatSpecifier(tp, tz, "%x", "01/01/70");
214   TestFormatSpecifier(tp, tz, "%X", "00:00:00");
215 
216 #if defined(__linux__)
217   // SU/C99/TZ extensions
218   TestFormatSpecifier(tp, tz, "%h", "Jan");  // Same as %b
219   TestFormatSpecifier(tp, tz, "%P", "am");
220   TestFormatSpecifier(tp, tz, "%r", "12:00:00 AM");
221 
222   // Modified conversion specifiers %E_
223   TestFormatSpecifier(tp, tz, "%Ec", "Thu Jan  1 00:00:00 1970");
224   TestFormatSpecifier(tp, tz, "%EC", "19");
225   TestFormatSpecifier(tp, tz, "%Ex", "01/01/70");
226   TestFormatSpecifier(tp, tz, "%EX", "00:00:00");
227   TestFormatSpecifier(tp, tz, "%Ey", "70");
228   TestFormatSpecifier(tp, tz, "%EY", "1970");
229 
230   // Modified conversion specifiers %O_
231   TestFormatSpecifier(tp, tz, "%Od", "01");
232   TestFormatSpecifier(tp, tz, "%Oe", " 1");
233   TestFormatSpecifier(tp, tz, "%OH", "00");
234   TestFormatSpecifier(tp, tz, "%OI", "12");
235   TestFormatSpecifier(tp, tz, "%Om", "01");
236   TestFormatSpecifier(tp, tz, "%OM", "00");
237   TestFormatSpecifier(tp, tz, "%OS", "00");
238   TestFormatSpecifier(tp, tz, "%Ou", "4");  // 4=Thursday
239   TestFormatSpecifier(tp, tz, "%OU", "00");
240   TestFormatSpecifier(tp, tz, "%OV", "01");
241   TestFormatSpecifier(tp, tz, "%Ow", "4");  // 4=Thursday
242   TestFormatSpecifier(tp, tz, "%OW", "00");
243   TestFormatSpecifier(tp, tz, "%Oy", "70");
244 #endif
245 }
246 
TEST(Format,Escaping)247 TEST(Format, Escaping) {
248   const time_zone tz = utc_time_zone();
249   auto tp = chrono::system_clock::from_time_t(0);
250 
251   TestFormatSpecifier(tp, tz, "%%", "%");
252   TestFormatSpecifier(tp, tz, "%%a", "%a");
253   TestFormatSpecifier(tp, tz, "%%b", "%b");
254   TestFormatSpecifier(tp, tz, "%%Ea", "%Ea");
255   TestFormatSpecifier(tp, tz, "%%Es", "%Es");
256   TestFormatSpecifier(tp, tz, "%%E3S", "%E3S");
257   TestFormatSpecifier(tp, tz, "%%OS", "%OS");
258   TestFormatSpecifier(tp, tz, "%%O3S", "%O3S");
259 
260   // Multiple levels of escaping.
261   TestFormatSpecifier(tp, tz, "%%%Y", "%1970");
262   TestFormatSpecifier(tp, tz, "%%%E3S", "%00.000");
263   TestFormatSpecifier(tp, tz, "%%%%E3S", "%%E3S");
264 }
265 
TEST(Format,ExtendedSeconds)266 TEST(Format, ExtendedSeconds) {
267   const time_zone tz = utc_time_zone();
268 
269   // No subseconds.
270   time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);
271   tp += chrono::seconds(5);
272   EXPECT_EQ("05", format("%E*S", tp, tz));
273   EXPECT_EQ("05", format("%E0S", tp, tz));
274   EXPECT_EQ("05.0", format("%E1S", tp, tz));
275   EXPECT_EQ("05.00", format("%E2S", tp, tz));
276   EXPECT_EQ("05.000", format("%E3S", tp, tz));
277   EXPECT_EQ("05.0000", format("%E4S", tp, tz));
278   EXPECT_EQ("05.00000", format("%E5S", tp, tz));
279   EXPECT_EQ("05.000000", format("%E6S", tp, tz));
280   EXPECT_EQ("05.0000000", format("%E7S", tp, tz));
281   EXPECT_EQ("05.00000000", format("%E8S", tp, tz));
282   EXPECT_EQ("05.000000000", format("%E9S", tp, tz));
283   EXPECT_EQ("05.0000000000", format("%E10S", tp, tz));
284   EXPECT_EQ("05.00000000000", format("%E11S", tp, tz));
285   EXPECT_EQ("05.000000000000", format("%E12S", tp, tz));
286   EXPECT_EQ("05.0000000000000", format("%E13S", tp, tz));
287   EXPECT_EQ("05.00000000000000", format("%E14S", tp, tz));
288   EXPECT_EQ("05.000000000000000", format("%E15S", tp, tz));
289 
290   // With subseconds.
291   tp += chrono::milliseconds(6) + chrono::microseconds(7) +
292         chrono::nanoseconds(8);
293   EXPECT_EQ("05.006007008", format("%E*S", tp, tz));
294   EXPECT_EQ("05", format("%E0S", tp, tz));
295   EXPECT_EQ("05.0", format("%E1S", tp, tz));
296   EXPECT_EQ("05.00", format("%E2S", tp, tz));
297   EXPECT_EQ("05.006", format("%E3S", tp, tz));
298   EXPECT_EQ("05.0060", format("%E4S", tp, tz));
299   EXPECT_EQ("05.00600", format("%E5S", tp, tz));
300   EXPECT_EQ("05.006007", format("%E6S", tp, tz));
301   EXPECT_EQ("05.0060070", format("%E7S", tp, tz));
302   EXPECT_EQ("05.00600700", format("%E8S", tp, tz));
303   EXPECT_EQ("05.006007008", format("%E9S", tp, tz));
304   EXPECT_EQ("05.0060070080", format("%E10S", tp, tz));
305   EXPECT_EQ("05.00600700800", format("%E11S", tp, tz));
306   EXPECT_EQ("05.006007008000", format("%E12S", tp, tz));
307   EXPECT_EQ("05.0060070080000", format("%E13S", tp, tz));
308   EXPECT_EQ("05.00600700800000", format("%E14S", tp, tz));
309   EXPECT_EQ("05.006007008000000", format("%E15S", tp, tz));
310 
311   // Times before the Unix epoch.
312   tp = chrono::system_clock::from_time_t(0) + chrono::microseconds(-1);
313   EXPECT_EQ("1969-12-31 23:59:59.999999",
314             format("%Y-%m-%d %H:%M:%E*S", tp, tz));
315 
316   // Here is a "%E*S" case we got wrong for a while.  While the first
317   // instant below is correctly rendered as "...:07.333304", the second
318   // one used to appear as "...:07.33330499999999999".
319   tp = chrono::system_clock::from_time_t(0) +
320        chrono::microseconds(1395024427333304);
321   EXPECT_EQ("2014-03-17 02:47:07.333304",
322             format("%Y-%m-%d %H:%M:%E*S", tp, tz));
323   tp += chrono::microseconds(1);
324   EXPECT_EQ("2014-03-17 02:47:07.333305",
325             format("%Y-%m-%d %H:%M:%E*S", tp, tz));
326 }
327 
TEST(Format,ExtendedSubeconds)328 TEST(Format, ExtendedSubeconds) {
329   const time_zone tz = utc_time_zone();
330 
331   // No subseconds.
332   time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);
333   tp += chrono::seconds(5);
334   EXPECT_EQ("0", format("%E*f", tp, tz));
335   EXPECT_EQ("", format("%E0f", tp, tz));
336   EXPECT_EQ("0", format("%E1f", tp, tz));
337   EXPECT_EQ("00", format("%E2f", tp, tz));
338   EXPECT_EQ("000", format("%E3f", tp, tz));
339   EXPECT_EQ("0000", format("%E4f", tp, tz));
340   EXPECT_EQ("00000", format("%E5f", tp, tz));
341   EXPECT_EQ("000000", format("%E6f", tp, tz));
342   EXPECT_EQ("0000000", format("%E7f", tp, tz));
343   EXPECT_EQ("00000000", format("%E8f", tp, tz));
344   EXPECT_EQ("000000000", format("%E9f", tp, tz));
345   EXPECT_EQ("0000000000", format("%E10f", tp, tz));
346   EXPECT_EQ("00000000000", format("%E11f", tp, tz));
347   EXPECT_EQ("000000000000", format("%E12f", tp, tz));
348   EXPECT_EQ("0000000000000", format("%E13f", tp, tz));
349   EXPECT_EQ("00000000000000", format("%E14f", tp, tz));
350   EXPECT_EQ("000000000000000", format("%E15f", tp, tz));
351 
352   // With subseconds.
353   tp += chrono::milliseconds(6) + chrono::microseconds(7) +
354         chrono::nanoseconds(8);
355   EXPECT_EQ("006007008", format("%E*f", tp, tz));
356   EXPECT_EQ("", format("%E0f", tp, tz));
357   EXPECT_EQ("0", format("%E1f", tp, tz));
358   EXPECT_EQ("00", format("%E2f", tp, tz));
359   EXPECT_EQ("006", format("%E3f", tp, tz));
360   EXPECT_EQ("0060", format("%E4f", tp, tz));
361   EXPECT_EQ("00600", format("%E5f", tp, tz));
362   EXPECT_EQ("006007", format("%E6f", tp, tz));
363   EXPECT_EQ("0060070", format("%E7f", tp, tz));
364   EXPECT_EQ("00600700", format("%E8f", tp, tz));
365   EXPECT_EQ("006007008", format("%E9f", tp, tz));
366   EXPECT_EQ("0060070080", format("%E10f", tp, tz));
367   EXPECT_EQ("00600700800", format("%E11f", tp, tz));
368   EXPECT_EQ("006007008000", format("%E12f", tp, tz));
369   EXPECT_EQ("0060070080000", format("%E13f", tp, tz));
370   EXPECT_EQ("00600700800000", format("%E14f", tp, tz));
371   EXPECT_EQ("006007008000000", format("%E15f", tp, tz));
372 
373   // Times before the Unix epoch.
374   tp = chrono::system_clock::from_time_t(0) + chrono::microseconds(-1);
375   EXPECT_EQ("1969-12-31 23:59:59.999999",
376             format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz));
377 
378   // Here is a "%E*S" case we got wrong for a while.  While the first
379   // instant below is correctly rendered as "...:07.333304", the second
380   // one used to appear as "...:07.33330499999999999".
381   tp = chrono::system_clock::from_time_t(0) +
382        chrono::microseconds(1395024427333304);
383   EXPECT_EQ("2014-03-17 02:47:07.333304",
384             format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz));
385   tp += chrono::microseconds(1);
386   EXPECT_EQ("2014-03-17 02:47:07.333305",
387             format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz));
388 }
389 
TEST(Format,CompareExtendSecondsVsSubseconds)390 TEST(Format, CompareExtendSecondsVsSubseconds) {
391   const time_zone tz = utc_time_zone();
392 
393   // This test case illustrates the differences/similarities between:
394   //   fmt_A: %E<prec>S
395   //   fmt_B: %S.%E<prec>f
396   auto fmt_A = [](const std::string& prec) { return "%E" + prec + "S"; };
397   auto fmt_B = [](const std::string& prec) { return "%S.%E" + prec + "f"; };
398 
399   // No subseconds:
400   time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0);
401   tp += chrono::seconds(5);
402   // ... %E*S and %S.%E*f are different.
403   EXPECT_EQ("05", format(fmt_A("*"), tp, tz));
404   EXPECT_EQ("05.0", format(fmt_B("*"), tp, tz));
405   // ... %E0S and %S.%E0f are different.
406   EXPECT_EQ("05", format(fmt_A("0"), tp, tz));
407   EXPECT_EQ("05.", format(fmt_B("0"), tp, tz));
408   // ... %E<prec>S and %S.%E<prec>f are the same for prec in [1:15].
409   for (int prec = 1; prec <= 15; ++prec) {
410     const std::string a = format(fmt_A(std::to_string(prec)), tp, tz);
411     const std::string b = format(fmt_B(std::to_string(prec)), tp, tz);
412     EXPECT_EQ(a, b) << "prec=" << prec;
413   }
414 
415   // With subseconds:
416   // ... %E*S and %S.%E*f are the same.
417   tp += chrono::milliseconds(6) + chrono::microseconds(7) +
418         chrono::nanoseconds(8);
419   EXPECT_EQ("05.006007008", format(fmt_A("*"), tp, tz));
420   EXPECT_EQ("05.006007008", format(fmt_B("*"), tp, tz));
421   // ... %E0S and %S.%E0f are different.
422   EXPECT_EQ("05", format(fmt_A("0"), tp, tz));
423   EXPECT_EQ("05.", format(fmt_B("0"), tp, tz));
424   // ... %E<prec>S and %S.%E<prec>f are the same for prec in [1:15].
425   for (int prec = 1; prec <= 15; ++prec) {
426     const std::string a = format(fmt_A(std::to_string(prec)), tp, tz);
427     const std::string b = format(fmt_B(std::to_string(prec)), tp, tz);
428     EXPECT_EQ(a, b) << "prec=" << prec;
429   }
430 }
431 
TEST(Format,ExtendedOffset)432 TEST(Format, ExtendedOffset) {
433   const auto tp = chrono::system_clock::from_time_t(0);
434 
435   auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
436   TestFormatSpecifier(tp, tz, "%z", "+0000");
437   TestFormatSpecifier(tp, tz, "%:z", "+00:00");
438   TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
439 
440   tz = fixed_time_zone(chrono::seconds(56));
441   TestFormatSpecifier(tp, tz, "%z", "+0000");
442   TestFormatSpecifier(tp, tz, "%:z", "+00:00");
443   TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
444 
445   tz = fixed_time_zone(-chrono::seconds(56));  // NOTE: +00:00
446   TestFormatSpecifier(tp, tz, "%z", "+0000");
447   TestFormatSpecifier(tp, tz, "%:z", "+00:00");
448   TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
449 
450   tz = fixed_time_zone(chrono::minutes(34));
451   TestFormatSpecifier(tp, tz, "%z", "+0034");
452   TestFormatSpecifier(tp, tz, "%:z", "+00:34");
453   TestFormatSpecifier(tp, tz, "%Ez", "+00:34");
454 
455   tz = fixed_time_zone(-chrono::minutes(34));
456   TestFormatSpecifier(tp, tz, "%z", "-0034");
457   TestFormatSpecifier(tp, tz, "%:z", "-00:34");
458   TestFormatSpecifier(tp, tz, "%Ez", "-00:34");
459 
460   tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));
461   TestFormatSpecifier(tp, tz, "%z", "+0034");
462   TestFormatSpecifier(tp, tz, "%:z", "+00:34");
463   TestFormatSpecifier(tp, tz, "%Ez", "+00:34");
464 
465   tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));
466   TestFormatSpecifier(tp, tz, "%z", "-0034");
467   TestFormatSpecifier(tp, tz, "%:z", "-00:34");
468   TestFormatSpecifier(tp, tz, "%Ez", "-00:34");
469 
470   tz = fixed_time_zone(chrono::hours(12));
471   TestFormatSpecifier(tp, tz, "%z", "+1200");
472   TestFormatSpecifier(tp, tz, "%:z", "+12:00");
473   TestFormatSpecifier(tp, tz, "%Ez", "+12:00");
474 
475   tz = fixed_time_zone(-chrono::hours(12));
476   TestFormatSpecifier(tp, tz, "%z", "-1200");
477   TestFormatSpecifier(tp, tz, "%:z", "-12:00");
478   TestFormatSpecifier(tp, tz, "%Ez", "-12:00");
479 
480   tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));
481   TestFormatSpecifier(tp, tz, "%z", "+1200");
482   TestFormatSpecifier(tp, tz, "%:z", "+12:00");
483   TestFormatSpecifier(tp, tz, "%Ez", "+12:00");
484 
485   tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));
486   TestFormatSpecifier(tp, tz, "%z", "-1200");
487   TestFormatSpecifier(tp, tz, "%:z", "-12:00");
488   TestFormatSpecifier(tp, tz, "%Ez", "-12:00");
489 
490   tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));
491   TestFormatSpecifier(tp, tz, "%z", "+1234");
492   TestFormatSpecifier(tp, tz, "%:z", "+12:34");
493   TestFormatSpecifier(tp, tz, "%Ez", "+12:34");
494 
495   tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));
496   TestFormatSpecifier(tp, tz, "%z", "-1234");
497   TestFormatSpecifier(tp, tz, "%:z", "-12:34");
498   TestFormatSpecifier(tp, tz, "%Ez", "-12:34");
499 
500   tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +
501                        chrono::seconds(56));
502   TestFormatSpecifier(tp, tz, "%z", "+1234");
503   TestFormatSpecifier(tp, tz, "%:z", "+12:34");
504   TestFormatSpecifier(tp, tz, "%Ez", "+12:34");
505 
506   tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -
507                        chrono::seconds(56));
508   TestFormatSpecifier(tp, tz, "%z", "-1234");
509   TestFormatSpecifier(tp, tz, "%:z", "-12:34");
510   TestFormatSpecifier(tp, tz, "%Ez", "-12:34");
511 }
512 
TEST(Format,ExtendedSecondOffset)513 TEST(Format, ExtendedSecondOffset) {
514   const auto tp = chrono::system_clock::from_time_t(0);
515 
516   auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
517   TestFormatSpecifier(tp, tz, "%E*z", "+00:00:00");
518   TestFormatSpecifier(tp, tz, "%::z", "+00:00:00");
519   TestFormatSpecifier(tp, tz, "%:::z", "+00");
520 
521   tz = fixed_time_zone(chrono::seconds(56));
522   TestFormatSpecifier(tp, tz, "%E*z", "+00:00:56");
523   TestFormatSpecifier(tp, tz, "%::z", "+00:00:56");
524   TestFormatSpecifier(tp, tz, "%:::z", "+00:00:56");
525 
526   tz = fixed_time_zone(-chrono::seconds(56));
527   TestFormatSpecifier(tp, tz, "%E*z", "-00:00:56");
528   TestFormatSpecifier(tp, tz, "%::z", "-00:00:56");
529   TestFormatSpecifier(tp, tz, "%:::z", "-00:00:56");
530 
531   tz = fixed_time_zone(chrono::minutes(34));
532   TestFormatSpecifier(tp, tz, "%E*z", "+00:34:00");
533   TestFormatSpecifier(tp, tz, "%::z", "+00:34:00");
534   TestFormatSpecifier(tp, tz, "%:::z", "+00:34");
535 
536   tz = fixed_time_zone(-chrono::minutes(34));
537   TestFormatSpecifier(tp, tz, "%E*z", "-00:34:00");
538   TestFormatSpecifier(tp, tz, "%::z", "-00:34:00");
539   TestFormatSpecifier(tp, tz, "%:::z", "-00:34");
540 
541   tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));
542   TestFormatSpecifier(tp, tz, "%E*z", "+00:34:56");
543   TestFormatSpecifier(tp, tz, "%::z", "+00:34:56");
544   TestFormatSpecifier(tp, tz, "%:::z", "+00:34:56");
545 
546   tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));
547   TestFormatSpecifier(tp, tz, "%E*z", "-00:34:56");
548   TestFormatSpecifier(tp, tz, "%::z", "-00:34:56");
549   TestFormatSpecifier(tp, tz, "%:::z", "-00:34:56");
550 
551   tz = fixed_time_zone(chrono::hours(12));
552   TestFormatSpecifier(tp, tz, "%E*z", "+12:00:00");
553   TestFormatSpecifier(tp, tz, "%::z", "+12:00:00");
554   TestFormatSpecifier(tp, tz, "%:::z", "+12");
555 
556   tz = fixed_time_zone(-chrono::hours(12));
557   TestFormatSpecifier(tp, tz, "%E*z", "-12:00:00");
558   TestFormatSpecifier(tp, tz, "%::z", "-12:00:00");
559   TestFormatSpecifier(tp, tz, "%:::z", "-12");
560 
561   tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));
562   TestFormatSpecifier(tp, tz, "%E*z", "+12:00:56");
563   TestFormatSpecifier(tp, tz, "%::z", "+12:00:56");
564   TestFormatSpecifier(tp, tz, "%:::z", "+12:00:56");
565 
566   tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));
567   TestFormatSpecifier(tp, tz, "%E*z", "-12:00:56");
568   TestFormatSpecifier(tp, tz, "%::z", "-12:00:56");
569   TestFormatSpecifier(tp, tz, "%:::z", "-12:00:56");
570 
571   tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));
572   TestFormatSpecifier(tp, tz, "%E*z", "+12:34:00");
573   TestFormatSpecifier(tp, tz, "%::z", "+12:34:00");
574   TestFormatSpecifier(tp, tz, "%:::z", "+12:34");
575 
576   tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));
577   TestFormatSpecifier(tp, tz, "%E*z", "-12:34:00");
578   TestFormatSpecifier(tp, tz, "%::z", "-12:34:00");
579   TestFormatSpecifier(tp, tz, "%:::z", "-12:34");
580 
581   tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +
582                        chrono::seconds(56));
583   TestFormatSpecifier(tp, tz, "%E*z", "+12:34:56");
584   TestFormatSpecifier(tp, tz, "%::z", "+12:34:56");
585   TestFormatSpecifier(tp, tz, "%:::z", "+12:34:56");
586 
587   tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -
588                        chrono::seconds(56));
589   TestFormatSpecifier(tp, tz, "%E*z", "-12:34:56");
590   TestFormatSpecifier(tp, tz, "%::z", "-12:34:56");
591   TestFormatSpecifier(tp, tz, "%:::z", "-12:34:56");
592 }
593 
TEST(Format,ExtendedYears)594 TEST(Format, ExtendedYears) {
595   const time_zone utc = utc_time_zone();
596   const char e4y_fmt[] = "%E4Y%m%d";  // no separators
597 
598   // %E4Y zero-pads the year to produce at least 4 chars, including the sign.
599   auto tp = convert(civil_second(-999, 11, 27, 0, 0, 0), utc);
600   EXPECT_EQ("-9991127", format(e4y_fmt, tp, utc));
601   tp = convert(civil_second(-99, 11, 27, 0, 0, 0), utc);
602   EXPECT_EQ("-0991127", format(e4y_fmt, tp, utc));
603   tp = convert(civil_second(-9, 11, 27, 0, 0, 0), utc);
604   EXPECT_EQ("-0091127", format(e4y_fmt, tp, utc));
605   tp = convert(civil_second(-1, 11, 27, 0, 0, 0), utc);
606   EXPECT_EQ("-0011127", format(e4y_fmt, tp, utc));
607   tp = convert(civil_second(0, 11, 27, 0, 0, 0), utc);
608   EXPECT_EQ("00001127", format(e4y_fmt, tp, utc));
609   tp = convert(civil_second(1, 11, 27, 0, 0, 0), utc);
610   EXPECT_EQ("00011127", format(e4y_fmt, tp, utc));
611   tp = convert(civil_second(9, 11, 27, 0, 0, 0), utc);
612   EXPECT_EQ("00091127", format(e4y_fmt, tp, utc));
613   tp = convert(civil_second(99, 11, 27, 0, 0, 0), utc);
614   EXPECT_EQ("00991127", format(e4y_fmt, tp, utc));
615   tp = convert(civil_second(999, 11, 27, 0, 0, 0), utc);
616   EXPECT_EQ("09991127", format(e4y_fmt, tp, utc));
617   tp = convert(civil_second(9999, 11, 27, 0, 0, 0), utc);
618   EXPECT_EQ("99991127", format(e4y_fmt, tp, utc));
619 
620   // When the year is outside [-999:9999], more than 4 chars are produced.
621   tp = convert(civil_second(-1000, 11, 27, 0, 0, 0), utc);
622   EXPECT_EQ("-10001127", format(e4y_fmt, tp, utc));
623   tp = convert(civil_second(10000, 11, 27, 0, 0, 0), utc);
624   EXPECT_EQ("100001127", format(e4y_fmt, tp, utc));
625 }
626 
TEST(Format,RFC3339Format)627 TEST(Format, RFC3339Format) {
628   time_zone tz;
629   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
630 
631   time_point<chrono::nanoseconds> tp =
632       convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
633   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_full, tp, tz));
634   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
635 
636   tp += chrono::milliseconds(100);
637   EXPECT_EQ("1977-06-28T09:08:07.1-07:00", format(RFC3339_full, tp, tz));
638   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
639 
640   tp += chrono::milliseconds(20);
641   EXPECT_EQ("1977-06-28T09:08:07.12-07:00", format(RFC3339_full, tp, tz));
642   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
643 
644   tp += chrono::milliseconds(3);
645   EXPECT_EQ("1977-06-28T09:08:07.123-07:00", format(RFC3339_full, tp, tz));
646   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
647 
648   tp += chrono::microseconds(400);
649   EXPECT_EQ("1977-06-28T09:08:07.1234-07:00", format(RFC3339_full, tp, tz));
650   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
651 
652   tp += chrono::microseconds(50);
653   EXPECT_EQ("1977-06-28T09:08:07.12345-07:00", format(RFC3339_full, tp, tz));
654   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
655 
656   tp += chrono::microseconds(6);
657   EXPECT_EQ("1977-06-28T09:08:07.123456-07:00", format(RFC3339_full, tp, tz));
658   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
659 
660   tp += chrono::nanoseconds(700);
661   EXPECT_EQ("1977-06-28T09:08:07.1234567-07:00", format(RFC3339_full, tp, tz));
662   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
663 
664   tp += chrono::nanoseconds(80);
665   EXPECT_EQ("1977-06-28T09:08:07.12345678-07:00", format(RFC3339_full, tp, tz));
666   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
667 
668   tp += chrono::nanoseconds(9);
669   EXPECT_EQ("1977-06-28T09:08:07.123456789-07:00",
670             format(RFC3339_full, tp, tz));
671   EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz));
672 }
673 
TEST(Format,RFC1123Format)674 TEST(Format, RFC1123Format) {  // locale specific
675   time_zone tz;
676   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
677 
678   auto tp = convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
679   EXPECT_EQ("Tue, 28 Jun 1977 09:08:07 -0700", format(RFC1123_full, tp, tz));
680   EXPECT_EQ("28 Jun 1977 09:08:07 -0700", format(RFC1123_no_wday, tp, tz));
681 }
682 
TEST(Format,Week)683 TEST(Format, Week) {
684   const time_zone utc = utc_time_zone();
685 
686   auto tp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc);
687   EXPECT_EQ("2017-01-7", format("%Y-%U-%u", tp, utc));
688   EXPECT_EQ("2017-00-0", format("%Y-%W-%w", tp, utc));
689 
690   tp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc);
691   EXPECT_EQ("2017-53-7", format("%Y-%U-%u", tp, utc));
692   EXPECT_EQ("2017-52-0", format("%Y-%W-%w", tp, utc));
693 
694   tp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc);
695   EXPECT_EQ("2018-00-1", format("%Y-%U-%u", tp, utc));
696   EXPECT_EQ("2018-01-1", format("%Y-%W-%w", tp, utc));
697 
698   tp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc);
699   EXPECT_EQ("2018-52-1", format("%Y-%U-%u", tp, utc));
700   EXPECT_EQ("2018-53-1", format("%Y-%W-%w", tp, utc));
701 
702   tp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc);
703   EXPECT_EQ("2019-00-2", format("%Y-%U-%u", tp, utc));
704   EXPECT_EQ("2019-00-2", format("%Y-%W-%w", tp, utc));
705 
706   tp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc);
707   EXPECT_EQ("2019-52-2", format("%Y-%U-%u", tp, utc));
708   EXPECT_EQ("2019-52-2", format("%Y-%W-%w", tp, utc));
709 }
710 
711 //
712 // Testing parse()
713 //
714 
TEST(Parse,TimePointResolution)715 TEST(Parse, TimePointResolution) {
716   const char kFmt[] = "%H:%M:%E*S";
717   const time_zone utc = utc_time_zone();
718 
719   time_point<chrono::nanoseconds> tp_ns;
720   EXPECT_TRUE(parse(kFmt, "03:04:05.123456789", utc, &tp_ns));
721   EXPECT_EQ("03:04:05.123456789", format(kFmt, tp_ns, utc));
722   EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_ns));
723   EXPECT_EQ("03:04:05.123456", format(kFmt, tp_ns, utc));
724 
725   time_point<chrono::microseconds> tp_us;
726   EXPECT_TRUE(parse(kFmt, "03:04:05.123456789", utc, &tp_us));
727   EXPECT_EQ("03:04:05.123456", format(kFmt, tp_us, utc));
728   EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_us));
729   EXPECT_EQ("03:04:05.123456", format(kFmt, tp_us, utc));
730   EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_us));
731   EXPECT_EQ("03:04:05.123", format(kFmt, tp_us, utc));
732 
733   time_point<chrono::milliseconds> tp_ms;
734   EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_ms));
735   EXPECT_EQ("03:04:05.123", format(kFmt, tp_ms, utc));
736   EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_ms));
737   EXPECT_EQ("03:04:05.123", format(kFmt, tp_ms, utc));
738   EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_ms));
739   EXPECT_EQ("03:04:05", format(kFmt, tp_ms, utc));
740 
741   time_point<chrono::seconds> tp_s;
742   EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_s));
743   EXPECT_EQ("03:04:05", format(kFmt, tp_s, utc));
744   EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_s));
745   EXPECT_EQ("03:04:05", format(kFmt, tp_s, utc));
746 
747   time_point<chrono::minutes> tp_m;
748   EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_m));
749   EXPECT_EQ("03:04:00", format(kFmt, tp_m, utc));
750 
751   time_point<chrono::hours> tp_h;
752   EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_h));
753   EXPECT_EQ("03:00:00", format(kFmt, tp_h, utc));
754 }
755 
TEST(Parse,TimePointExtendedResolution)756 TEST(Parse, TimePointExtendedResolution) {
757   const char kFmt[] = "%H:%M:%E*S";
758   const time_zone utc = utc_time_zone();
759 
760   time_point<absl::time_internal::cctz::seconds> tp;
761   detail::femtoseconds fs;
762   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.123456789012345", utc, &tp, &fs));
763   EXPECT_EQ("12:34:56.123456789012345", detail::format(kFmt, tp, fs, utc));
764   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.012345678901234", utc, &tp, &fs));
765   EXPECT_EQ("12:34:56.012345678901234", detail::format(kFmt, tp, fs, utc));
766   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.001234567890123", utc, &tp, &fs));
767   EXPECT_EQ("12:34:56.001234567890123", detail::format(kFmt, tp, fs, utc));
768   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000123", utc, &tp, &fs));
769   EXPECT_EQ("12:34:56.000000000000123", detail::format(kFmt, tp, fs, utc));
770   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000012", utc, &tp, &fs));
771   EXPECT_EQ("12:34:56.000000000000012", detail::format(kFmt, tp, fs, utc));
772   EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000001", utc, &tp, &fs));
773   EXPECT_EQ("12:34:56.000000000000001", detail::format(kFmt, tp, fs, utc));
774 }
775 
TEST(Parse,Basics)776 TEST(Parse, Basics) {
777   time_zone tz = utc_time_zone();
778   time_point<chrono::nanoseconds> tp =
779       chrono::system_clock::from_time_t(1234567890);
780 
781   // Simple edge cases.
782   EXPECT_TRUE(parse("", "", tz, &tp));
783   EXPECT_EQ(chrono::system_clock::from_time_t(0), tp);  // everything defaulted
784   EXPECT_TRUE(parse(" ", " ", tz, &tp));
785   EXPECT_TRUE(parse("  ", "  ", tz, &tp));
786   EXPECT_TRUE(parse("x", "x", tz, &tp));
787   EXPECT_TRUE(parse("xxx", "xxx", tz, &tp));
788 
789   EXPECT_TRUE(
790       parse("%Y-%m-%d %H:%M:%S %z", "2013-06-28 19:08:09 -0800", tz, &tp));
791   ExpectTime(tp, tz, 2013, 6, 29, 3, 8, 9, 0, false, "UTC");
792 }
793 
TEST(Parse,WithTimeZone)794 TEST(Parse, WithTimeZone) {
795   time_zone tz;
796   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
797   time_point<chrono::nanoseconds> tp;
798 
799   // We can parse a string without a UTC offset if we supply a timezone.
800   EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &tp));
801   ExpectTime(tp, tz, 2013, 6, 28, 19, 8, 9, -7 * 60 * 60, true, "PDT");
802 
803   // But the timezone is ignored when a UTC offset is present.
804   EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S %z", "2013-06-28 19:08:09 +0800",
805                     utc_time_zone(), &tp));
806   ExpectTime(tp, tz, 2013, 6, 28, 19 - 8 - 7, 8, 9, -7 * 60 * 60, true, "PDT");
807 
808   // Check a skipped time (a Spring DST transition). parse() uses the
809   // pre-transition offset.
810   EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2011-03-13 02:15:00", tz, &tp));
811   ExpectTime(tp, tz, 2011, 3, 13, 3, 15, 0, -7 * 60 * 60, true, "PDT");
812 
813   // Check a repeated time (a Fall DST transition).  parse() uses the
814   // pre-transition offset.
815   EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2011-11-06 01:15:00", tz, &tp));
816   ExpectTime(tp, tz, 2011, 11, 6, 1, 15, 0, -7 * 60 * 60, true, "PDT");
817 }
818 
TEST(Parse,LeapSecond)819 TEST(Parse, LeapSecond) {
820   time_zone tz;
821   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
822   time_point<chrono::nanoseconds> tp;
823 
824   // ":59" -> ":59"
825   EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:59-08:00", tz, &tp));
826   ExpectTime(tp, tz, 2013, 6, 28, 8, 8, 59, -7 * 60 * 60, true, "PDT");
827 
828   // ":59.5" -> ":59.5"
829   EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:59.5-08:00", tz, &tp));
830   ExpectTime(tp, tz, 2013, 6, 28, 8, 8, 59, -7 * 60 * 60, true, "PDT");
831 
832   // ":60" -> ":00"
833   EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:60-08:00", tz, &tp));
834   ExpectTime(tp, tz, 2013, 6, 28, 8, 9, 0, -7 * 60 * 60, true, "PDT");
835 
836   // ":60.5" -> ":00.0"
837   EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:60.5-08:00", tz, &tp));
838   ExpectTime(tp, tz, 2013, 6, 28, 8, 9, 0, -7 * 60 * 60, true, "PDT");
839 
840   // ":61" -> error
841   EXPECT_FALSE(parse(RFC3339_full, "2013-06-28T07:08:61-08:00", tz, &tp));
842 }
843 
TEST(Parse,ErrorCases)844 TEST(Parse, ErrorCases) {
845   const time_zone tz = utc_time_zone();
846   auto tp = chrono::system_clock::from_time_t(0);
847 
848   // Illegal trailing data.
849   EXPECT_FALSE(parse("%S", "123", tz, &tp));
850 
851   // Can't parse an illegal format specifier.
852   EXPECT_FALSE(parse("%Q", "x", tz, &tp));
853 
854   // Fails because of trailing, unparsed data "blah".
855   EXPECT_FALSE(parse("%m-%d", "2-3 blah", tz, &tp));
856 
857   // Trailing whitespace is allowed.
858   EXPECT_TRUE(parse("%m-%d", "2-3  ", tz, &tp));
859   EXPECT_EQ(2, convert(tp, utc_time_zone()).month());
860   EXPECT_EQ(3, convert(tp, utc_time_zone()).day());
861 
862   // Feb 31 requires normalization.
863   EXPECT_FALSE(parse("%m-%d", "2-31", tz, &tp));
864 
865   // Check that we cannot have spaces in UTC offsets.
866   EXPECT_TRUE(parse("%z", "-0203", tz, &tp));
867   EXPECT_FALSE(parse("%z", "- 2 3", tz, &tp));
868   EXPECT_TRUE(parse("%Ez", "-02:03", tz, &tp));
869   EXPECT_FALSE(parse("%Ez", "- 2: 3", tz, &tp));
870 
871   // Check that we reject other malformed UTC offsets.
872   EXPECT_FALSE(parse("%Ez", "+-08:00", tz, &tp));
873   EXPECT_FALSE(parse("%Ez", "-+08:00", tz, &tp));
874 
875   // Check that we do not accept "-0" in fields that allow zero.
876   EXPECT_FALSE(parse("%Y", "-0", tz, &tp));
877   EXPECT_FALSE(parse("%E4Y", "-0", tz, &tp));
878   EXPECT_FALSE(parse("%H", "-0", tz, &tp));
879   EXPECT_FALSE(parse("%M", "-0", tz, &tp));
880   EXPECT_FALSE(parse("%S", "-0", tz, &tp));
881   EXPECT_FALSE(parse("%z", "+-000", tz, &tp));
882   EXPECT_FALSE(parse("%Ez", "+-0:00", tz, &tp));
883   EXPECT_FALSE(parse("%z", "-00-0", tz, &tp));
884   EXPECT_FALSE(parse("%Ez", "-00:-0", tz, &tp));
885 }
886 
TEST(Parse,PosixConversions)887 TEST(Parse, PosixConversions) {
888   time_zone tz = utc_time_zone();
889   auto tp = chrono::system_clock::from_time_t(0);
890   const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
891 
892   tp = reset;
893   EXPECT_TRUE(parse("%d", "15", tz, &tp));
894   EXPECT_EQ(15, convert(tp, tz).day());
895 
896   // %e is an extension, but is supported internally.
897   tp = reset;
898   EXPECT_TRUE(parse("%e", "15", tz, &tp));
899   EXPECT_EQ(15, convert(tp, tz).day());  // Equivalent to %d
900 
901   tp = reset;
902   EXPECT_TRUE(parse("%H", "17", tz, &tp));
903   EXPECT_EQ(17, convert(tp, tz).hour());
904 
905   tp = reset;
906   EXPECT_TRUE(parse("%I", "5", tz, &tp));
907   EXPECT_EQ(5, convert(tp, tz).hour());
908 
909   // %j is parsed but ignored.
910   EXPECT_TRUE(parse("%j", "32", tz, &tp));
911 
912   tp = reset;
913   EXPECT_TRUE(parse("%m", "11", tz, &tp));
914   EXPECT_EQ(11, convert(tp, tz).month());
915 
916   tp = reset;
917   EXPECT_TRUE(parse("%M", "33", tz, &tp));
918   EXPECT_EQ(33, convert(tp, tz).minute());
919 
920   tp = reset;
921   EXPECT_TRUE(parse("%S", "55", tz, &tp));
922   EXPECT_EQ(55, convert(tp, tz).second());
923 
924   // %U is parsed but ignored.
925   EXPECT_TRUE(parse("%U", "15", tz, &tp));
926 
927   // %w is parsed but ignored.
928   EXPECT_TRUE(parse("%w", "2", tz, &tp));
929 
930   // %W is parsed but ignored.
931   EXPECT_TRUE(parse("%W", "22", tz, &tp));
932 
933   tp = reset;
934   EXPECT_TRUE(parse("%y", "04", tz, &tp));
935   EXPECT_EQ(2004, convert(tp, tz).year());
936 
937   tp = reset;
938   EXPECT_TRUE(parse("%Y", "2004", tz, &tp));
939   EXPECT_EQ(2004, convert(tp, tz).year());
940 
941   EXPECT_TRUE(parse("%%", "%", tz, &tp));
942 
943 #if defined(__linux__)
944   // SU/C99/TZ extensions
945 
946   // Because we handle each (non-internal) specifier in a separate call
947   // to strptime(), there is no way to group %C and %y together.  So we
948   // just skip the %C/%y case.
949 #if 0
950   tp = reset;
951   EXPECT_TRUE(parse("%C %y", "20 04", tz, &tp));
952   EXPECT_EQ(2004, convert(tp, tz).year());
953 #endif
954 
955   tp = reset;
956   EXPECT_TRUE(parse("%D", "02/03/04", tz, &tp));
957   EXPECT_EQ(2, convert(tp, tz).month());
958   EXPECT_EQ(3, convert(tp, tz).day());
959   EXPECT_EQ(2004, convert(tp, tz).year());
960 
961   EXPECT_TRUE(parse("%n", "\n", tz, &tp));
962 
963   tp = reset;
964   EXPECT_TRUE(parse("%R", "03:44", tz, &tp));
965   EXPECT_EQ(3, convert(tp, tz).hour());
966   EXPECT_EQ(44, convert(tp, tz).minute());
967 
968   EXPECT_TRUE(parse("%t", "\t\v\f\n\r ", tz, &tp));
969 
970   tp = reset;
971   EXPECT_TRUE(parse("%T", "03:44:55", tz, &tp));
972   EXPECT_EQ(3, convert(tp, tz).hour());
973   EXPECT_EQ(44, convert(tp, tz).minute());
974   EXPECT_EQ(55, convert(tp, tz).second());
975 
976   tp = reset;
977   EXPECT_TRUE(parse("%s", "1234567890", tz, &tp));
978   EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp);
979 
980   // %s conversion, like %z/%Ez, pays no heed to the optional zone.
981   time_zone lax;
982   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &lax));
983   tp = reset;
984   EXPECT_TRUE(parse("%s", "1234567890", lax, &tp));
985   EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp);
986 
987   // This is most important when the time has the same YMDhms
988   // breakdown in the zone as some other time.  For example, ...
989   //  1414917000 in US/Pacific -> Sun Nov 2 01:30:00 2014 (PDT)
990   //  1414920600 in US/Pacific -> Sun Nov 2 01:30:00 2014 (PST)
991   tp = reset;
992   EXPECT_TRUE(parse("%s", "1414917000", lax, &tp));
993   EXPECT_EQ(chrono::system_clock::from_time_t(1414917000), tp);
994   tp = reset;
995   EXPECT_TRUE(parse("%s", "1414920600", lax, &tp));
996   EXPECT_EQ(chrono::system_clock::from_time_t(1414920600), tp);
997 #endif
998 }
999 
TEST(Parse,LocaleSpecific)1000 TEST(Parse, LocaleSpecific) {
1001   time_zone tz = utc_time_zone();
1002   auto tp = chrono::system_clock::from_time_t(0);
1003   const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz);
1004 
1005   // %a is parsed but ignored.
1006   EXPECT_TRUE(parse("%a", "Mon", tz, &tp));
1007 
1008   // %A is parsed but ignored.
1009   EXPECT_TRUE(parse("%A", "Monday", tz, &tp));
1010 
1011   tp = reset;
1012   EXPECT_TRUE(parse("%b", "Feb", tz, &tp));
1013   EXPECT_EQ(2, convert(tp, tz).month());
1014 
1015   tp = reset;
1016   EXPECT_TRUE(parse("%B", "February", tz, &tp));
1017   EXPECT_EQ(2, convert(tp, tz).month());
1018 
1019   // %p is parsed but ignored if it's alone.  But it's used with %I.
1020   EXPECT_TRUE(parse("%p", "AM", tz, &tp));
1021   tp = reset;
1022   EXPECT_TRUE(parse("%I %p", "5 PM", tz, &tp));
1023   EXPECT_EQ(17, convert(tp, tz).hour());
1024 
1025   tp = reset;
1026   EXPECT_TRUE(parse("%x", "02/03/04", tz, &tp));
1027   if (convert(tp, tz).month() == 2) {
1028     EXPECT_EQ(3, convert(tp, tz).day());
1029   } else {
1030     EXPECT_EQ(2, convert(tp, tz).day());
1031     EXPECT_EQ(3, convert(tp, tz).month());
1032   }
1033   EXPECT_EQ(2004, convert(tp, tz).year());
1034 
1035   tp = reset;
1036   EXPECT_TRUE(parse("%X", "15:44:55", tz, &tp));
1037   EXPECT_EQ(15, convert(tp, tz).hour());
1038   EXPECT_EQ(44, convert(tp, tz).minute());
1039   EXPECT_EQ(55, convert(tp, tz).second());
1040 
1041 #if defined(__linux__)
1042   // SU/C99/TZ extensions
1043 
1044   tp = reset;
1045   EXPECT_TRUE(parse("%h", "Feb", tz, &tp));
1046   EXPECT_EQ(2, convert(tp, tz).month());  // Equivalent to %b
1047 
1048   tp = reset;
1049   EXPECT_TRUE(parse("%l %p", "5 PM", tz, &tp));
1050   EXPECT_EQ(17, convert(tp, tz).hour());
1051 
1052   tp = reset;
1053   EXPECT_TRUE(parse("%r", "03:44:55 PM", tz, &tp));
1054   EXPECT_EQ(15, convert(tp, tz).hour());
1055   EXPECT_EQ(44, convert(tp, tz).minute());
1056   EXPECT_EQ(55, convert(tp, tz).second());
1057 
1058   tp = reset;
1059   EXPECT_TRUE(parse("%Ec", "Tue Nov 19 05:06:07 2013", tz, &tp));
1060   EXPECT_EQ(convert(civil_second(2013, 11, 19, 5, 6, 7), tz), tp);
1061 
1062   // Modified conversion specifiers %E_
1063 
1064   tp = reset;
1065   EXPECT_TRUE(parse("%Ex", "02/03/04", tz, &tp));
1066   EXPECT_EQ(2, convert(tp, tz).month());
1067   EXPECT_EQ(3, convert(tp, tz).day());
1068   EXPECT_EQ(2004, convert(tp, tz).year());
1069 
1070   tp = reset;
1071   EXPECT_TRUE(parse("%EX", "15:44:55", tz, &tp));
1072   EXPECT_EQ(15, convert(tp, tz).hour());
1073   EXPECT_EQ(44, convert(tp, tz).minute());
1074   EXPECT_EQ(55, convert(tp, tz).second());
1075 
1076   // %Ey, the year offset from %EC, doesn't really make sense alone as there
1077   // is no way to represent it in tm_year (%EC is not simply the century).
1078   // Yet, because we handle each (non-internal) specifier in a separate call
1079   // to strptime(), there is no way to group %EC and %Ey either.  So we just
1080   // skip the %EC and %Ey cases.
1081 
1082   tp = reset;
1083   EXPECT_TRUE(parse("%EY", "2004", tz, &tp));
1084   EXPECT_EQ(2004, convert(tp, tz).year());
1085 
1086   // Modified conversion specifiers %O_
1087 
1088   tp = reset;
1089   EXPECT_TRUE(parse("%Od", "15", tz, &tp));
1090   EXPECT_EQ(15, convert(tp, tz).day());
1091 
1092   tp = reset;
1093   EXPECT_TRUE(parse("%Oe", "15", tz, &tp));
1094   EXPECT_EQ(15, convert(tp, tz).day());  // Equivalent to %d
1095 
1096   tp = reset;
1097   EXPECT_TRUE(parse("%OH", "17", tz, &tp));
1098   EXPECT_EQ(17, convert(tp, tz).hour());
1099 
1100   tp = reset;
1101   EXPECT_TRUE(parse("%OI", "5", tz, &tp));
1102   EXPECT_EQ(5, convert(tp, tz).hour());
1103 
1104   tp = reset;
1105   EXPECT_TRUE(parse("%Om", "11", tz, &tp));
1106   EXPECT_EQ(11, convert(tp, tz).month());
1107 
1108   tp = reset;
1109   EXPECT_TRUE(parse("%OM", "33", tz, &tp));
1110   EXPECT_EQ(33, convert(tp, tz).minute());
1111 
1112   tp = reset;
1113   EXPECT_TRUE(parse("%OS", "55", tz, &tp));
1114   EXPECT_EQ(55, convert(tp, tz).second());
1115 
1116   // %OU is parsed but ignored.
1117   EXPECT_TRUE(parse("%OU", "15", tz, &tp));
1118 
1119   // %Ow is parsed but ignored.
1120   EXPECT_TRUE(parse("%Ow", "2", tz, &tp));
1121 
1122   // %OW is parsed but ignored.
1123   EXPECT_TRUE(parse("%OW", "22", tz, &tp));
1124 
1125   tp = reset;
1126   EXPECT_TRUE(parse("%Oy", "04", tz, &tp));
1127   EXPECT_EQ(2004, convert(tp, tz).year());
1128 #endif
1129 }
1130 
TEST(Parse,ExtendedSeconds)1131 TEST(Parse, ExtendedSeconds) {
1132   const time_zone tz = utc_time_zone();
1133   const time_point<chrono::nanoseconds> unix_epoch =
1134       chrono::system_clock::from_time_t(0);
1135 
1136   // All %E<prec>S cases are treated the same as %E*S on input.
1137   auto precisions = {"*", "0", "1",  "2",  "3",  "4",  "5",  "6", "7",
1138                      "8", "9", "10", "11", "12", "13", "14", "15"};
1139   for (const std::string prec : precisions) {
1140     const std::string fmt = "%E" + prec + "S";
1141     SCOPED_TRACE(fmt);
1142     time_point<chrono::nanoseconds> tp = unix_epoch;
1143     EXPECT_TRUE(parse(fmt, "5", tz, &tp));
1144     EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);
1145     tp = unix_epoch;
1146     EXPECT_TRUE(parse(fmt, "05", tz, &tp));
1147     EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);
1148     tp = unix_epoch;
1149     EXPECT_TRUE(parse(fmt, "05.0", tz, &tp));
1150     EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);
1151     tp = unix_epoch;
1152     EXPECT_TRUE(parse(fmt, "05.00", tz, &tp));
1153     EXPECT_EQ(unix_epoch + chrono::seconds(5), tp);
1154     tp = unix_epoch;
1155     EXPECT_TRUE(parse(fmt, "05.6", tz, &tp));
1156     EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp);
1157     tp = unix_epoch;
1158     EXPECT_TRUE(parse(fmt, "05.60", tz, &tp));
1159     EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp);
1160     tp = unix_epoch;
1161     EXPECT_TRUE(parse(fmt, "05.600", tz, &tp));
1162     EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp);
1163     tp = unix_epoch;
1164     EXPECT_TRUE(parse(fmt, "05.67", tz, &tp));
1165     EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(670), tp);
1166     tp = unix_epoch;
1167     EXPECT_TRUE(parse(fmt, "05.670", tz, &tp));
1168     EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(670), tp);
1169     tp = unix_epoch;
1170     EXPECT_TRUE(parse(fmt, "05.678", tz, &tp));
1171     EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(678), tp);
1172   }
1173 
1174   // Here is a "%E*S" case we got wrong for a while.  The fractional
1175   // part of the first instant is less than 2^31 and was correctly
1176   // parsed, while the second (and any subsecond field >=2^31) failed.
1177   time_point<chrono::nanoseconds> tp = unix_epoch;
1178   EXPECT_TRUE(parse("%E*S", "0.2147483647", tz, &tp));
1179   EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
1180   tp = unix_epoch;
1181   EXPECT_TRUE(parse("%E*S", "0.2147483648", tz, &tp));
1182   EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
1183 
1184   // We should also be able to specify long strings of digits far
1185   // beyond the current resolution and have them convert the same way.
1186   tp = unix_epoch;
1187   EXPECT_TRUE(parse(
1188       "%E*S", "0.214748364801234567890123456789012345678901234567890123456789",
1189       tz, &tp));
1190   EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
1191 }
1192 
TEST(Parse,ExtendedSecondsScan)1193 TEST(Parse, ExtendedSecondsScan) {
1194   const time_zone tz = utc_time_zone();
1195   time_point<chrono::nanoseconds> tp;
1196   for (int ms = 0; ms < 1000; ms += 111) {
1197     for (int us = 0; us < 1000; us += 27) {
1198       const int micros = ms * 1000 + us;
1199       for (int ns = 0; ns < 1000; ns += 9) {
1200         const auto expected = chrono::system_clock::from_time_t(0) +
1201                               chrono::nanoseconds(micros * 1000 + ns);
1202         std::ostringstream oss;
1203         oss << "0." << std::setfill('0') << std::setw(3);
1204         oss << ms << std::setw(3) << us << std::setw(3) << ns;
1205         const std::string input = oss.str();
1206         EXPECT_TRUE(parse("%E*S", input, tz, &tp));
1207         EXPECT_EQ(expected, tp) << input;
1208       }
1209     }
1210   }
1211 }
1212 
TEST(Parse,ExtendedSubeconds)1213 TEST(Parse, ExtendedSubeconds) {
1214   const time_zone tz = utc_time_zone();
1215   const time_point<chrono::nanoseconds> unix_epoch =
1216       chrono::system_clock::from_time_t(0);
1217 
1218   // All %E<prec>f cases are treated the same as %E*f on input.
1219   auto precisions = {"*", "0", "1",  "2",  "3",  "4",  "5",  "6", "7",
1220                      "8", "9", "10", "11", "12", "13", "14", "15"};
1221   for (const std::string prec : precisions) {
1222     const std::string fmt = "%E" + prec + "f";
1223     SCOPED_TRACE(fmt);
1224     time_point<chrono::nanoseconds> tp = unix_epoch - chrono::seconds(1);
1225     EXPECT_TRUE(parse(fmt, "", tz, &tp));
1226     EXPECT_EQ(unix_epoch, tp);
1227     tp = unix_epoch;
1228     EXPECT_TRUE(parse(fmt, "6", tz, &tp));
1229     EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp);
1230     tp = unix_epoch;
1231     EXPECT_TRUE(parse(fmt, "60", tz, &tp));
1232     EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp);
1233     tp = unix_epoch;
1234     EXPECT_TRUE(parse(fmt, "600", tz, &tp));
1235     EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp);
1236     tp = unix_epoch;
1237     EXPECT_TRUE(parse(fmt, "67", tz, &tp));
1238     EXPECT_EQ(unix_epoch + chrono::milliseconds(670), tp);
1239     tp = unix_epoch;
1240     EXPECT_TRUE(parse(fmt, "670", tz, &tp));
1241     EXPECT_EQ(unix_epoch + chrono::milliseconds(670), tp);
1242     tp = unix_epoch;
1243     EXPECT_TRUE(parse(fmt, "678", tz, &tp));
1244     EXPECT_EQ(unix_epoch + chrono::milliseconds(678), tp);
1245     tp = unix_epoch;
1246     EXPECT_TRUE(parse(fmt, "6789", tz, &tp));
1247     EXPECT_EQ(
1248         unix_epoch + chrono::milliseconds(678) + chrono::microseconds(900), tp);
1249   }
1250 
1251   // Here is a "%E*f" case we got wrong for a while.  The fractional
1252   // part of the first instant is less than 2^31 and was correctly
1253   // parsed, while the second (and any subsecond field >=2^31) failed.
1254   time_point<chrono::nanoseconds> tp = unix_epoch;
1255   EXPECT_TRUE(parse("%E*f", "2147483647", tz, &tp));
1256   EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
1257   tp = unix_epoch;
1258   EXPECT_TRUE(parse("%E*f", "2147483648", tz, &tp));
1259   EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
1260 
1261   // We should also be able to specify long strings of digits far
1262   // beyond the current resolution and have them convert the same way.
1263   tp = unix_epoch;
1264   EXPECT_TRUE(parse(
1265       "%E*f", "214748364801234567890123456789012345678901234567890123456789",
1266       tz, &tp));
1267   EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp);
1268 }
1269 
TEST(Parse,ExtendedSubecondsScan)1270 TEST(Parse, ExtendedSubecondsScan) {
1271   time_point<chrono::nanoseconds> tp;
1272   const time_zone tz = utc_time_zone();
1273   for (int ms = 0; ms < 1000; ms += 111) {
1274     for (int us = 0; us < 1000; us += 27) {
1275       const int micros = ms * 1000 + us;
1276       for (int ns = 0; ns < 1000; ns += 9) {
1277         std::ostringstream oss;
1278         oss << std::setfill('0') << std::setw(3) << ms;
1279         oss << std::setw(3) << us << std::setw(3) << ns;
1280         const std::string nanos = oss.str();
1281         const auto expected = chrono::system_clock::from_time_t(0) +
1282                               chrono::nanoseconds(micros * 1000 + ns);
1283         for (int ps = 0; ps < 1000; ps += 250) {
1284           std::ostringstream ps_oss;
1285           oss << std::setfill('0') << std::setw(3) << ps;
1286           const std::string input = nanos + ps_oss.str() + "999";
1287           EXPECT_TRUE(parse("%E*f", input, tz, &tp));
1288           EXPECT_EQ(expected + chrono::nanoseconds(ps) / 1000, tp) << input;
1289         }
1290       }
1291     }
1292   }
1293 }
1294 
TEST(Parse,ExtendedOffset)1295 TEST(Parse, ExtendedOffset) {
1296   const time_zone utc = utc_time_zone();
1297   time_point<absl::time_internal::cctz::seconds> tp;
1298 
1299   EXPECT_TRUE(parse("%Ez", "+00:00", utc, &tp));
1300   EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
1301   EXPECT_TRUE(parse("%Ez", "-12:34", utc, &tp));
1302   EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
1303   EXPECT_TRUE(parse("%Ez", "+12:34", utc, &tp));
1304   EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
1305   EXPECT_FALSE(parse("%Ez", "-12:3", utc, &tp));
1306 
1307   for (auto fmt : {"%Ez", "%z"}) {
1308     EXPECT_TRUE(parse(fmt, "+0000", utc, &tp));
1309     EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
1310     EXPECT_TRUE(parse(fmt, "-1234", utc, &tp));
1311     EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
1312     EXPECT_TRUE(parse(fmt, "+1234", utc, &tp));
1313     EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
1314     EXPECT_FALSE(parse(fmt, "-123", utc, &tp));
1315 
1316     EXPECT_TRUE(parse(fmt, "+00", utc, &tp));
1317     EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
1318     EXPECT_TRUE(parse(fmt, "-12", utc, &tp));
1319     EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
1320     EXPECT_TRUE(parse(fmt, "+12", utc, &tp));
1321     EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
1322     EXPECT_FALSE(parse(fmt, "-1", utc, &tp));
1323   }
1324 }
1325 
TEST(Parse,ExtendedSecondOffset)1326 TEST(Parse, ExtendedSecondOffset) {
1327   const time_zone utc = utc_time_zone();
1328   time_point<absl::time_internal::cctz::seconds> tp;
1329 
1330   for (auto fmt : {"%Ez", "%E*z", "%:z", "%::z", "%:::z"}) {
1331     EXPECT_TRUE(parse(fmt, "+00:00:00", utc, &tp));
1332     EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
1333     EXPECT_TRUE(parse(fmt, "-12:34:56", utc, &tp));
1334     EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
1335     EXPECT_TRUE(parse(fmt, "+12:34:56", utc, &tp));
1336     EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
1337     EXPECT_FALSE(parse(fmt, "-12:34:5", utc, &tp));
1338 
1339     EXPECT_TRUE(parse(fmt, "+000000", utc, &tp));
1340     EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
1341     EXPECT_TRUE(parse(fmt, "-123456", utc, &tp));
1342     EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
1343     EXPECT_TRUE(parse(fmt, "+123456", utc, &tp));
1344     EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
1345     EXPECT_FALSE(parse(fmt, "-12345", utc, &tp));
1346 
1347     EXPECT_TRUE(parse(fmt, "+00:00", utc, &tp));
1348     EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
1349     EXPECT_TRUE(parse(fmt, "-12:34", utc, &tp));
1350     EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
1351     EXPECT_TRUE(parse(fmt, "+12:34", utc, &tp));
1352     EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
1353     EXPECT_FALSE(parse(fmt, "-12:3", utc, &tp));
1354 
1355     EXPECT_TRUE(parse(fmt, "+0000", utc, &tp));
1356     EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
1357     EXPECT_TRUE(parse(fmt, "-1234", utc, &tp));
1358     EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
1359     EXPECT_TRUE(parse(fmt, "+1234", utc, &tp));
1360     EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
1361     EXPECT_FALSE(parse(fmt, "-123", utc, &tp));
1362 
1363     EXPECT_TRUE(parse(fmt, "+00", utc, &tp));
1364     EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
1365     EXPECT_TRUE(parse(fmt, "-12", utc, &tp));
1366     EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
1367     EXPECT_TRUE(parse(fmt, "+12", utc, &tp));
1368     EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
1369     EXPECT_FALSE(parse(fmt, "-1", utc, &tp));
1370   }
1371 }
1372 
TEST(Parse,ExtendedYears)1373 TEST(Parse, ExtendedYears) {
1374   const time_zone utc = utc_time_zone();
1375   const char e4y_fmt[] = "%E4Y%m%d";  // no separators
1376   time_point<absl::time_internal::cctz::seconds> tp;
1377 
1378   // %E4Y consumes exactly four chars, including any sign.
1379   EXPECT_TRUE(parse(e4y_fmt, "-9991127", utc, &tp));
1380   EXPECT_EQ(convert(civil_second(-999, 11, 27, 0, 0, 0), utc), tp);
1381   EXPECT_TRUE(parse(e4y_fmt, "-0991127", utc, &tp));
1382   EXPECT_EQ(convert(civil_second(-99, 11, 27, 0, 0, 0), utc), tp);
1383   EXPECT_TRUE(parse(e4y_fmt, "-0091127", utc, &tp));
1384   EXPECT_EQ(convert(civil_second(-9, 11, 27, 0, 0, 0), utc), tp);
1385   EXPECT_TRUE(parse(e4y_fmt, "-0011127", utc, &tp));
1386   EXPECT_EQ(convert(civil_second(-1, 11, 27, 0, 0, 0), utc), tp);
1387   EXPECT_TRUE(parse(e4y_fmt, "00001127", utc, &tp));
1388   EXPECT_EQ(convert(civil_second(0, 11, 27, 0, 0, 0), utc), tp);
1389   EXPECT_TRUE(parse(e4y_fmt, "00011127", utc, &tp));
1390   EXPECT_EQ(convert(civil_second(1, 11, 27, 0, 0, 0), utc), tp);
1391   EXPECT_TRUE(parse(e4y_fmt, "00091127", utc, &tp));
1392   EXPECT_EQ(convert(civil_second(9, 11, 27, 0, 0, 0), utc), tp);
1393   EXPECT_TRUE(parse(e4y_fmt, "00991127", utc, &tp));
1394   EXPECT_EQ(convert(civil_second(99, 11, 27, 0, 0, 0), utc), tp);
1395   EXPECT_TRUE(parse(e4y_fmt, "09991127", utc, &tp));
1396   EXPECT_EQ(convert(civil_second(999, 11, 27, 0, 0, 0), utc), tp);
1397   EXPECT_TRUE(parse(e4y_fmt, "99991127", utc, &tp));
1398   EXPECT_EQ(convert(civil_second(9999, 11, 27, 0, 0, 0), utc), tp);
1399 
1400   // When the year is outside [-999:9999], the parse fails.
1401   EXPECT_FALSE(parse(e4y_fmt, "-10001127", utc, &tp));
1402   EXPECT_FALSE(parse(e4y_fmt, "100001127", utc, &tp));
1403 }
1404 
TEST(Parse,RFC3339Format)1405 TEST(Parse, RFC3339Format) {
1406   const time_zone tz = utc_time_zone();
1407   time_point<chrono::nanoseconds> tp;
1408   EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00+00:00", tz, &tp));
1409   ExpectTime(tp, tz, 2014, 2, 12, 20, 21, 0, 0, false, "UTC");
1410 
1411   // Check that %ET also accepts "t".
1412   time_point<chrono::nanoseconds> tp2;
1413   EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12t20:21:00+00:00", tz, &tp2));
1414   EXPECT_EQ(tp, tp2);
1415 
1416   // Check that %Ez also accepts "Z" as a synonym for "+00:00".
1417   time_point<chrono::nanoseconds> tp3;
1418   EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00Z", tz, &tp3));
1419   EXPECT_EQ(tp, tp3);
1420 
1421   // Check that %Ez also accepts "z" as a synonym for "+00:00".
1422   time_point<chrono::nanoseconds> tp4;
1423   EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00z", tz, &tp4));
1424   EXPECT_EQ(tp, tp4);
1425 }
1426 
TEST(Parse,Week)1427 TEST(Parse, Week) {
1428   const time_zone utc = utc_time_zone();
1429   time_point<absl::time_internal::cctz::seconds> tp;
1430 
1431   auto exp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc);
1432   EXPECT_TRUE(parse("%Y-%U-%u", "2017-01-7", utc, &tp));
1433   EXPECT_EQ(exp, tp);
1434   EXPECT_TRUE(parse("%Y-%W-%w", "2017-00-0", utc, &tp));
1435   EXPECT_EQ(exp, tp);
1436 
1437   exp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc);
1438   EXPECT_TRUE(parse("%Y-%U-%u", "2017-53-7", utc, &tp));
1439   EXPECT_EQ(exp, tp);
1440   EXPECT_TRUE(parse("%Y-%W-%w", "2017-52-0", utc, &tp));
1441   EXPECT_EQ(exp, tp);
1442 
1443   exp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc);
1444   EXPECT_TRUE(parse("%Y-%U-%u", "2018-00-1", utc, &tp));
1445   EXPECT_EQ(exp, tp);
1446   EXPECT_TRUE(parse("%Y-%W-%w", "2018-01-1", utc, &tp));
1447   EXPECT_EQ(exp, tp);
1448 
1449   exp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc);
1450   EXPECT_TRUE(parse("%Y-%U-%u", "2018-52-1", utc, &tp));
1451   EXPECT_EQ(exp, tp);
1452   EXPECT_TRUE(parse("%Y-%W-%w", "2018-53-1", utc, &tp));
1453   EXPECT_EQ(exp, tp);
1454 
1455   exp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc);
1456   EXPECT_TRUE(parse("%Y-%U-%u", "2019-00-2", utc, &tp));
1457   EXPECT_EQ(exp, tp);
1458   EXPECT_TRUE(parse("%Y-%W-%w", "2019-00-2", utc, &tp));
1459   EXPECT_EQ(exp, tp);
1460 
1461   exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc);
1462   EXPECT_TRUE(parse("%Y-%U-%u", "2019-52-2", utc, &tp));
1463   EXPECT_EQ(exp, tp);
1464   EXPECT_TRUE(parse("%Y-%W-%w", "2019-52-2", utc, &tp));
1465   EXPECT_EQ(exp, tp);
1466 }
1467 
TEST(Parse,WeekYearShift)1468 TEST(Parse, WeekYearShift) {
1469   // %U/%W conversions with week values in {0, 52, 53} can slip
1470   // into the previous/following calendar years.
1471   const time_zone utc = utc_time_zone();
1472   time_point<absl::time_internal::cctz::seconds> tp;
1473 
1474   auto exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc);
1475   EXPECT_TRUE(parse("%Y-%U-%u", "2020-00-2", utc, &tp));
1476   EXPECT_EQ(exp, tp);
1477   EXPECT_TRUE(parse("%Y-%W-%w", "2020-00-2", utc, &tp));
1478   EXPECT_EQ(exp, tp);
1479 
1480   exp = convert(civil_second(2021, 1, 1, 0, 0, 0), utc);
1481   EXPECT_TRUE(parse("%Y-%U-%u", "2020-52-5", utc, &tp));
1482   EXPECT_EQ(exp, tp);
1483   EXPECT_TRUE(parse("%Y-%W-%w", "2020-52-5", utc, &tp));
1484   EXPECT_EQ(exp, tp);
1485 
1486   // Slipping into the previous/following calendar years should fail when
1487   // we're already at the extremes.
1488   EXPECT_FALSE(parse("%Y-%U-%u", "-9223372036854775808-0-7", utc, &tp));
1489   EXPECT_FALSE(parse("%Y-%U-%u", "9223372036854775807-53-7", utc, &tp));
1490 }
1491 
TEST(Parse,MaxRange)1492 TEST(Parse, MaxRange) {
1493   const time_zone utc = utc_time_zone();
1494   time_point<absl::time_internal::cctz::seconds> tp;
1495 
1496   // tests the upper limit using +00:00 offset
1497   EXPECT_TRUE(
1498       parse(RFC3339_sec, "292277026596-12-04T15:30:07+00:00", utc, &tp));
1499   EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::max());
1500   EXPECT_FALSE(
1501       parse(RFC3339_sec, "292277026596-12-04T15:30:08+00:00", utc, &tp));
1502 
1503   // tests the upper limit using -01:00 offset
1504   EXPECT_TRUE(
1505       parse(RFC3339_sec, "292277026596-12-04T14:30:07-01:00", utc, &tp));
1506   EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::max());
1507   EXPECT_FALSE(
1508       parse(RFC3339_sec, "292277026596-12-04T14:30:08-01:00", utc, &tp));
1509 
1510   // tests the lower limit using +00:00 offset
1511   EXPECT_TRUE(
1512       parse(RFC3339_sec, "-292277022657-01-27T08:29:52+00:00", utc, &tp));
1513   EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::min());
1514   EXPECT_FALSE(
1515       parse(RFC3339_sec, "-292277022657-01-27T08:29:51+00:00", utc, &tp));
1516 
1517   // tests the lower limit using +01:00 offset
1518   EXPECT_TRUE(
1519       parse(RFC3339_sec, "-292277022657-01-27T09:29:52+01:00", utc, &tp));
1520   EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::min());
1521   EXPECT_FALSE(
1522       parse(RFC3339_sec, "-292277022657-01-27T08:29:51+01:00", utc, &tp));
1523 
1524   // tests max/min civil-second overflow
1525   EXPECT_FALSE(
1526       parse(RFC3339_sec, "9223372036854775807-12-31T23:59:59-00:01", utc, &tp));
1527   EXPECT_FALSE(parse(RFC3339_sec, "-9223372036854775808-01-01T00:00:00+00:01",
1528                      utc, &tp));
1529 }
1530 
TEST(Parse,TimePointOverflow)1531 TEST(Parse, TimePointOverflow) {
1532   const time_zone utc = utc_time_zone();
1533 
1534   using D = chrono::duration<std::int64_t, std::nano>;
1535   time_point<D> tp;
1536 
1537   EXPECT_TRUE(
1538       parse(RFC3339_full, "2262-04-11T23:47:16.8547758079+00:00", utc, &tp));
1539   EXPECT_EQ(tp, time_point<D>::max());
1540   EXPECT_EQ("2262-04-11T23:47:16.854775807+00:00",
1541             format(RFC3339_full, tp, utc));
1542 #if 0
1543   // TODO(#199): Will fail until cctz::parse() properly detects overflow.
1544   EXPECT_FALSE(
1545       parse(RFC3339_full, "2262-04-11T23:47:16.8547758080+00:00", utc, &tp));
1546   EXPECT_TRUE(
1547       parse(RFC3339_full, "1677-09-21T00:12:43.1452241920+00:00", utc, &tp));
1548   EXPECT_EQ(tp, time_point<D>::min());
1549   EXPECT_EQ("1677-09-21T00:12:43.145224192+00:00",
1550             format(RFC3339_full, tp, utc));
1551   EXPECT_FALSE(
1552       parse(RFC3339_full, "1677-09-21T00:12:43.1452241919+00:00", utc, &tp));
1553 #endif
1554 
1555   using DS = chrono::duration<std::int8_t, chrono::seconds::period>;
1556   time_point<DS> stp;
1557 
1558   EXPECT_TRUE(parse(RFC3339_full, "1970-01-01T00:02:07.9+00:00", utc, &stp));
1559   EXPECT_EQ(stp, time_point<DS>::max());
1560   EXPECT_EQ("1970-01-01T00:02:07+00:00", format(RFC3339_full, stp, utc));
1561   EXPECT_FALSE(parse(RFC3339_full, "1970-01-01T00:02:08+00:00", utc, &stp));
1562 
1563   EXPECT_TRUE(parse(RFC3339_full, "1969-12-31T23:57:52+00:00", utc, &stp));
1564   EXPECT_EQ(stp, time_point<DS>::min());
1565   EXPECT_EQ("1969-12-31T23:57:52+00:00", format(RFC3339_full, stp, utc));
1566   EXPECT_FALSE(parse(RFC3339_full, "1969-12-31T23:57:51.9+00:00", utc, &stp));
1567 
1568   using DM = chrono::duration<std::int8_t, chrono::minutes::period>;
1569   time_point<DM> mtp;
1570 
1571   EXPECT_TRUE(parse(RFC3339_full, "1970-01-01T02:07:59+00:00", utc, &mtp));
1572   EXPECT_EQ(mtp, time_point<DM>::max());
1573   EXPECT_EQ("1970-01-01T02:07:00+00:00", format(RFC3339_full, mtp, utc));
1574   EXPECT_FALSE(parse(RFC3339_full, "1970-01-01T02:08:00+00:00", utc, &mtp));
1575 
1576   EXPECT_TRUE(parse(RFC3339_full, "1969-12-31T21:52:00+00:00", utc, &mtp));
1577   EXPECT_EQ(mtp, time_point<DM>::min());
1578   EXPECT_EQ("1969-12-31T21:52:00+00:00", format(RFC3339_full, mtp, utc));
1579   EXPECT_FALSE(parse(RFC3339_full, "1969-12-31T21:51:59+00:00", utc, &mtp));
1580 }
1581 
TEST(Parse,TimePointOverflowFloor)1582 TEST(Parse, TimePointOverflowFloor) {
1583   const time_zone utc = utc_time_zone();
1584 
1585   using D = chrono::duration<std::int64_t, std::micro>;
1586   time_point<D> tp;
1587 
1588   EXPECT_TRUE(
1589       parse(RFC3339_full, "294247-01-10T04:00:54.7758079+00:00", utc, &tp));
1590   EXPECT_EQ(tp, time_point<D>::max());
1591   EXPECT_EQ("294247-01-10T04:00:54.775807+00:00",
1592             format(RFC3339_full, tp, utc));
1593 #if 0
1594   // TODO(#199): Will fail until cctz::parse() properly detects overflow.
1595   EXPECT_FALSE(
1596       parse(RFC3339_full, "294247-01-10T04:00:54.7758080+00:00", utc, &tp));
1597   EXPECT_TRUE(
1598       parse(RFC3339_full, "-290308-12-21T19:59:05.2241920+00:00", utc, &tp));
1599   EXPECT_EQ(tp, time_point<D>::min());
1600   EXPECT_EQ("-290308-12-21T19:59:05.224192+00:00",
1601             format(RFC3339_full, tp, utc));
1602   EXPECT_FALSE(
1603       parse(RFC3339_full, "-290308-12-21T19:59:05.2241919+00:00", utc, &tp));
1604 #endif
1605 }
1606 
1607 //
1608 // Roundtrip test for format()/parse().
1609 //
1610 
TEST(FormatParse,RoundTrip)1611 TEST(FormatParse, RoundTrip) {
1612   time_zone lax;
1613   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &lax));
1614   const auto in = convert(civil_second(1977, 6, 28, 9, 8, 7), lax);
1615   const auto subseconds = chrono::nanoseconds(654321);
1616 
1617   // RFC3339, which renders subseconds.
1618   {
1619     time_point<chrono::nanoseconds> out;
1620     const std::string s = format(RFC3339_full, in + subseconds, lax);
1621     EXPECT_TRUE(parse(RFC3339_full, s, lax, &out)) << s;
1622     EXPECT_EQ(in + subseconds, out);  // RFC3339_full includes %Ez
1623   }
1624 
1625   // RFC1123, which only does whole seconds.
1626   {
1627     time_point<chrono::nanoseconds> out;
1628     const std::string s = format(RFC1123_full, in, lax);
1629     EXPECT_TRUE(parse(RFC1123_full, s, lax, &out)) << s;
1630     EXPECT_EQ(in, out);  // RFC1123_full includes %z
1631   }
1632 
1633 #if defined(_WIN32) || defined(_WIN64)
1634   // Initial investigations indicate the %c does not roundtrip on Windows.
1635   // TODO: Figure out what is going on here (perhaps a locale problem).
1636 #elif defined(__EMSCRIPTEN__)
1637   // strftime() and strptime() use different defintions for "%c" under
1638   // emscripten (see https://github.com/kripken/emscripten/pull/7491),
1639   // causing its round-trip test to fail.
1640 #else
1641   // Even though we don't know what %c will produce, it should roundtrip,
1642   // but only in the 0-offset timezone.
1643   {
1644     time_point<chrono::nanoseconds> out;
1645     time_zone utc = utc_time_zone();
1646     const std::string s = format("%c", in, utc);
1647     EXPECT_TRUE(parse("%c", s, utc, &out)) << s;
1648     EXPECT_EQ(in, out);
1649   }
1650 #endif
1651 }
1652 
TEST(FormatParse,RoundTripDistantFuture)1653 TEST(FormatParse, RoundTripDistantFuture) {
1654   const time_zone utc = utc_time_zone();
1655   const time_point<absl::time_internal::cctz::seconds> in =
1656       time_point<absl::time_internal::cctz::seconds>::max();
1657   const std::string s = format(RFC3339_full, in, utc);
1658   time_point<absl::time_internal::cctz::seconds> out;
1659   EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;
1660   EXPECT_EQ(in, out);
1661 }
1662 
TEST(FormatParse,RoundTripDistantPast)1663 TEST(FormatParse, RoundTripDistantPast) {
1664   const time_zone utc = utc_time_zone();
1665   const time_point<absl::time_internal::cctz::seconds> in =
1666       time_point<absl::time_internal::cctz::seconds>::min();
1667   const std::string s = format(RFC3339_full, in, utc);
1668   time_point<absl::time_internal::cctz::seconds> out;
1669   EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;
1670   EXPECT_EQ(in, out);
1671 }
1672 
1673 }  // namespace cctz
1674 }  // namespace time_internal
1675 ABSL_NAMESPACE_END
1676 }  // namespace absl
1677