github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/timex/jsontime.go (about) 1 package timex 2 3 import ( 4 "errors" 5 "strconv" 6 "strings" 7 "time" 8 9 perrors "github.com/pkg/errors" 10 ) 11 12 // ErrUnknownTimeFormat defines the error type for unknown time format. 13 var ErrUnknownTimeFormat = errors.New("unknown errors time format") 14 15 // JSONTime defines a time.Time that can be used in struct tag for JSON unmarshalling. 16 type JSONTime time.Time 17 18 // UnmarshalJSON unmarshals bytes to JSONTime. 19 func (t *JSONTime) UnmarshalJSON(b []byte) error { 20 v, _ := TryUnQuoted(string(b)) 21 if v == "" { 22 return nil 23 } 24 25 // 首先看是否是数字,表示毫秒数或者纳秒数 26 if p, err := strconv.ParseInt(v, 10, 64); err == nil { 27 *t = JSONTime(time.Unix(0, p*1000000)) // milliseconds range, 1 millis = 1000,000 nanos) 28 return nil 29 } 30 31 v = strings.ReplaceAll(v, "/", "-") 32 v = strings.ReplaceAll(v, ",", ".") 33 v = strings.ReplaceAll(v, "T", " ") 34 35 parser := func(layout, value string) (time.Time, error) { 36 return time.ParseInLocation(layout, value, time.Local) 37 } 38 39 if strings.Contains(v, "Z") { 40 if strings.HasSuffix(v, "Z") { 41 v = strings.TrimSuffix(v, "Z") 42 } 43 parser = func(layout, value string) (time.Time, error) { 44 return time.Parse(layout, value) 45 } 46 } 47 48 for _, f := range []string{ 49 "2006-01-02 15:04:05.999999999Z07:00", // time.RFC3339Nano, 50 "2006-01-02 15:04:05Z07:00", // time.RFC3339, 51 "2006-01-02 15:04:05.000000", 52 "2006-01-02 15:04:05.000", 53 } { 54 if tt, err := parser(f, v); err == nil { 55 *t = JSONTime(tt) 56 return nil 57 } 58 } 59 60 return perrors.Wrapf(ErrUnknownTimeFormat, "value %s has unknown time format"+v) 61 } 62 63 // TryUnQuoted tries to unquote string. 64 func TryUnQuoted(v string) (string, bool) { 65 vlen := len(v) 66 yes := vlen >= 2 && v[0] == '"' && v[vlen-1] == '"' 67 if !yes { 68 return v, false 69 } 70 71 return v[1 : vlen-1], true 72 }