-
Notifications
You must be signed in to change notification settings - Fork 5
/
strftime.go
134 lines (121 loc) · 4.33 KB
/
strftime.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Package strftime provides a C99-compatible strftime formatter for use with
// Go time.Time instances.
package strftime
import (
"bytes"
"fmt"
"strings"
"text/scanner"
"time"
"unicode"
)
// Format accepts a Time pointer and a C99-compatible strftime format string
// and returns the formatted result. If the Time pointer is nil, the current
// time is used.
//
// See http://en.cppreference.com/w/c/chrono/strftime for available conversion
// specifiers. Specific locale specifiers are not yet supported.
func Format(t *time.Time, f string) string {
var (
buf bytes.Buffer
s scanner.Scanner
)
if t == nil {
now := time.Now()
t = &now
}
s.Init(strings.NewReader(f))
s.IsIdentRune = func(ch rune, i int) bool {
return (ch == '%' && i <= 1) || (unicode.IsLetter(ch) && i == 1)
}
// Honor all white space characters.
s.Whitespace = 0
for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
txt := s.TokenText()
if len(txt) < 2 || !strings.HasPrefix(txt, "%") {
buf.WriteString(txt)
continue
}
buf.WriteString(formats.Apply(*t, txt[1:]))
}
return buf.String()
}
// formatMap allows for quick lookup of supported formats where the key
// is the C99-compatible conversion specifier and the value is a function
// that accepts a Time object and returns the formatted datetime string.
type formatMap map[string]func(time.Time) string
// Apply the C99-compatible conversion specifier to the Time object and
// return the formatted datetime string. If no such specifier exists,
// the original conversion specifier prepended with the delimiter will
// be returned.
func (f formatMap) Apply(t time.Time, txt string) string {
fc, ok := f[txt]
if !ok {
return fmt.Sprintf("%%%s", txt)
}
return fc(t)
}
var formats = formatMap{
"a": func(t time.Time) string { return t.Format("Mon") },
"A": func(t time.Time) string { return t.Format("Monday") },
"b": func(t time.Time) string { return t.Format("Jan") },
"B": func(t time.Time) string { return t.Format("January") },
"c": func(t time.Time) string { return t.Format(time.ANSIC) },
"C": func(t time.Time) string { return t.Format("2006")[:2] },
"d": func(t time.Time) string { return t.Format("02") },
"D": func(t time.Time) string { return t.Format("01/02/06") },
"e": func(t time.Time) string { return t.Format("_2") },
"F": func(t time.Time) string { return t.Format("2006-01-02") },
"g": func(t time.Time) string {
y, _ := t.ISOWeek()
return fmt.Sprintf("%d", y)[2:]
},
"G": func(t time.Time) string {
y, _ := t.ISOWeek()
return fmt.Sprintf("%d", y)
},
"h": func(t time.Time) string { return t.Format("Jan") },
"H": func(t time.Time) string { return t.Format("15") },
"I": func(t time.Time) string { return t.Format("03") },
"j": func(t time.Time) string { return fmt.Sprintf("%03d", t.YearDay()) },
"k": func(t time.Time) string { return fmt.Sprintf("%2d", t.Hour()) },
"l": func(t time.Time) string { return fmt.Sprintf("%2s", t.Format("3")) },
"m": func(t time.Time) string { return t.Format("01") },
"M": func(t time.Time) string { return t.Format("04") },
"n": func(t time.Time) string { return "\n" },
"p": func(t time.Time) string { return t.Format("PM") },
"P": func(t time.Time) string { return t.Format("pm") },
"r": func(t time.Time) string { return t.Format("03:04:05 PM") },
"R": func(t time.Time) string { return t.Format("15:04") },
"s": func(t time.Time) string { return fmt.Sprintf("%d", t.Unix()) },
"S": func(t time.Time) string { return t.Format("05") },
"t": func(t time.Time) string { return "\t" },
"T": func(t time.Time) string { return t.Format("15:04:05") },
"u": func(t time.Time) string {
d := t.Weekday()
if d == 0 {
d = 7
}
return fmt.Sprintf("%d", d)
},
// "U": func(t time.Time) string {
// TODO
// },
"V": func(t time.Time) string {
_, w := t.ISOWeek()
return fmt.Sprintf("%02d", w)
},
"w": func(t time.Time) string {
return fmt.Sprintf("%d", t.Weekday())
},
// "W": func(t time.Time) string {
// TODO
// },
"x": func(t time.Time) string { return t.Format("01/02/2006") },
"X": func(t time.Time) string { return t.Format("15:04:05") },
"y": func(t time.Time) string { return t.Format("06") },
"Y": func(t time.Time) string { return t.Format("2006") },
"z": func(t time.Time) string { return t.Format("-0700") },
"Z": func(t time.Time) string { return t.Format("MST") },
"%": func(t time.Time) string { return "%" },
}