@@ -47,19 +47,22 @@ func defaultFormat(v interface{}, f fmt.State, c rune) {
47
47
}
48
48
49
49
type flagScanner struct {
50
- flag byte
51
- start string
52
- end string
53
- buf []byte
54
- str string
55
- Length int
56
- Pos int
57
- HasFlag bool
58
- ChangeFlag bool
50
+ flag byte
51
+ modifiers []byte
52
+ start string
53
+ end string
54
+ buf []byte
55
+ str string
56
+ Length int
57
+ Pos int
58
+ HasFlag bool
59
+ ChangeFlag bool
60
+ HasModifier bool
61
+ Modifier byte
59
62
}
60
63
61
- func newFlagScanner (flag byte , start , end , str string ) * flagScanner {
62
- return & flagScanner {flag , start , end , make ([]byte , 0 , len (str )), str , len (str ), 0 , false , false }
64
+ func newFlagScanner (flag byte , modifiers , start , end , str string ) * flagScanner {
65
+ return & flagScanner {flag , [] byte ( modifiers ), start , end , make ([]byte , 0 , len (str )), str , len (str ), 0 , false , false , false , 0 }
63
66
}
64
67
65
68
func (fs * flagScanner ) AppendString (str string ) { fs .buf = append (fs .buf , str ... ) }
@@ -84,38 +87,103 @@ func (fs *flagScanner) Next() (byte, bool) {
84
87
fs .AppendChar (fs .flag )
85
88
fs .Pos += 2
86
89
return fs .Next ()
87
- } else if fs .Pos != fs .Length - 1 {
90
+ } else if fs .Pos < fs .Length - 1 {
88
91
if fs .HasFlag {
89
92
fs .AppendString (fs .end )
90
93
}
91
94
fs .AppendString (fs .start )
92
95
fs .ChangeFlag = true
93
96
fs .HasFlag = true
97
+ fs .HasModifier = false
98
+ fs .Modifier = 0
99
+ if fs .Pos < fs .Length - 2 {
100
+ for _ , modifier := range fs .modifiers {
101
+ if fs .str [fs .Pos + 1 ] == modifier {
102
+ fs .HasModifier = true
103
+ fs .Modifier = modifier
104
+ fs .Pos += 1
105
+ }
106
+ }
107
+ }
94
108
}
95
109
}
96
110
}
97
111
fs .Pos ++
98
112
return c , false
99
113
}
100
114
101
- var cDateFlagToGo = map [byte ]string {
102
- 'a' : "mon" , 'A' : "Monday" , 'b' : "Jan" , 'B' : "January" , 'c' : "02 Jan 06 15:04 MST" , 'd' : "02" ,
103
- 'F' : "2006-01-02" , 'H' : "15" , 'I' : "03" , 'm' : "01" , 'M' : "04" , 'p' : "PM" , 'P' : "pm" , 'S' : "05" ,
104
- 'x' : "15/04/05" , 'X' : "15:04:05" , 'y' : "06" , 'Y' : "2006" , 'z' : "-0700" , 'Z' : "MST" }
115
+ var cDateFlagToGo = map [string ]string {
116
+ // Formatting
117
+ "n" : "\n " ,
118
+ "t" : "\t " ,
119
+
120
+ // Year
121
+ "Y" : "2006" , "y" : "06" ,
122
+
123
+ // Month
124
+ "b" : "Jan" , "B" : "January" ,
125
+ "m" : "01" , "-m" : "1" ,
126
+
127
+ // Day of the year/month
128
+ "j" : "002" ,
129
+ "d" : "02" , "-d" : "2" , "e" : "_2" ,
130
+
131
+ // Day of the week
132
+ "a" : "Mon" , "A" : "Monday" ,
105
133
134
+ // Hour, minute, second
135
+ "H" : "15" ,
136
+ "I" : "03" , "l" : "3" ,
137
+ "M" : "04" ,
138
+ "S" : "05" ,
139
+
140
+ // Other
141
+ "c" : "02 Jan 06 15:04 MST" ,
142
+ "x" : "01/02/06" , "X" : "15:04:05" ,
143
+ "D" : "01/02/06" ,
144
+ "F" : "2006-01-02" ,
145
+ "r" : "03:04:05 PM" , "R" : "15:04" ,
146
+ "T" : "15:04:05" ,
147
+ "p" : "PM" , "P" : "pm" ,
148
+ "z" : "-0700" , "Z" : "MST" ,
149
+
150
+ // Many other flags are handled in the body of strftime since they cannot
151
+ // be represented in Go format strings.
152
+ }
153
+
154
+ // This implementation of strftime is inspired by both the C spec and Ruby's
155
+ // extensions. This allows for flags like %-d, which provides the day of the
156
+ // month without padding (1..31 instead of 01..31).
106
157
func strftime (t time.Time , cfmt string ) string {
107
- sc := newFlagScanner ('%' , "" , "" , cfmt )
158
+ sc := newFlagScanner ('%' , "-" , " " , "" , cfmt )
108
159
for c , eos := sc .Next (); ! eos ; c , eos = sc .Next () {
109
160
if ! sc .ChangeFlag {
110
161
if sc .HasFlag {
111
- if v , ok := cDateFlagToGo [c ]; ok {
162
+ flag := string (c )
163
+ if sc .HasModifier {
164
+ flag = string (sc .Modifier ) + flag
165
+ }
166
+
167
+ if v , ok := cDateFlagToGo [flag ]; ok {
112
168
sc .AppendString (t .Format (v ))
113
169
} else {
114
170
switch c {
171
+ case 'G' :
172
+ isoYear , _ := t .ISOWeek ()
173
+ sc .AppendString (fmt .Sprint (isoYear ))
174
+ case 'g' :
175
+ isoYear , _ := t .ISOWeek ()
176
+ sc .AppendString (fmt .Sprint (isoYear )[2 :])
177
+ case 'V' :
178
+ _ , isoWeek := t .ISOWeek ()
179
+ sc .AppendString (fmt .Sprint (isoWeek ))
115
180
case 'w' :
116
181
sc .AppendString (fmt .Sprint (int (t .Weekday ())))
117
182
default :
118
183
sc .AppendChar ('%' )
184
+ if sc .HasModifier {
185
+ sc .AppendChar (sc .Modifier )
186
+ }
119
187
sc .AppendChar (c )
120
188
}
121
189
}
0 commit comments