Skip to content

Commit c6faf07

Browse files
Optimize %F/%T format/parse (#322)
* add benchmark * optimize parse %F and %T * optimize format %F and %T
1 parent 4a49902 commit c6faf07

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

src/cctz_benchmark.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ const char* const kFormats[] = {
400400
RFC3339_sec, // 3
401401
"%Y-%m-%d%ET%H:%M:%S", // 4
402402
"%Y-%m-%d", // 5
403+
"%F%ET%T", // 6
403404
};
404405
const int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
405406

src/time_zone_format.cc

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ std::string format(const std::string& format, const time_point<seconds>& tp,
334334
const std::tm tm = ToTM(al);
335335

336336
// Scratch buffer for internal conversions.
337-
char buf[3 + kDigits10_64]; // enough for longest conversion
337+
char buf[6 + (kDigits10_64 + 2)]; // enough for longest conversion %F
338338
char* const ep = buf + sizeof(buf);
339339
char* bp; // works back from ep
340340

@@ -378,7 +378,7 @@ std::string format(const std::string& format, const time_point<seconds>& tp,
378378
if (cur == end || (cur - percent) % 2 == 0) continue;
379379

380380
// Simple specifiers that we handle ourselves.
381-
if (strchr("YmdeUuWwHMSzZs%", *cur)) {
381+
if (strchr("YmdeFUuWwHMSTzZs%", *cur)) {
382382
if (cur - 1 != pending) {
383383
FormatTM(&result, std::string(pending, cur - 1), tm);
384384
}
@@ -399,6 +399,14 @@ std::string format(const std::string& format, const time_point<seconds>& tp,
399399
if (*cur == 'e' && *bp == '0') *bp = ' '; // for Windows
400400
result.append(bp, static_cast<std::size_t>(ep - bp));
401401
break;
402+
case 'F':
403+
bp = Format02d(ep, al.cs.day());
404+
*--bp = '-';
405+
bp = Format02d(bp, al.cs.month());
406+
*--bp = '-';
407+
bp = Format64(bp, 0, al.cs.year());
408+
result.append(bp, static_cast<std::size_t>(ep - bp));
409+
break;
402410
case 'U':
403411
bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::sunday));
404412
result.append(bp, static_cast<std::size_t>(ep - bp));
@@ -427,6 +435,14 @@ std::string format(const std::string& format, const time_point<seconds>& tp,
427435
bp = Format02d(ep, al.cs.second());
428436
result.append(bp, static_cast<std::size_t>(ep - bp));
429437
break;
438+
case 'T':
439+
bp = Format02d(ep, al.cs.second());
440+
*--bp = ':';
441+
bp = Format02d(bp, al.cs.minute());
442+
*--bp = ':';
443+
bp = Format02d(bp, al.cs.hour());
444+
result.append(bp, static_cast<std::size_t>(ep - bp));
445+
break;
430446
case 'z':
431447
bp = FormatOffset(ep, al.offset, "");
432448
result.append(bp, static_cast<std::size_t>(ep - bp));
@@ -764,6 +780,20 @@ bool parse(const std::string& format, const std::string& input,
764780
data = ParseInt(data, 2, 1, 31, &tm.tm_mday);
765781
week_num = -1;
766782
continue;
783+
case 'F':
784+
data = ParseInt(data, 0, kyearmin, kyearmax, &year);
785+
if (data != nullptr) {
786+
saw_year = true;
787+
data = (*data == '-' ? data + 1 : nullptr);
788+
}
789+
data = ParseInt(data, 2, 1, 12, &tm.tm_mon);
790+
if (data != nullptr) {
791+
tm.tm_mon -= 1;
792+
data = (*data == '-' ? data + 1 : nullptr);
793+
}
794+
data = ParseInt(data, 2, 1, 31, &tm.tm_mday);
795+
week_num = -1;
796+
continue;
767797
case 'U':
768798
data = ParseInt(data, 0, 0, 53, &week_num);
769799
week_start = weekday::sunday;
@@ -789,13 +819,20 @@ bool parse(const std::string& format, const std::string& input,
789819
case 'S':
790820
data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
791821
continue;
822+
case 'T':
823+
data = ParseInt(data, 2, 0, 23, &tm.tm_hour);
824+
twelve_hour = false;
825+
data = (data != nullptr && *data == ':' ? data + 1 : nullptr);
826+
data = ParseInt(data, 2, 0, 59, &tm.tm_min);
827+
data = (data != nullptr && *data == ':' ? data + 1 : nullptr);
828+
data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
829+
continue;
792830
case 'I':
793831
case 'l':
794832
case 'r': // probably uses %I
795833
twelve_hour = true;
796834
break;
797835
case 'R': // uses %H
798-
case 'T': // uses %H
799836
case 'c': // probably uses %H
800837
case 'X': // probably uses %H
801838
twelve_hour = false;

0 commit comments

Comments
 (0)