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