1 // Copyright 2016 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //   http://www.apache.org/licenses/LICENSE-2.0
8 //
9 //   Unless required by applicable law or agreed to in writing, software
10 //   distributed under the License is distributed on an "AS IS" BASIS,
11 //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 //   See the License for the specific language governing permissions and
13 //   limitations under the License.
14 
15 #if !defined(HAS_STRPTIME)
16 # if !defined(_MSC_VER)
17 #  define HAS_STRPTIME 1  // assume everyone has strptime() except windows
18 # endif
19 #endif
20 
21 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
22 
23 #include <cctype>
24 #include <chrono>
25 #include <cstddef>
26 #include <cstdint>
27 #include <cstring>
28 #include <ctime>
29 #include <limits>
30 #include <string>
31 #include <vector>
32 #if !HAS_STRPTIME
33 #include <iomanip>
34 #include <sstream>
35 #endif
36 
37 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
38 #include "time_zone_if.h"
39 
40 namespace absl {
41 namespace time_internal {
42 namespace cctz {
43 namespace detail {
44 
45 namespace {
46 
47 #if !HAS_STRPTIME
48 // Build a strptime() using C++11's std::get_time().
strptime(const char * s,const char * fmt,std::tm * tm)49 char* strptime(const char* s, const char* fmt, std::tm* tm) {
50   std::istringstream input(s);
51   input >> std::get_time(tm, fmt);
52   if (input.fail()) return nullptr;
53   return const_cast<char*>(s) +
54          (input.eof() ? strlen(s) : static_cast<std::size_t>(input.tellg()));
55 }
56 #endif
57 
ToTM(const time_zone::absolute_lookup & al)58 std::tm ToTM(const time_zone::absolute_lookup& al) {
59   std::tm tm{};
60   tm.tm_sec = al.cs.second();
61   tm.tm_min = al.cs.minute();
62   tm.tm_hour = al.cs.hour();
63   tm.tm_mday = al.cs.day();
64   tm.tm_mon = al.cs.month() - 1;
65 
66   // Saturate tm.tm_year is cases of over/underflow.
67   if (al.cs.year() < std::numeric_limits<int>::min() + 1900) {
68     tm.tm_year = std::numeric_limits<int>::min();
69   } else if (al.cs.year() - 1900 > std::numeric_limits<int>::max()) {
70     tm.tm_year = std::numeric_limits<int>::max();
71   } else {
72     tm.tm_year = static_cast<int>(al.cs.year() - 1900);
73   }
74 
75   switch (get_weekday(civil_day(al.cs))) {
76     case weekday::sunday:
77       tm.tm_wday = 0;
78       break;
79     case weekday::monday:
80       tm.tm_wday = 1;
81       break;
82     case weekday::tuesday:
83       tm.tm_wday = 2;
84       break;
85     case weekday::wednesday:
86       tm.tm_wday = 3;
87       break;
88     case weekday::thursday:
89       tm.tm_wday = 4;
90       break;
91     case weekday::friday:
92       tm.tm_wday = 5;
93       break;
94     case weekday::saturday:
95       tm.tm_wday = 6;
96       break;
97   }
98   tm.tm_yday = get_yearday(civil_day(al.cs)) - 1;
99   tm.tm_isdst = al.is_dst ? 1 : 0;
100   return tm;
101 }
102 
103 const char kDigits[] = "0123456789";
104 
105 // Formats a 64-bit integer in the given field width.  Note that it is up
106 // to the caller of Format64() [and Format02d()/FormatOffset()] to ensure
107 // that there is sufficient space before ep to hold the conversion.
Format64(char * ep,int width,std::int_fast64_t v)108 char* Format64(char* ep, int width, std::int_fast64_t v) {
109   bool neg = false;
110   if (v < 0) {
111     --width;
112     neg = true;
113     if (v == std::numeric_limits<std::int_fast64_t>::min()) {
114       // Avoid negating minimum value.
115       std::int_fast64_t last_digit = -(v % 10);
116       v /= 10;
117       if (last_digit < 0) {
118         ++v;
119         last_digit += 10;
120       }
121       --width;
122       *--ep = kDigits[last_digit];
123     }
124     v = -v;
125   }
126   do {
127     --width;
128     *--ep = kDigits[v % 10];
129   } while (v /= 10);
130   while (--width >= 0) *--ep = '0';  // zero pad
131   if (neg) *--ep = '-';
132   return ep;
133 }
134 
135 // Formats [0 .. 99] as %02d.
Format02d(char * ep,int v)136 char* Format02d(char* ep, int v) {
137   *--ep = kDigits[v % 10];
138   *--ep = kDigits[(v / 10) % 10];
139   return ep;
140 }
141 
142 // Formats a UTC offset, like +00:00.
FormatOffset(char * ep,int offset,const char * mode)143 char* FormatOffset(char* ep, int offset, const char* mode) {
144   // TODO: Follow the RFC3339 "Unknown Local Offset Convention" and
145   // generate a "negative zero" when we're formatting a zero offset
146   // as the result of a failed load_time_zone().
147   char sign = '+';
148   if (offset < 0) {
149     offset = -offset;  // bounded by 24h so no overflow
150     sign = '-';
151   }
152   char sep = mode[0];
153   if (sep != '\0' && mode[1] == '*') {
154     ep = Format02d(ep, offset % 60);
155     *--ep = sep;
156   }
157   int minutes = offset / 60;
158   ep = Format02d(ep, minutes % 60);
159   if (sep != '\0') *--ep = sep;
160   ep = Format02d(ep, minutes / 60);
161   *--ep = sign;
162   return ep;
163 }
164 
165 // Formats a std::tm using strftime(3).
FormatTM(std::string * out,const std::string & fmt,const std::tm & tm)166 void FormatTM(std::string* out, const std::string& fmt, const std::tm& tm) {
167   // strftime(3) returns the number of characters placed in the output
168   // array (which may be 0 characters).  It also returns 0 to indicate
169   // an error, like the array wasn't large enough.  To accommodate this,
170   // the following code grows the buffer size from 2x the format std::string
171   // length up to 32x.
172   for (std::size_t i = 2; i != 32; i *= 2) {
173     std::size_t buf_size = fmt.size() * i;
174     std::vector<char> buf(buf_size);
175     if (std::size_t len = strftime(&buf[0], buf_size, fmt.c_str(), &tm)) {
176       out->append(&buf[0], len);
177       return;
178     }
179   }
180 }
181 
182 // Used for %E#S/%E#f specifiers and for data values in parse().
183 template <typename T>
ParseInt(const char * dp,int width,T min,T max,T * vp)184 const char* ParseInt(const char* dp, int width, T min, T max, T* vp) {
185   if (dp != nullptr) {
186     const T kmin = std::numeric_limits<T>::min();
187     bool erange = false;
188     bool neg = false;
189     T value = 0;
190     if (*dp == '-') {
191       neg = true;
192       if (width <= 0 || --width != 0) {
193         ++dp;
194       } else {
195         dp = nullptr;  // width was 1
196       }
197     }
198     if (const char* const bp = dp) {
199       while (const char* cp = strchr(kDigits, *dp)) {
200         int d = static_cast<int>(cp - kDigits);
201         if (d >= 10) break;
202         if (value < kmin / 10) {
203           erange = true;
204           break;
205         }
206         value *= 10;
207         if (value < kmin + d) {
208           erange = true;
209           break;
210         }
211         value -= d;
212         dp += 1;
213         if (width > 0 && --width == 0) break;
214       }
215       if (dp != bp && !erange && (neg || value != kmin)) {
216         if (!neg || value != 0) {
217           if (!neg) value = -value;  // make positive
218           if (min <= value && value <= max) {
219             *vp = value;
220           } else {
221             dp = nullptr;
222           }
223         } else {
224           dp = nullptr;
225         }
226       } else {
227         dp = nullptr;
228       }
229     }
230   }
231   return dp;
232 }
233 
234 // The number of base-10 digits that can be represented by a signed 64-bit
235 // integer.  That is, 10^kDigits10_64 <= 2^63 - 1 < 10^(kDigits10_64 + 1).
236 const int kDigits10_64 = 18;
237 
238 // 10^n for everything that can be represented by a signed 64-bit integer.
239 const std::int_fast64_t kExp10[kDigits10_64 + 1] = {
240     1,
241     10,
242     100,
243     1000,
244     10000,
245     100000,
246     1000000,
247     10000000,
248     100000000,
249     1000000000,
250     10000000000,
251     100000000000,
252     1000000000000,
253     10000000000000,
254     100000000000000,
255     1000000000000000,
256     10000000000000000,
257     100000000000000000,
258     1000000000000000000,
259 };
260 
261 }  // namespace
262 
263 // Uses strftime(3) to format the given Time.  The following extended format
264 // specifiers are also supported:
265 //
266 //   - %Ez  - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm)
267 //   - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss)
268 //   - %E#S - Seconds with # digits of fractional precision
269 //   - %E*S - Seconds with full fractional precision (a literal '*')
270 //   - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
271 //
272 // The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are
273 // handled internally for performance reasons.  strftime(3) is slow due to
274 // a POSIX requirement to respect changes to ${TZ}.
275 //
276 // The TZ/GNU %s extension is handled internally because strftime() has
277 // to use mktime() to generate it, and that assumes the local time zone.
278 //
279 // We also handle the %z and %Z specifiers to accommodate platforms that do
280 // not support the tm_gmtoff and tm_zone extensions to std::tm.
281 //
282 // Requires that zero() <= fs < seconds(1).
format(const std::string & format,const time_point<seconds> & tp,const detail::femtoseconds & fs,const time_zone & tz)283 std::string format(const std::string& format, const time_point<seconds>& tp,
284                    const detail::femtoseconds& fs, const time_zone& tz) {
285   std::string result;
286   result.reserve(format.size());  // A reasonable guess for the result size.
287   const time_zone::absolute_lookup al = tz.lookup(tp);
288   const std::tm tm = ToTM(al);
289 
290   // Scratch buffer for internal conversions.
291   char buf[3 + kDigits10_64];  // enough for longest conversion
292   char* const ep = buf + sizeof(buf);
293   char* bp;  // works back from ep
294 
295   // Maintain three, disjoint subsequences that span format.
296   //   [format.begin() ... pending) : already formatted into result
297   //   [pending ... cur) : formatting pending, but no special cases
298   //   [cur ... format.end()) : unexamined
299   // Initially, everything is in the unexamined part.
300   const char* pending = format.c_str();  // NUL terminated
301   const char* cur = pending;
302   const char* end = pending + format.length();
303 
304   while (cur != end) {  // while something is unexamined
305     // Moves cur to the next percent sign.
306     const char* start = cur;
307     while (cur != end && *cur != '%') ++cur;
308 
309     // If the new pending text is all ordinary, copy it out.
310     if (cur != start && pending == start) {
311       result.append(pending, static_cast<std::size_t>(cur - pending));
312       pending = start = cur;
313     }
314 
315     // Span the sequential percent signs.
316     const char* percent = cur;
317     while (cur != end && *cur == '%') ++cur;
318 
319     // If the new pending text is all percents, copy out one
320     // percent for every matched pair, then skip those pairs.
321     if (cur != start && pending == start) {
322       std::size_t escaped = static_cast<std::size_t>(cur - pending) / 2;
323       result.append(pending, escaped);
324       pending += escaped * 2;
325       // Also copy out a single trailing percent.
326       if (pending != cur && cur == end) {
327         result.push_back(*pending++);
328       }
329     }
330 
331     // Loop unless we have an unescaped percent.
332     if (cur == end || (cur - percent) % 2 == 0) continue;
333 
334     // Simple specifiers that we handle ourselves.
335     if (strchr("YmdeHMSzZs%", *cur)) {
336       if (cur - 1 != pending) {
337         FormatTM(&result, std::string(pending, cur - 1), tm);
338       }
339       switch (*cur) {
340         case 'Y':
341           // This avoids the tm.tm_year overflow problem for %Y, however
342           // tm.tm_year will still be used by other specifiers like %D.
343           bp = Format64(ep, 0, al.cs.year());
344           result.append(bp, static_cast<std::size_t>(ep - bp));
345           break;
346         case 'm':
347           bp = Format02d(ep, al.cs.month());
348           result.append(bp, static_cast<std::size_t>(ep - bp));
349           break;
350         case 'd':
351         case 'e':
352           bp = Format02d(ep, al.cs.day());
353           if (*cur == 'e' && *bp == '0') *bp = ' ';  // for Windows
354           result.append(bp, static_cast<std::size_t>(ep - bp));
355           break;
356         case 'H':
357           bp = Format02d(ep, al.cs.hour());
358           result.append(bp, static_cast<std::size_t>(ep - bp));
359           break;
360         case 'M':
361           bp = Format02d(ep, al.cs.minute());
362           result.append(bp, static_cast<std::size_t>(ep - bp));
363           break;
364         case 'S':
365           bp = Format02d(ep, al.cs.second());
366           result.append(bp, static_cast<std::size_t>(ep - bp));
367           break;
368         case 'z':
369           bp = FormatOffset(ep, al.offset, "");
370           result.append(bp, static_cast<std::size_t>(ep - bp));
371           break;
372         case 'Z':
373           result.append(al.abbr);
374           break;
375         case 's':
376           bp = Format64(ep, 0, ToUnixSeconds(tp));
377           result.append(bp, static_cast<std::size_t>(ep - bp));
378           break;
379         case '%':
380           result.push_back('%');
381           break;
382       }
383       pending = ++cur;
384       continue;
385     }
386 
387     // Loop if there is no E modifier.
388     if (*cur != 'E' || ++cur == end) continue;
389 
390     // Format our extensions.
391     if (*cur == 'z') {
392       // Formats %Ez.
393       if (cur - 2 != pending) {
394         FormatTM(&result, std::string(pending, cur - 2), tm);
395       }
396       bp = FormatOffset(ep, al.offset, ":");
397       result.append(bp, static_cast<std::size_t>(ep - bp));
398       pending = ++cur;
399     } else if (*cur == '*' && cur + 1 != end && *(cur + 1) == 'z') {
400       // Formats %E*z.
401       if (cur - 2 != pending) {
402         FormatTM(&result, std::string(pending, cur - 2), tm);
403       }
404       bp = FormatOffset(ep, al.offset, ":*");
405       result.append(bp, static_cast<std::size_t>(ep - bp));
406       pending = cur += 2;
407     } else if (*cur == '*' && cur + 1 != end &&
408                (*(cur + 1) == 'S' || *(cur + 1) == 'f')) {
409       // Formats %E*S or %E*F.
410       if (cur - 2 != pending) {
411         FormatTM(&result, std::string(pending, cur - 2), tm);
412       }
413       char* cp = ep;
414       bp = Format64(cp, 15, fs.count());
415       while (cp != bp && cp[-1] == '0') --cp;
416       switch (*(cur + 1)) {
417         case 'S':
418           if (cp != bp) *--bp = '.';
419           bp = Format02d(bp, al.cs.second());
420           break;
421         case 'f':
422           if (cp == bp) *--bp = '0';
423           break;
424       }
425       result.append(bp, static_cast<std::size_t>(cp - bp));
426       pending = cur += 2;
427     } else if (*cur == '4' && cur + 1 != end && *(cur + 1) == 'Y') {
428       // Formats %E4Y.
429       if (cur - 2 != pending) {
430         FormatTM(&result, std::string(pending, cur - 2), tm);
431       }
432       bp = Format64(ep, 4, al.cs.year());
433       result.append(bp, static_cast<std::size_t>(ep - bp));
434       pending = cur += 2;
435     } else if (std::isdigit(*cur)) {
436       // Possibly found %E#S or %E#f.
437       int n = 0;
438       if (const char* np = ParseInt(cur, 0, 0, 1024, &n)) {
439         if (*np == 'S' || *np == 'f') {
440           // Formats %E#S or %E#f.
441           if (cur - 2 != pending) {
442             FormatTM(&result, std::string(pending, cur - 2), tm);
443           }
444           bp = ep;
445           if (n > 0) {
446             if (n > kDigits10_64) n = kDigits10_64;
447             bp = Format64(bp, n, (n > 15) ? fs.count() * kExp10[n - 15]
448                                           : fs.count() / kExp10[15 - n]);
449             if (*np == 'S') *--bp = '.';
450           }
451           if (*np == 'S') bp = Format02d(bp, al.cs.second());
452           result.append(bp, static_cast<std::size_t>(ep - bp));
453           pending = cur = ++np;
454         }
455       }
456     }
457   }
458 
459   // Formats any remaining data.
460   if (end != pending) {
461     FormatTM(&result, std::string(pending, end), tm);
462   }
463 
464   return result;
465 }
466 
467 namespace {
468 
ParseOffset(const char * dp,const char * mode,int * offset)469 const char* ParseOffset(const char* dp, const char* mode, int* offset) {
470   if (dp != nullptr) {
471     const char first = *dp++;
472     if (first == '+' || first == '-') {
473       char sep = mode[0];
474       int hours = 0;
475       int minutes = 0;
476       int seconds = 0;
477       const char* ap = ParseInt(dp, 2, 0, 23, &hours);
478       if (ap != nullptr && ap - dp == 2) {
479         dp = ap;
480         if (sep != '\0' && *ap == sep) ++ap;
481         const char* bp = ParseInt(ap, 2, 0, 59, &minutes);
482         if (bp != nullptr && bp - ap == 2) {
483           dp = bp;
484           if (sep != '\0' && *bp == sep) ++bp;
485           const char* cp = ParseInt(bp, 2, 0, 59, &seconds);
486           if (cp != nullptr && cp - bp == 2) dp = cp;
487         }
488         *offset = ((hours * 60 + minutes) * 60) + seconds;
489         if (first == '-') *offset = -*offset;
490       } else {
491         dp = nullptr;
492       }
493     } else if (first == 'Z') {  // Zulu
494       *offset = 0;
495     } else {
496       dp = nullptr;
497     }
498   }
499   return dp;
500 }
501 
ParseZone(const char * dp,std::string * zone)502 const char* ParseZone(const char* dp, std::string* zone) {
503   zone->clear();
504   if (dp != nullptr) {
505     while (*dp != '\0' && !std::isspace(*dp)) zone->push_back(*dp++);
506     if (zone->empty()) dp = nullptr;
507   }
508   return dp;
509 }
510 
ParseSubSeconds(const char * dp,detail::femtoseconds * subseconds)511 const char* ParseSubSeconds(const char* dp, detail::femtoseconds* subseconds) {
512   if (dp != nullptr) {
513     std::int_fast64_t v = 0;
514     std::int_fast64_t exp = 0;
515     const char* const bp = dp;
516     while (const char* cp = strchr(kDigits, *dp)) {
517       int d = static_cast<int>(cp - kDigits);
518       if (d >= 10) break;
519       if (exp < 15) {
520         exp += 1;
521         v *= 10;
522         v += d;
523       }
524       ++dp;
525     }
526     if (dp != bp) {
527       v *= kExp10[15 - exp];
528       *subseconds = detail::femtoseconds(v);
529     } else {
530       dp = nullptr;
531     }
532   }
533   return dp;
534 }
535 
536 // Parses a std::string into a std::tm using strptime(3).
ParseTM(const char * dp,const char * fmt,std::tm * tm)537 const char* ParseTM(const char* dp, const char* fmt, std::tm* tm) {
538   if (dp != nullptr) {
539     dp = strptime(dp, fmt, tm);
540   }
541   return dp;
542 }
543 
544 }  // namespace
545 
546 // Uses strptime(3) to parse the given input.  Supports the same extended
547 // format specifiers as format(), although %E#S and %E*S are treated
548 // identically (and similarly for %E#f and %E*f).  %Ez and %E*z also accept
549 // the same inputs.
550 //
551 // The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are
552 // handled internally so that we can normally avoid strptime() altogether
553 // (which is particularly helpful when the native implementation is broken).
554 //
555 // The TZ/GNU %s extension is handled internally because strptime() has to
556 // use localtime_r() to generate it, and that assumes the local time zone.
557 //
558 // We also handle the %z specifier to accommodate platforms that do not
559 // support the tm_gmtoff extension to std::tm.  %Z is parsed but ignored.
parse(const std::string & format,const std::string & input,const time_zone & tz,time_point<seconds> * sec,detail::femtoseconds * fs,std::string * err)560 bool parse(const std::string& format, const std::string& input,
561            const time_zone& tz, time_point<seconds>* sec,
562            detail::femtoseconds* fs, std::string* err) {
563   // The unparsed input.
564   const char* data = input.c_str();  // NUL terminated
565 
566   // Skips leading whitespace.
567   while (std::isspace(*data)) ++data;
568 
569   const year_t kyearmax = std::numeric_limits<year_t>::max();
570   const year_t kyearmin = std::numeric_limits<year_t>::min();
571 
572   // Sets default values for unspecified fields.
573   bool saw_year = false;
574   year_t year = 1970;
575   std::tm tm{};
576   tm.tm_year = 1970 - 1900;
577   tm.tm_mon = 1 - 1;  // Jan
578   tm.tm_mday = 1;
579   tm.tm_hour = 0;
580   tm.tm_min = 0;
581   tm.tm_sec = 0;
582   tm.tm_wday = 4;  // Thu
583   tm.tm_yday = 0;
584   tm.tm_isdst = 0;
585   auto subseconds = detail::femtoseconds::zero();
586   bool saw_offset = false;
587   int offset = 0;  // No offset from passed tz.
588   std::string zone = "UTC";
589 
590   const char* fmt = format.c_str();  // NUL terminated
591   bool twelve_hour = false;
592   bool afternoon = false;
593 
594   bool saw_percent_s = false;
595   std::int_fast64_t percent_s = 0;
596 
597   // Steps through format, one specifier at a time.
598   while (data != nullptr && *fmt != '\0') {
599     if (std::isspace(*fmt)) {
600       while (std::isspace(*data)) ++data;
601       while (std::isspace(*++fmt)) continue;
602       continue;
603     }
604 
605     if (*fmt != '%') {
606       if (*data == *fmt) {
607         ++data;
608         ++fmt;
609       } else {
610         data = nullptr;
611       }
612       continue;
613     }
614 
615     const char* percent = fmt;
616     if (*++fmt == '\0') {
617       data = nullptr;
618       continue;
619     }
620     switch (*fmt++) {
621       case 'Y':
622         // Symmetrically with FormatTime(), directly handing %Y avoids the
623         // tm.tm_year overflow problem.  However, tm.tm_year will still be
624         // used by other specifiers like %D.
625         data = ParseInt(data, 0, kyearmin, kyearmax, &year);
626         if (data != nullptr) saw_year = true;
627         continue;
628       case 'm':
629         data = ParseInt(data, 2, 1, 12, &tm.tm_mon);
630         if (data != nullptr) tm.tm_mon -= 1;
631         continue;
632       case 'd':
633       case 'e':
634         data = ParseInt(data, 2, 1, 31, &tm.tm_mday);
635         continue;
636       case 'H':
637         data = ParseInt(data, 2, 0, 23, &tm.tm_hour);
638         twelve_hour = false;
639         continue;
640       case 'M':
641         data = ParseInt(data, 2, 0, 59, &tm.tm_min);
642         continue;
643       case 'S':
644         data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
645         continue;
646       case 'I':
647       case 'l':
648       case 'r':  // probably uses %I
649         twelve_hour = true;
650         break;
651       case 'R':  // uses %H
652       case 'T':  // uses %H
653       case 'c':  // probably uses %H
654       case 'X':  // probably uses %H
655         twelve_hour = false;
656         break;
657       case 'z':
658         data = ParseOffset(data, "", &offset);
659         if (data != nullptr) saw_offset = true;
660         continue;
661       case 'Z':  // ignored; zone abbreviations are ambiguous
662         data = ParseZone(data, &zone);
663         continue;
664       case 's':
665         data = ParseInt(data, 0,
666                         std::numeric_limits<std::int_fast64_t>::min(),
667                         std::numeric_limits<std::int_fast64_t>::max(),
668                         &percent_s);
669         if (data != nullptr) saw_percent_s = true;
670         continue;
671       case '%':
672         data = (*data == '%' ? data + 1 : nullptr);
673         continue;
674       case 'E':
675         if (*fmt == 'z' || (*fmt == '*' && *(fmt + 1) == 'z')) {
676           data = ParseOffset(data, ":", &offset);
677           if (data != nullptr) saw_offset = true;
678           fmt += (*fmt == 'z') ? 1 : 2;
679           continue;
680         }
681         if (*fmt == '*' && *(fmt + 1) == 'S') {
682           data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
683           if (data != nullptr && *data == '.') {
684             data = ParseSubSeconds(data + 1, &subseconds);
685           }
686           fmt += 2;
687           continue;
688         }
689         if (*fmt == '*' && *(fmt + 1) == 'f') {
690           if (data != nullptr && std::isdigit(*data)) {
691             data = ParseSubSeconds(data, &subseconds);
692           }
693           fmt += 2;
694           continue;
695         }
696         if (*fmt == '4' && *(fmt + 1) == 'Y') {
697           const char* bp = data;
698           data = ParseInt(data, 4, year_t{-999}, year_t{9999}, &year);
699           if (data != nullptr) {
700             if (data - bp == 4) {
701               saw_year = true;
702             } else {
703               data = nullptr;  // stopped too soon
704             }
705           }
706           fmt += 2;
707           continue;
708         }
709         if (std::isdigit(*fmt)) {
710           int n = 0;  // value ignored
711           if (const char* np = ParseInt(fmt, 0, 0, 1024, &n)) {
712             if (*np == 'S') {
713               data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
714               if (data != nullptr && *data == '.') {
715                 data = ParseSubSeconds(data + 1, &subseconds);
716               }
717               fmt = ++np;
718               continue;
719             }
720             if (*np == 'f') {
721               if (data != nullptr && std::isdigit(*data)) {
722                 data = ParseSubSeconds(data, &subseconds);
723               }
724               fmt = ++np;
725               continue;
726             }
727           }
728         }
729         if (*fmt == 'c') twelve_hour = false;  // probably uses %H
730         if (*fmt == 'X') twelve_hour = false;  // probably uses %H
731         if (*fmt != '\0') ++fmt;
732         break;
733       case 'O':
734         if (*fmt == 'H') twelve_hour = false;
735         if (*fmt == 'I') twelve_hour = true;
736         if (*fmt != '\0') ++fmt;
737         break;
738     }
739 
740     // Parses the current specifier.
741     const char* orig_data = data;
742     std::string spec(percent, static_cast<std::size_t>(fmt - percent));
743     data = ParseTM(data, spec.c_str(), &tm);
744 
745     // If we successfully parsed %p we need to remember whether the result
746     // was AM or PM so that we can adjust tm_hour before ConvertDateTime().
747     // So reparse the input with a known AM hour, and check if it is shifted
748     // to a PM hour.
749     if (spec == "%p" && data != nullptr) {
750       std::string test_input = "1";
751       test_input.append(orig_data, static_cast<std::size_t>(data - orig_data));
752       const char* test_data = test_input.c_str();
753       std::tm tmp{};
754       ParseTM(test_data, "%I%p", &tmp);
755       afternoon = (tmp.tm_hour == 13);
756     }
757   }
758 
759   // Adjust a 12-hour tm_hour value if it should be in the afternoon.
760   if (twelve_hour && afternoon && tm.tm_hour < 12) {
761     tm.tm_hour += 12;
762   }
763 
764   if (data == nullptr) {
765     if (err != nullptr) *err = "Failed to parse input";
766     return false;
767   }
768 
769   // Skip any remaining whitespace.
770   while (std::isspace(*data)) ++data;
771 
772   // parse() must consume the entire input std::string.
773   if (*data != '\0') {
774     if (err != nullptr) *err = "Illegal trailing data in input string";
775     return false;
776   }
777 
778   // If we saw %s then we ignore anything else and return that time.
779   if (saw_percent_s) {
780     *sec = FromUnixSeconds(percent_s);
781     *fs = detail::femtoseconds::zero();
782     return true;
783   }
784 
785   // If we saw %z, %Ez, or %E*z then we want to interpret the parsed fields
786   // in UTC and then shift by that offset.  Otherwise we want to interpret
787   // the fields directly in the passed time_zone.
788   time_zone ptz = saw_offset ? utc_time_zone() : tz;
789 
790   // Allows a leap second of 60 to normalize forward to the following ":00".
791   if (tm.tm_sec == 60) {
792     tm.tm_sec -= 1;
793     offset -= 1;
794     subseconds = detail::femtoseconds::zero();
795   }
796 
797   if (!saw_year) {
798     year = year_t{tm.tm_year};
799     if (year > kyearmax - 1900) {
800       // Platform-dependent, maybe unreachable.
801       if (err != nullptr) *err = "Out-of-range year";
802       return false;
803     }
804     year += 1900;
805   }
806 
807   const int month = tm.tm_mon + 1;
808   civil_second cs(year, month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
809 
810   // parse() should not allow normalization. Due to the restricted field
811   // ranges above (see ParseInt()), the only possibility is for days to roll
812   // into months. That is, parsing "Sep 31" should not produce "Oct 1".
813   if (cs.month() != month || cs.day() != tm.tm_mday) {
814     if (err != nullptr) *err = "Out-of-range field";
815     return false;
816   }
817 
818   // Accounts for the offset adjustment before converting to absolute time.
819   if ((offset < 0 && cs > civil_second::max() + offset) ||
820       (offset > 0 && cs < civil_second::min() + offset)) {
821     if (err != nullptr) *err = "Out-of-range field";
822     return false;
823   }
824   cs -= offset;
825 
826   const auto tp = ptz.lookup(cs).pre;
827   // Checks for overflow/underflow and returns an error as necessary.
828   if (tp == time_point<seconds>::max()) {
829     const auto al = ptz.lookup(time_point<seconds>::max());
830     if (cs > al.cs) {
831       if (err != nullptr) *err = "Out-of-range field";
832       return false;
833     }
834   }
835   if (tp == time_point<seconds>::min()) {
836     const auto al = ptz.lookup(time_point<seconds>::min());
837     if (cs < al.cs) {
838       if (err != nullptr) *err = "Out-of-range field";
839       return false;
840     }
841   }
842 
843   *sec = tp;
844   *fs = subseconds;
845   return true;
846 }
847 
848 }  // namespace detail
849 }  // namespace cctz
850 }  // namespace time_internal
851 }  // namespace absl
852