Skip to content

Commit e6be41d

Browse files
authored
Merge pull request #12 from timonwong/optimize
Add more documentation
2 parents 7a4c78c + 3fbce83 commit e6be41d

File tree

2 files changed

+167
-94
lines changed

2 files changed

+167
-94
lines changed

README.md

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# go-strftime
22

3-
[![GoDoc](https://godoc.org/github.com/imperfectgo/go-strftime?status.svg)](https://godoc.org/github.com/imperfectgo/go-strftime)
3+
[![GoDoc](https://godoc.org/github.com/imperfectgo/go-strftime?status.svg)](https://godoc.org/github.com/imperfectgo/go-strftime)
44
[![Build Status](https://travis-ci.org/imperfectgo/go-strftime.svg?branch=master)](https://travis-ci.org/imperfectgo/go-strftime)
55
[![Go Report Card](https://goreportcard.com/badge/github.com/imperfectgo/go-strftime)](https://goreportcard.com/report/github.com/imperfectgo/go-strftime)
66
[![Coverage](https://codecov.io/gh/imperfectgo/go-strftime/branch/master/graph/badge.svg)](https://codecov.io/gh/imperfectgo/go-strftime)
@@ -11,6 +11,49 @@ High performance C99-compatible `strftime` formatter for Go.
1111

1212
**EXPERIMENTAL** Please test before use.
1313

14+
## Compatibility
15+
16+
| Specifier | Description |
17+
| :-------: | -------------------------------------------------------------------------------- |
18+
| `%a` | abbreviated weekday name (Sun) |
19+
| `%A` | full weekday name (Sunday) |
20+
| `%b` | abbreviated month name (Sep) |
21+
| `%B` | full month name (September) |
22+
| `%c` | the same as time.ANSIC (%a %b %e %H:%M:%S %) |
23+
| `%C` | (year / 100) as number. Single digits are preceded by zero (20) |
24+
| `%d` | day of month as number. Single digits are preceded by zero (21) |
25+
| `%D` | equivalent to %m/%d/%y (09/21/14) |
26+
| `%e` | day of month as number. Single digits are preceded by a blank (21) |
27+
| `%f` | microsecond as a six digit decimal number, zero-padded on the left (001234) |
28+
| `%F` | equivalent to %Y-%m-%d (2014-09-21) |
29+
| `%g` | last two digits of ISO 8601 week-based year |
30+
| `%G` | ISO 8601 week-based year |
31+
| `%h` | same as %b |
32+
| `%H` | the hour (24 hour clock) as a number. Single digits are preceded by zero (15) |
33+
| `%I` | the hour (12 hour clock) as a number. Single digits are preceded by zero (03) |
34+
| `%j` | the day of the year as a decimal number. Single digits are preced by zeros (264) |
35+
| `%m` | the month as a decimal number. Single digits are preceded by a zero (09) |
36+
| `%M` | the minute as a decimal number. Single digits are preceded by a zero (32) |
37+
| `%n` | a newline (\n) |
38+
| `%p` | AM or PM as appropriate |
39+
| `%P` | am or pm as appropriate |
40+
| `%r` | equivalent to %I:%M:%S %p |
41+
| `%R` | equivalent to %H:%M |
42+
| `%S` | the second as a number. Single digits are preceded by a zero (05) |
43+
| `%t` | a tab (\t) |
44+
| `%T` | equivalent to %H:%M:%S |
45+
| `%u` | weekday as a decimal number, where Monday is 1 |
46+
| `%U` | week of the year as a decimal number (Sunday is the first day of the week) |
47+
| `%V` | ISO 8601 week of the year |
48+
| `%w` | the weekday (Sunday as first day of the week) as a number. (0) |
49+
| `%W` | week of the year as a decimal number (Monday is the first day of the week) |
50+
| `%x` | equivalent to %m/%d/%Y |
51+
| `%X` | equivalent to %H:%M:%S |
52+
| `%y` | year without century as a number. Single digits are preceded by zero (14) |
53+
| `%Y` | the year with century as a number (2014) |
54+
| `%z` | the time zone offset from UTC (-0700) |
55+
| `%Z` | time zone name (UTC) |
56+
1457
## Performance
1558

1659
Comparision with the standard library `time.(*Time).Format()`:

format.go

Lines changed: 123 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,50 @@ const (
5454

5555
// Format returns a textual representation of the time value formatted
5656
// according to C99-compatible strftime layout.
57+
//
58+
// List of accepted specifiers:
59+
// %a abbreviated weekday name (Sun)
60+
// %A full weekday name (Sunday)
61+
// %b abbreviated month name (Sep)
62+
// %B full month name (September)
63+
// %c the same as time.ANSIC (%a %b %e %H:%M:%S %)
64+
// %C (year / 100) as number. Single digits are preceded by zero (20)
65+
// %d day of month as number. Single digits are preceded by zero (21)
66+
// %D equivalent to %m/%d/%y (09/21/14)
67+
// %e day of month as number. Single digits are preceded by a blank (21)
68+
// %f microsecond as a six digit decimal number, zero-padded on the left (001234)
69+
// %F equivalent to %Y-%m-%d (2014-09-21)
70+
// %g last two digits of ISO 8601 week-based year
71+
// %G ISO 8601 week-based year
72+
// %h same as %b
73+
// %H the hour (24 hour clock) as a number. Single digits are preceded by zero (15)
74+
// %I the hour (12 hour clock) as a number. Single digits are preceded by zero (03)
75+
// %j the day of the year as a decimal number. Single digits are preced by zeros (264)
76+
// %m the month as a decimal number. Single digits are preceded by a zero (09)
77+
// %M the minute as a decimal number. Single digits are preceded by a zero (32)
78+
// %n a newline (\n)
79+
// %p AM or PM as appropriate
80+
// %P am or pm as appropriate
81+
// %r equivalent to %I:%M:%S %p
82+
// %R equivalent to %H:%M
83+
// %S the second as a number. Single digits are preceded by a zero (05)
84+
// %t a tab (\t)
85+
// %T equivalent to %H:%M:%S
86+
// %u weekday as a decimal number, where Monday is 1
87+
// %U week of the year as a decimal number (Sunday is the first day of the week)
88+
// %V ISO 8601 week of the year
89+
// %w the weekday (Sunday as first day of the week) as a number. (0)
90+
// %W week of the year as a decimal number (Monday is the first day of the week)
91+
// %x equivalent to %m/%d/%Y
92+
// %X equivalent to %H:%M:%S
93+
// %y year without century as a number. Single digits are preceded by zero (14)
94+
// %Y the year with century as a number (2014)
95+
// %z the time zone offset from UTC (-0700)
96+
// %Z time zone name (UTC)
5797
func Format(t time.Time, layout string) string {
5898
const bufSize = 64
5999
var b [bufSize]byte
60-
var buf = b[:0]
61-
buf = AppendFormat(buf, t, layout)
100+
buf := AppendFormat(b[:0], t, layout)
62101
return string(buf)
63102
}
64103

@@ -212,7 +251,6 @@ func AppendFormat(b []byte, t time.Time, layout string) []byte {
212251
}
213252
b = appendInt(b, zone/60, 2)
214253
b = appendInt(b, zone%60, 2)
215-
216254
case stdTZ:
217255
if name != "" {
218256
b = append(b, name...)
@@ -228,99 +266,91 @@ func AppendFormat(b []byte, t time.Time, layout string) []byte {
228266
// nextStdChunk finds the first occurrence of a std string in
229267
// layout and returns the text before, the std string, and the text after.
230268
func nextStdChunk(layout string) (prefix string, std int, suffix string) {
231-
specPos := -1
232-
233269
for i := 0; i < len(layout); i++ {
234-
c := int(layout[i])
235-
if specPos < 0 {
236-
if c == '%' {
237-
specPos = i
270+
j := i + 1
271+
if int(layout[i]) == '%' && len(layout) > j {
272+
spec := int(layout[j])
273+
switch spec {
274+
case 'a': // Mon
275+
return layout[0:i], stdWeekDay, layout[j+1:]
276+
case 'A': // Monday
277+
return layout[0:i], stdLongWeekDay, layout[j+1:]
278+
case 'b', 'h': // Jan
279+
return layout[0:i], stdMonth, layout[j+1:]
280+
case 'B': // January
281+
return layout[0:i], stdLongMonth, layout[j+1:]
282+
case 'c': // "Mon Jan _2 15:04:05 2006" (assumes "C" locale)
283+
return layout[0:i], stdNop, "%a %b %e %H:%M:%S %Y" + layout[j+1:]
284+
case 'C': // 20
285+
return layout[0:i], stdFirstTwoDigitYear, layout[j+1:]
286+
case 'd': // 02
287+
return layout[0:i], stdZeroDay, layout[j+1:]
288+
case 'D': // %m/%d/%y
289+
return layout[0:i], stdNop, "%m/%d/%y" + layout[j+1:]
290+
case 'e': // _2
291+
return layout[0:i], stdUnderDay, layout[j+1:]
292+
case 'f': // fraction seconds in microseconds (Python)
293+
std = stdFracSecond0
294+
std |= 6 << stdArgShift // microseconds precision
295+
return layout[0:i], std, layout[j+1:]
296+
case 'F': // %Y-%m-%d
297+
return layout[0:i], stdNop, "%Y-%m-%d" + layout[j+1:]
298+
case 'g':
299+
return layout[0:i], stdISO8601WeekYear, layout[j+1:]
300+
case 'G':
301+
return layout[0:i], stdISO8601LongWeekYear, layout[j+1:]
302+
case 'H':
303+
return layout[0:i], stdHour, layout[j+1:]
304+
case 'I':
305+
return layout[0:i], stdZeroHour12, layout[j+1:]
306+
case 'j':
307+
return layout[0:i], stdYearDay, layout[j+1:]
308+
case 'm':
309+
return layout[0:i], stdZeroMonth, layout[j+1:]
310+
case 'M':
311+
return layout[0:i], stdZeroMinute, layout[j+1:]
312+
case 'n':
313+
return layout[0:i] + "\n", stdNop, layout[j+1:]
314+
case 'p':
315+
return layout[0:i], stdPM, layout[j+1:]
316+
case 'P':
317+
return layout[0:i], stdpm, layout[j+1:]
318+
case 'r':
319+
return layout[0:i], stdNop, "%I:%M:%S %p" + layout[j+1:]
320+
case 'R': // %H:%M"
321+
return layout[0:i], stdNop, "%H:%M" + layout[j+1:]
322+
case 'S':
323+
return layout[0:i], stdZeroSecond, layout[j+1:]
324+
case 't':
325+
return layout[0:i] + "\t", stdNop, layout[j+1:]
326+
case 'T': // %H:%M:%S
327+
return layout[0:i], stdNop, "%H:%M:%S" + layout[j+1:]
328+
case 'u': // weekday as a decimal number, where Monday is 1
329+
return layout[0:i], stdNumWeekDay, layout[j+1:]
330+
case 'U': // week of the year as a decimal number (Sunday is the first day of the week)
331+
return layout[0:i], stdWeekOfYear, layout[j+1:]
332+
case 'V':
333+
return layout[0:i], stdISO8601Week, layout[j+1:]
334+
case 'w':
335+
return layout[0:i], stdZeroBasedNumWeekDay, layout[j+1:]
336+
case 'W': // week of the year as a decimal number (Monday is the first day of the week)
337+
return layout[0:i], stdMonFirstWeekOfYear, layout[j+1:]
338+
case 'x': // locale depended date representation (assumes "C" locale)
339+
return layout[0:i], stdNop, "%m/%d/%Y" + layout[j+1:]
340+
case 'X': // locale depended time representation (assumes "C" locale)
341+
return layout[0:i], stdNop, "%H:%M:%S" + layout[j+1:]
342+
case 'y':
343+
return layout[0:i], stdYear, layout[j+1:]
344+
case 'Y':
345+
return layout[0:i], stdLongYear, layout[j+1:]
346+
case 'z':
347+
return layout[0:i], stdNumTZ, layout[j+1:]
348+
case 'Z':
349+
return layout[0:i], stdTZ, layout[j+1:]
350+
case '%':
351+
return layout[0:i] + "%", stdNop, layout[j+1:]
238352
}
239-
continue
240353
}
241-
242-
switch c {
243-
case 'a': // Mon
244-
return layout[0:specPos], stdWeekDay, layout[i+1:]
245-
case 'A': // Monday
246-
return layout[0:specPos], stdLongWeekDay, layout[i+1:]
247-
case 'b', 'h': // Jan
248-
return layout[0:specPos], stdMonth, layout[i+1:]
249-
case 'B': // January
250-
return layout[0:specPos], stdLongMonth, layout[i+1:]
251-
case 'c': // "Mon Jan _2 15:04:05 2006" (assumes "C" locale)
252-
return layout[0:specPos], stdNop, "%a %b %e %H:%M:%S %Y" + layout[i+1:]
253-
case 'C': // 20
254-
return layout[0:specPos], stdFirstTwoDigitYear, layout[i+1:]
255-
case 'd': // 02
256-
return layout[0:specPos], stdZeroDay, layout[i+1:]
257-
case 'D': // %m/%d/%y
258-
return layout[0:specPos], stdNop, "%m/%d/%y" + layout[i+1:]
259-
case 'e': // _2
260-
return layout[0:specPos], stdUnderDay, layout[i+1:]
261-
case 'f': // fraction seconds in microseconds (Python)
262-
std = stdFracSecond0
263-
std |= 6 << stdArgShift // microseconds precision
264-
return layout[0:specPos], std, layout[i+1:]
265-
case 'F': // %Y-%m-%d
266-
return layout[0:specPos], stdNop, "%Y-%m-%d" + layout[i+1:]
267-
case 'g':
268-
return layout[0:specPos], stdISO8601WeekYear, layout[i+1:]
269-
case 'G':
270-
return layout[0:specPos], stdISO8601LongWeekYear, layout[i+1:]
271-
case 'H':
272-
return layout[0:specPos], stdHour, layout[i+1:]
273-
case 'I':
274-
return layout[0:specPos], stdZeroHour12, layout[i+1:]
275-
case 'j':
276-
return layout[0:specPos], stdYearDay, layout[i+1:]
277-
case 'm':
278-
return layout[0:specPos], stdZeroMonth, layout[i+1:]
279-
case 'M':
280-
return layout[0:specPos], stdZeroMinute, layout[i+1:]
281-
case 'n':
282-
return layout[0:specPos] + "\n", stdNop, layout[i+1:]
283-
case 'p':
284-
return layout[0:specPos], stdPM, layout[i+1:]
285-
case 'P':
286-
return layout[0:specPos], stdpm, layout[i+1:]
287-
case 'r':
288-
return layout[0:specPos], stdNop, "%I:%M:%S %p" + layout[i+1:]
289-
case 'R': // %H:%M"
290-
return layout[0:specPos], stdNop, "%H:%M" + layout[i+1:]
291-
case 'S':
292-
return layout[0:specPos], stdZeroSecond, layout[i+1:]
293-
case 't':
294-
return layout[0:specPos] + "\t", stdNop, layout[i+1:]
295-
case 'T': // %H:%M:%S
296-
return layout[0:specPos], stdNop, "%H:%M:%S" + layout[i+1:]
297-
case 'u': // weekday as a decimal number, where Monday is 1
298-
return layout[0:specPos], stdNumWeekDay, layout[i+1:]
299-
case 'U': // week of the year as a decimal number (Sunday is the first day of the week)
300-
return layout[0:specPos], stdWeekOfYear, layout[i+1:]
301-
case 'V':
302-
return layout[0:specPos], stdISO8601Week, layout[i+1:]
303-
case 'w':
304-
return layout[0:specPos], stdZeroBasedNumWeekDay, layout[i+1:]
305-
case 'W': // week of the year as a decimal number (Monday is the first day of the week)
306-
return layout[0:specPos], stdMonFirstWeekOfYear, layout[i+1:]
307-
case 'x': // locale depended date representation (assumes "C" locale)
308-
return layout[0:specPos], stdNop, "%m/%d/%Y" + layout[i+1:]
309-
case 'X': // locale depended time representation (assumes "C" locale)
310-
return layout[0:specPos], stdNop, "%H:%M:%S" + layout[i+1:]
311-
case 'y':
312-
return layout[0:specPos], stdYear, layout[i+1:]
313-
case 'Y':
314-
return layout[0:specPos], stdLongYear, layout[i+1:]
315-
case 'z':
316-
return layout[0:specPos], stdNumTZ, layout[i+1:]
317-
case 'Z':
318-
return layout[0:specPos], stdTZ, layout[i+1:]
319-
case '%':
320-
return layout[0:specPos] + "%", stdNop, layout[i+1:]
321-
}
322-
323-
specPos = -1
324354
}
325355

326356
return layout, 0, ""

0 commit comments

Comments
 (0)