18 |
18 |
19 var errNegativeNotAllowed = errors.New("unable to cast negative value") |
19 var errNegativeNotAllowed = errors.New("unable to cast negative value") |
20 |
20 |
21 // ToTimeE casts an interface to a time.Time type. |
21 // ToTimeE casts an interface to a time.Time type. |
22 func ToTimeE(i interface{}) (tim time.Time, err error) { |
22 func ToTimeE(i interface{}) (tim time.Time, err error) { |
|
23 return ToTimeInDefaultLocationE(i, time.UTC) |
|
24 } |
|
25 |
|
26 // ToTimeInDefaultLocationE casts an empty interface to time.Time, |
|
27 // interpreting inputs without a timezone to be in the given location, |
|
28 // or the local timezone if nil. |
|
29 func ToTimeInDefaultLocationE(i interface{}, location *time.Location) (tim time.Time, err error) { |
23 i = indirect(i) |
30 i = indirect(i) |
24 |
31 |
25 switch v := i.(type) { |
32 switch v := i.(type) { |
26 case time.Time: |
33 case time.Time: |
27 return v, nil |
34 return v, nil |
28 case string: |
35 case string: |
29 return StringToDate(v) |
36 return StringToDateInDefaultLocation(v, location) |
|
37 case json.Number: |
|
38 s, err1 := ToInt64E(v) |
|
39 if err1 != nil { |
|
40 return time.Time{}, fmt.Errorf("unable to cast %#v of type %T to Time", i, i) |
|
41 } |
|
42 return time.Unix(s, 0), nil |
30 case int: |
43 case int: |
31 return time.Unix(int64(v), 0), nil |
44 return time.Unix(int64(v), 0), nil |
32 case int64: |
45 case int64: |
33 return time.Unix(v, 0), nil |
46 return time.Unix(v, 0), nil |
34 case int32: |
47 case int32: |
84 return true, nil |
102 return true, nil |
85 } |
103 } |
86 return false, nil |
104 return false, nil |
87 case string: |
105 case string: |
88 return strconv.ParseBool(i.(string)) |
106 return strconv.ParseBool(i.(string)) |
|
107 case json.Number: |
|
108 v, err := ToInt64E(b) |
|
109 if err == nil { |
|
110 return v != 0, nil |
|
111 } |
|
112 return false, fmt.Errorf("unable to cast %#v of type %T to bool", i, i) |
89 default: |
113 default: |
90 return false, fmt.Errorf("unable to cast %#v of type %T to bool", i, i) |
114 return false, fmt.Errorf("unable to cast %#v of type %T to bool", i, i) |
91 } |
115 } |
92 } |
116 } |
93 |
117 |
94 // ToFloat64E casts an interface to a float64 type. |
118 // ToFloat64E casts an interface to a float64 type. |
95 func ToFloat64E(i interface{}) (float64, error) { |
119 func ToFloat64E(i interface{}) (float64, error) { |
96 i = indirect(i) |
120 i = indirect(i) |
|
121 |
|
122 intv, ok := toInt(i) |
|
123 if ok { |
|
124 return float64(intv), nil |
|
125 } |
97 |
126 |
98 switch s := i.(type) { |
127 switch s := i.(type) { |
99 case float64: |
128 case float64: |
100 return s, nil |
129 return s, nil |
101 case float32: |
130 case float32: |
102 return float64(s), nil |
|
103 case int: |
|
104 return float64(s), nil |
131 return float64(s), nil |
105 case int64: |
132 case int64: |
106 return float64(s), nil |
133 return float64(s), nil |
107 case int32: |
134 case int32: |
108 return float64(s), nil |
135 return float64(s), nil |
124 v, err := strconv.ParseFloat(s, 64) |
151 v, err := strconv.ParseFloat(s, 64) |
125 if err == nil { |
152 if err == nil { |
126 return v, nil |
153 return v, nil |
127 } |
154 } |
128 return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) |
155 return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) |
|
156 case json.Number: |
|
157 v, err := s.Float64() |
|
158 if err == nil { |
|
159 return v, nil |
|
160 } |
|
161 return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) |
129 case bool: |
162 case bool: |
130 if s { |
163 if s { |
131 return 1, nil |
164 return 1, nil |
132 } |
165 } |
133 return 0, nil |
166 return 0, nil |
|
167 case nil: |
|
168 return 0, nil |
134 default: |
169 default: |
135 return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) |
170 return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) |
136 } |
171 } |
137 } |
172 } |
138 |
173 |
139 // ToFloat32E casts an interface to a float32 type. |
174 // ToFloat32E casts an interface to a float32 type. |
140 func ToFloat32E(i interface{}) (float32, error) { |
175 func ToFloat32E(i interface{}) (float32, error) { |
141 i = indirect(i) |
176 i = indirect(i) |
|
177 |
|
178 intv, ok := toInt(i) |
|
179 if ok { |
|
180 return float32(intv), nil |
|
181 } |
142 |
182 |
143 switch s := i.(type) { |
183 switch s := i.(type) { |
144 case float64: |
184 case float64: |
145 return float32(s), nil |
185 return float32(s), nil |
146 case float32: |
186 case float32: |
147 return s, nil |
187 return s, nil |
148 case int: |
|
149 return float32(s), nil |
|
150 case int64: |
188 case int64: |
151 return float32(s), nil |
189 return float32(s), nil |
152 case int32: |
190 case int32: |
153 return float32(s), nil |
191 return float32(s), nil |
154 case int16: |
192 case int16: |
169 v, err := strconv.ParseFloat(s, 32) |
207 v, err := strconv.ParseFloat(s, 32) |
170 if err == nil { |
208 if err == nil { |
171 return float32(v), nil |
209 return float32(v), nil |
172 } |
210 } |
173 return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) |
211 return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) |
|
212 case json.Number: |
|
213 v, err := s.Float64() |
|
214 if err == nil { |
|
215 return float32(v), nil |
|
216 } |
|
217 return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) |
174 case bool: |
218 case bool: |
175 if s { |
219 if s { |
176 return 1, nil |
220 return 1, nil |
177 } |
221 } |
178 return 0, nil |
222 return 0, nil |
|
223 case nil: |
|
224 return 0, nil |
179 default: |
225 default: |
180 return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) |
226 return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) |
181 } |
227 } |
182 } |
228 } |
183 |
229 |
184 // ToInt64E casts an interface to an int64 type. |
230 // ToInt64E casts an interface to an int64 type. |
185 func ToInt64E(i interface{}) (int64, error) { |
231 func ToInt64E(i interface{}) (int64, error) { |
186 i = indirect(i) |
232 i = indirect(i) |
187 |
233 |
|
234 intv, ok := toInt(i) |
|
235 if ok { |
|
236 return int64(intv), nil |
|
237 } |
|
238 |
188 switch s := i.(type) { |
239 switch s := i.(type) { |
189 case int: |
|
190 return int64(s), nil |
|
191 case int64: |
240 case int64: |
192 return s, nil |
241 return s, nil |
193 case int32: |
242 case int32: |
194 return int64(s), nil |
243 return int64(s), nil |
195 case int16: |
244 case int16: |
418 |
489 |
419 // ToUintE casts an interface to a uint type. |
490 // ToUintE casts an interface to a uint type. |
420 func ToUintE(i interface{}) (uint, error) { |
491 func ToUintE(i interface{}) (uint, error) { |
421 i = indirect(i) |
492 i = indirect(i) |
422 |
493 |
|
494 intv, ok := toInt(i) |
|
495 if ok { |
|
496 if intv < 0 { |
|
497 return 0, errNegativeNotAllowed |
|
498 } |
|
499 return uint(intv), nil |
|
500 } |
|
501 |
423 switch s := i.(type) { |
502 switch s := i.(type) { |
424 case string: |
503 case string: |
425 v, err := strconv.ParseUint(s, 0, 0) |
504 v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) |
426 if err == nil { |
505 if err == nil { |
|
506 if v < 0 { |
|
507 return 0, errNegativeNotAllowed |
|
508 } |
427 return uint(v), nil |
509 return uint(v), nil |
428 } |
510 } |
429 return 0, fmt.Errorf("unable to cast %#v to uint: %s", i, err) |
511 return 0, fmt.Errorf("unable to cast %#v of type %T to uint", i, i) |
430 case int: |
512 case json.Number: |
431 if s < 0 { |
513 return ToUintE(string(s)) |
432 return 0, errNegativeNotAllowed |
|
433 } |
|
434 return uint(s), nil |
|
435 case int64: |
514 case int64: |
436 if s < 0 { |
515 if s < 0 { |
437 return 0, errNegativeNotAllowed |
516 return 0, errNegativeNotAllowed |
438 } |
517 } |
439 return uint(s), nil |
518 return uint(s), nil |
486 |
565 |
487 // ToUint64E casts an interface to a uint64 type. |
566 // ToUint64E casts an interface to a uint64 type. |
488 func ToUint64E(i interface{}) (uint64, error) { |
567 func ToUint64E(i interface{}) (uint64, error) { |
489 i = indirect(i) |
568 i = indirect(i) |
490 |
569 |
|
570 intv, ok := toInt(i) |
|
571 if ok { |
|
572 if intv < 0 { |
|
573 return 0, errNegativeNotAllowed |
|
574 } |
|
575 return uint64(intv), nil |
|
576 } |
|
577 |
491 switch s := i.(type) { |
578 switch s := i.(type) { |
492 case string: |
579 case string: |
493 v, err := strconv.ParseUint(s, 0, 64) |
580 v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) |
494 if err == nil { |
581 if err == nil { |
495 return v, nil |
582 if v < 0 { |
496 } |
583 return 0, errNegativeNotAllowed |
497 return 0, fmt.Errorf("unable to cast %#v to uint64: %s", i, err) |
584 } |
498 case int: |
585 return uint64(v), nil |
499 if s < 0 { |
586 } |
500 return 0, errNegativeNotAllowed |
587 return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i) |
501 } |
588 case json.Number: |
502 return uint64(s), nil |
589 return ToUint64E(string(s)) |
503 case int64: |
590 case int64: |
504 if s < 0 { |
591 if s < 0 { |
505 return 0, errNegativeNotAllowed |
592 return 0, errNegativeNotAllowed |
506 } |
593 } |
507 return uint64(s), nil |
594 return uint64(s), nil |
554 |
641 |
555 // ToUint32E casts an interface to a uint32 type. |
642 // ToUint32E casts an interface to a uint32 type. |
556 func ToUint32E(i interface{}) (uint32, error) { |
643 func ToUint32E(i interface{}) (uint32, error) { |
557 i = indirect(i) |
644 i = indirect(i) |
558 |
645 |
|
646 intv, ok := toInt(i) |
|
647 if ok { |
|
648 if intv < 0 { |
|
649 return 0, errNegativeNotAllowed |
|
650 } |
|
651 return uint32(intv), nil |
|
652 } |
|
653 |
559 switch s := i.(type) { |
654 switch s := i.(type) { |
560 case string: |
655 case string: |
561 v, err := strconv.ParseUint(s, 0, 32) |
656 v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) |
562 if err == nil { |
657 if err == nil { |
|
658 if v < 0 { |
|
659 return 0, errNegativeNotAllowed |
|
660 } |
563 return uint32(v), nil |
661 return uint32(v), nil |
564 } |
662 } |
565 return 0, fmt.Errorf("unable to cast %#v to uint32: %s", i, err) |
663 return 0, fmt.Errorf("unable to cast %#v of type %T to uint32", i, i) |
566 case int: |
664 case json.Number: |
567 if s < 0 { |
665 return ToUint32E(string(s)) |
568 return 0, errNegativeNotAllowed |
|
569 } |
|
570 return uint32(s), nil |
|
571 case int64: |
666 case int64: |
572 if s < 0 { |
667 if s < 0 { |
573 return 0, errNegativeNotAllowed |
668 return 0, errNegativeNotAllowed |
574 } |
669 } |
575 return uint32(s), nil |
670 return uint32(s), nil |
622 |
717 |
623 // ToUint16E casts an interface to a uint16 type. |
718 // ToUint16E casts an interface to a uint16 type. |
624 func ToUint16E(i interface{}) (uint16, error) { |
719 func ToUint16E(i interface{}) (uint16, error) { |
625 i = indirect(i) |
720 i = indirect(i) |
626 |
721 |
|
722 intv, ok := toInt(i) |
|
723 if ok { |
|
724 if intv < 0 { |
|
725 return 0, errNegativeNotAllowed |
|
726 } |
|
727 return uint16(intv), nil |
|
728 } |
|
729 |
627 switch s := i.(type) { |
730 switch s := i.(type) { |
628 case string: |
731 case string: |
629 v, err := strconv.ParseUint(s, 0, 16) |
732 v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) |
630 if err == nil { |
733 if err == nil { |
|
734 if v < 0 { |
|
735 return 0, errNegativeNotAllowed |
|
736 } |
631 return uint16(v), nil |
737 return uint16(v), nil |
632 } |
738 } |
633 return 0, fmt.Errorf("unable to cast %#v to uint16: %s", i, err) |
739 return 0, fmt.Errorf("unable to cast %#v of type %T to uint16", i, i) |
634 case int: |
740 case json.Number: |
635 if s < 0 { |
741 return ToUint16E(string(s)) |
636 return 0, errNegativeNotAllowed |
|
637 } |
|
638 return uint16(s), nil |
|
639 case int64: |
742 case int64: |
640 if s < 0 { |
743 if s < 0 { |
641 return 0, errNegativeNotAllowed |
744 return 0, errNegativeNotAllowed |
642 } |
745 } |
643 return uint16(s), nil |
746 return uint16(s), nil |
690 |
793 |
691 // ToUint8E casts an interface to a uint type. |
794 // ToUint8E casts an interface to a uint type. |
692 func ToUint8E(i interface{}) (uint8, error) { |
795 func ToUint8E(i interface{}) (uint8, error) { |
693 i = indirect(i) |
796 i = indirect(i) |
694 |
797 |
|
798 intv, ok := toInt(i) |
|
799 if ok { |
|
800 if intv < 0 { |
|
801 return 0, errNegativeNotAllowed |
|
802 } |
|
803 return uint8(intv), nil |
|
804 } |
|
805 |
695 switch s := i.(type) { |
806 switch s := i.(type) { |
696 case string: |
807 case string: |
697 v, err := strconv.ParseUint(s, 0, 8) |
808 v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0) |
698 if err == nil { |
809 if err == nil { |
|
810 if v < 0 { |
|
811 return 0, errNegativeNotAllowed |
|
812 } |
699 return uint8(v), nil |
813 return uint8(v), nil |
700 } |
814 } |
701 return 0, fmt.Errorf("unable to cast %#v to uint8: %s", i, err) |
815 return 0, fmt.Errorf("unable to cast %#v of type %T to uint8", i, i) |
702 case int: |
816 case json.Number: |
703 if s < 0 { |
817 return ToUint8E(string(s)) |
704 return 0, errNegativeNotAllowed |
|
705 } |
|
706 return uint8(s), nil |
|
707 case int64: |
818 case int64: |
708 if s < 0 { |
819 if s < 0 { |
709 return 0, errNegativeNotAllowed |
820 return 0, errNegativeNotAllowed |
710 } |
821 } |
711 return uint8(s), nil |
822 return uint8(s), nil |
1127 a = append(a, ToString(u)) |
1240 a = append(a, ToString(u)) |
1128 } |
1241 } |
1129 return a, nil |
1242 return a, nil |
1130 case []string: |
1243 case []string: |
1131 return v, nil |
1244 return v, nil |
|
1245 case []int8: |
|
1246 for _, u := range v { |
|
1247 a = append(a, ToString(u)) |
|
1248 } |
|
1249 return a, nil |
|
1250 case []int: |
|
1251 for _, u := range v { |
|
1252 a = append(a, ToString(u)) |
|
1253 } |
|
1254 return a, nil |
|
1255 case []int32: |
|
1256 for _, u := range v { |
|
1257 a = append(a, ToString(u)) |
|
1258 } |
|
1259 return a, nil |
|
1260 case []int64: |
|
1261 for _, u := range v { |
|
1262 a = append(a, ToString(u)) |
|
1263 } |
|
1264 return a, nil |
|
1265 case []float32: |
|
1266 for _, u := range v { |
|
1267 a = append(a, ToString(u)) |
|
1268 } |
|
1269 return a, nil |
|
1270 case []float64: |
|
1271 for _, u := range v { |
|
1272 a = append(a, ToString(u)) |
|
1273 } |
|
1274 return a, nil |
1132 case string: |
1275 case string: |
1133 return strings.Fields(v), nil |
1276 return strings.Fields(v), nil |
|
1277 case []error: |
|
1278 for _, err := range i.([]error) { |
|
1279 a = append(a, err.Error()) |
|
1280 } |
|
1281 return a, nil |
1134 case interface{}: |
1282 case interface{}: |
1135 str, err := ToStringE(v) |
1283 str, err := ToStringE(v) |
1136 if err != nil { |
1284 if err != nil { |
1137 return a, fmt.Errorf("unable to cast %#v of type %T to []string", i, i) |
1285 return a, fmt.Errorf("unable to cast %#v of type %T to []string", i, i) |
1138 } |
1286 } |
1202 |
1350 |
1203 // StringToDate attempts to parse a string into a time.Time type using a |
1351 // StringToDate attempts to parse a string into a time.Time type using a |
1204 // predefined list of formats. If no suitable format is found, an error is |
1352 // predefined list of formats. If no suitable format is found, an error is |
1205 // returned. |
1353 // returned. |
1206 func StringToDate(s string) (time.Time, error) { |
1354 func StringToDate(s string) (time.Time, error) { |
1207 return parseDateWith(s, []string{ |
1355 return parseDateWith(s, time.UTC, timeFormats) |
1208 time.RFC3339, |
1356 } |
1209 "2006-01-02T15:04:05", // iso8601 without timezone |
1357 |
1210 time.RFC1123Z, |
1358 // StringToDateInDefaultLocation casts an empty interface to a time.Time, |
1211 time.RFC1123, |
1359 // interpreting inputs without a timezone to be in the given location, |
1212 time.RFC822Z, |
1360 // or the local timezone if nil. |
1213 time.RFC822, |
1361 func StringToDateInDefaultLocation(s string, location *time.Location) (time.Time, error) { |
1214 time.RFC850, |
1362 return parseDateWith(s, location, timeFormats) |
1215 time.ANSIC, |
1363 } |
1216 time.UnixDate, |
1364 |
1217 time.RubyDate, |
1365 type timeFormatType int |
1218 "2006-01-02 15:04:05.999999999 -0700 MST", // Time.String() |
1366 |
1219 "2006-01-02", |
1367 const ( |
1220 "02 Jan 2006", |
1368 timeFormatNoTimezone timeFormatType = iota |
1221 "2006-01-02T15:04:05-0700", // RFC3339 without timezone hh:mm colon |
1369 timeFormatNamedTimezone |
1222 "2006-01-02 15:04:05 -07:00", |
1370 timeFormatNumericTimezone |
1223 "2006-01-02 15:04:05 -0700", |
1371 timeFormatNumericAndNamedTimezone |
1224 "2006-01-02 15:04:05Z07:00", // RFC3339 without T |
1372 timeFormatTimeOnly |
1225 "2006-01-02 15:04:05Z0700", // RFC3339 without T or timezone hh:mm colon |
1373 ) |
1226 "2006-01-02 15:04:05", |
1374 |
1227 time.Kitchen, |
1375 type timeFormat struct { |
1228 time.Stamp, |
1376 format string |
1229 time.StampMilli, |
1377 typ timeFormatType |
1230 time.StampMicro, |
1378 } |
1231 time.StampNano, |
1379 |
1232 }) |
1380 func (f timeFormat) hasTimezone() bool { |
1233 } |
1381 // We don't include the formats with only named timezones, see |
1234 |
1382 // https://github.com/golang/go/issues/19694#issuecomment-289103522 |
1235 func parseDateWith(s string, dates []string) (d time.Time, e error) { |
1383 return f.typ >= timeFormatNumericTimezone && f.typ <= timeFormatNumericAndNamedTimezone |
1236 for _, dateType := range dates { |
1384 } |
1237 if d, e = time.Parse(dateType, s); e == nil { |
1385 |
|
1386 var ( |
|
1387 timeFormats = []timeFormat{ |
|
1388 {time.RFC3339, timeFormatNumericTimezone}, |
|
1389 {"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone |
|
1390 {time.RFC1123Z, timeFormatNumericTimezone}, |
|
1391 {time.RFC1123, timeFormatNamedTimezone}, |
|
1392 {time.RFC822Z, timeFormatNumericTimezone}, |
|
1393 {time.RFC822, timeFormatNamedTimezone}, |
|
1394 {time.RFC850, timeFormatNamedTimezone}, |
|
1395 {"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String() |
|
1396 {"2006-01-02T15:04:05-0700", timeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon |
|
1397 {"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon |
|
1398 {"2006-01-02 15:04:05", timeFormatNoTimezone}, |
|
1399 {time.ANSIC, timeFormatNoTimezone}, |
|
1400 {time.UnixDate, timeFormatNamedTimezone}, |
|
1401 {time.RubyDate, timeFormatNumericTimezone}, |
|
1402 {"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone}, |
|
1403 {"2006-01-02", timeFormatNoTimezone}, |
|
1404 {"02 Jan 2006", timeFormatNoTimezone}, |
|
1405 {"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone}, |
|
1406 {"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone}, |
|
1407 {time.Kitchen, timeFormatTimeOnly}, |
|
1408 {time.Stamp, timeFormatTimeOnly}, |
|
1409 {time.StampMilli, timeFormatTimeOnly}, |
|
1410 {time.StampMicro, timeFormatTimeOnly}, |
|
1411 {time.StampNano, timeFormatTimeOnly}, |
|
1412 } |
|
1413 ) |
|
1414 |
|
1415 func parseDateWith(s string, location *time.Location, formats []timeFormat) (d time.Time, e error) { |
|
1416 |
|
1417 for _, format := range formats { |
|
1418 if d, e = time.Parse(format.format, s); e == nil { |
|
1419 |
|
1420 // Some time formats have a zone name, but no offset, so it gets |
|
1421 // put in that zone name (not the default one passed in to us), but |
|
1422 // without that zone's offset. So set the location manually. |
|
1423 if format.typ <= timeFormatNamedTimezone { |
|
1424 if location == nil { |
|
1425 location = time.Local |
|
1426 } |
|
1427 year, month, day := d.Date() |
|
1428 hour, min, sec := d.Clock() |
|
1429 d = time.Date(year, month, day, hour, min, sec, d.Nanosecond(), location) |
|
1430 } |
|
1431 |
1238 return |
1432 return |
1239 } |
1433 } |
1240 } |
1434 } |
1241 return d, fmt.Errorf("unable to parse date: %s", s) |
1435 return d, fmt.Errorf("unable to parse date: %s", s) |
1242 } |
1436 } |