1
2
3
4
5 package json
6
7 import (
8 "errors"
9 "fmt"
10 "reflect"
11 "strings"
12 "time"
13 )
14
15 var (
16 timeDurationType = reflect.TypeOf((*time.Duration)(nil)).Elem()
17 timeTimeType = reflect.TypeOf((*time.Time)(nil)).Elem()
18 )
19
20 func makeTimeArshaler(fncs *arshaler, t reflect.Type) *arshaler {
21
22
23
24
25
26
27
28
29 switch t {
30 case timeDurationType:
31 fncs.nonDefault = true
32 marshalNanos := fncs.marshal
33 fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error {
34 if mo.format != "" && mo.formatDepth == enc.tokens.depth() {
35 if mo.format == "nanos" {
36 mo.format = ""
37 return marshalNanos(mo, enc, va)
38 } else {
39 return newInvalidFormatError("marshal", t, mo.format)
40 }
41 }
42
43 td := va.Interface().(time.Duration)
44 b := enc.UnusedBuffer()
45 b = append(b, '"')
46 b = append(b, td.String()...)
47 b = append(b, '"')
48 return enc.WriteValue(b)
49 }
50 unmarshalNanos := fncs.unmarshal
51 fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error {
52
53
54 if uo.format != "" && uo.formatDepth == dec.tokens.depth() {
55 if uo.format == "nanos" {
56 uo.format = ""
57 return unmarshalNanos(uo, dec, va)
58 } else {
59 return newInvalidFormatError("unmarshal", t, uo.format)
60 }
61 }
62
63 var flags valueFlags
64 td := va.Addr().Interface().(*time.Duration)
65 val, err := dec.readValue(&flags)
66 if err != nil {
67 return err
68 }
69 switch k := val.Kind(); k {
70 case 'n':
71 *td = time.Duration(0)
72 return nil
73 case '"':
74 val = unescapeStringMayCopy(val, flags.isVerbatim())
75 td2, err := time.ParseDuration(string(val))
76 if err != nil {
77 return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err}
78 }
79 *td = td2
80 return nil
81 default:
82 return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t}
83 }
84 }
85 case timeTimeType:
86 fncs.nonDefault = true
87 fncs.marshal = func(mo MarshalOptions, enc *Encoder, va addressableValue) error {
88 format := time.RFC3339Nano
89 isRFC3339 := true
90 if mo.format != "" && mo.formatDepth == enc.tokens.depth() {
91 var err error
92 format, isRFC3339, err = checkTimeFormat(mo.format)
93 if err != nil {
94 return &SemanticError{action: "marshal", GoType: t, Err: err}
95 }
96 }
97
98 tt := va.Interface().(time.Time)
99 b := enc.UnusedBuffer()
100 b = append(b, '"')
101 b = tt.AppendFormat(b, format)
102 b = append(b, '"')
103 if isRFC3339 {
104
105
106
107 var err error
108 switch b := b[len(`"`) : len(b)-len(`"`)]; {
109 case b[len("9999")] != '-':
110 err = errors.New("year outside of range [0,9999]")
111 case b[len(b)-1] != 'Z':
112 c := b[len(b)-len("Z07:00")]
113 if ('0' <= c && c <= '9') || parseDec2(b[len(b)-len("07:00"):]) >= 24 {
114 err = errors.New("timezone hour outside of range [0,23]")
115 }
116 }
117 if err != nil {
118 return &SemanticError{action: "marshal", GoType: t, Err: err}
119 }
120 return enc.WriteValue(b)
121 }
122
123
124
125 if consumeSimpleString(b) != len(b) {
126 b, _ = appendString(nil, string(b[len(`"`):len(b)-len(`"`)]), true, nil)
127 }
128 return enc.WriteValue(b)
129 }
130 fncs.unmarshal = func(uo UnmarshalOptions, dec *Decoder, va addressableValue) error {
131 format := time.RFC3339
132 isRFC3339 := true
133 if uo.format != "" && uo.formatDepth == dec.tokens.depth() {
134 var err error
135 format, isRFC3339, err = checkTimeFormat(uo.format)
136 if err != nil {
137 return &SemanticError{action: "unmarshal", GoType: t, Err: err}
138 }
139 }
140
141 var flags valueFlags
142 tt := va.Addr().Interface().(*time.Time)
143 val, err := dec.readValue(&flags)
144 if err != nil {
145 return err
146 }
147 k := val.Kind()
148 switch k {
149 case 'n':
150 *tt = time.Time{}
151 return nil
152 case '"':
153 val = unescapeStringMayCopy(val, flags.isVerbatim())
154 tt2, err := time.Parse(format, string(val))
155 if isRFC3339 && err == nil {
156
157
158
159
160
161 newParseError := func(layout, value, layoutElem, valueElem, message string) error {
162 return &time.ParseError{Layout: layout, Value: value, LayoutElem: layoutElem, ValueElem: valueElem, Message: message}
163 }
164 switch {
165 case val[len("2006-01-02T")+1] == ':':
166 err = newParseError(format, string(val), "15", string(val[len("2006-01-02T"):][:1]), "")
167 case val[len("2006-01-02T15:04:05")] == ',':
168 err = newParseError(format, string(val), ".", ",", "")
169 case val[len(val)-1] != 'Z':
170 switch {
171 case parseDec2(val[len(val)-len("07:00"):]) >= 24:
172 err = newParseError(format, string(val), "Z07:00", string(val[len(val)-len("Z07:00"):]), ": timezone hour out of range")
173 case parseDec2(val[len(val)-len("00"):]) >= 60:
174 err = newParseError(format, string(val), "Z07:00", string(val[len(val)-len("Z07:00"):]), ": timezone minute out of range")
175 }
176 }
177 }
178 if err != nil {
179 return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t, Err: err}
180 }
181 *tt = tt2
182 return nil
183 default:
184 return &SemanticError{action: "unmarshal", JSONKind: k, GoType: t}
185 }
186 }
187 }
188 return fncs
189 }
190
191 func checkTimeFormat(format string) (string, bool, error) {
192
193
194 if len(format) > 0 && 'A' <= format[0] && format[0] <= 'Z' {
195 switch format {
196 case "ANSIC":
197 return time.ANSIC, false, nil
198 case "UnixDate":
199 return time.UnixDate, false, nil
200 case "RubyDate":
201 return time.RubyDate, false, nil
202 case "RFC822":
203 return time.RFC822, false, nil
204 case "RFC822Z":
205 return time.RFC822Z, false, nil
206 case "RFC850":
207 return time.RFC850, false, nil
208 case "RFC1123":
209 return time.RFC1123, false, nil
210 case "RFC1123Z":
211 return time.RFC1123Z, false, nil
212 case "RFC3339":
213 return time.RFC3339, true, nil
214 case "RFC3339Nano":
215 return time.RFC3339Nano, true, nil
216 case "Kitchen":
217 return time.Kitchen, false, nil
218 case "Stamp":
219 return time.Stamp, false, nil
220 case "StampMilli":
221 return time.StampMilli, false, nil
222 case "StampMicro":
223 return time.StampMicro, false, nil
224 case "StampNano":
225 return time.StampNano, false, nil
226 default:
227
228
229 if strings.TrimFunc(format, isLetterOrDigit) == "" {
230 return "", false, fmt.Errorf("undefined format layout: %v", format)
231 }
232 }
233 }
234 return format, false, nil
235 }
236
237
238
239 func parseDec2(b []byte) byte {
240 return 10*(b[0]-'0') + (b[1] - '0')
241 }
242
View as plain text