github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/encoding/json/duration.go (about) 1 package json 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "errors" 7 "strconv" 8 "time" 9 ) 10 11 type Duration struct { 12 time.Duration 13 } 14 15 // UnmarshalJSON fulfills the encoding/json.Unmarshaler interface. 16 // It attempts to parse text as a time.Duration string. 17 // The Go documentation defines this as a possibly signed sequence of decimal 18 // numbers, each with optional fraction and a unit suffix, such as 19 // "300ms", "-1.5h" or "2h45m". 20 // Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h"). 21 // If there is no time unit, UnmarshalJSON defaults to ms. 22 func (d *Duration) UnmarshalJSON(b []byte) error { 23 if bytes.Equal(b, []byte("null")) { 24 return nil 25 } 26 27 dMS, err := strconv.ParseInt(string(b), 10, 64) 28 if err != nil { 29 // Assume this is a string instead, in which case we need to unmarshal it as a string 30 // before we try to parse it as a time.Duration. 31 var str string 32 err = json.Unmarshal(b, &str) 33 if err != nil { 34 return errors.New("invalid json.Duration") 35 } 36 37 d0, err := time.ParseDuration(str) 38 if err != nil { 39 return errors.New("invalid json.Duration") 40 } 41 if d0 < 0 { 42 return errors.New("invalid json.Duration: Duration cannot be less than 0") 43 } 44 d.Duration = d0 45 } else { 46 if dMS < 0 { 47 return errors.New("invalid json.Duration: Duration cannot be less than 0") 48 } 49 d.Duration = time.Duration(dMS) * time.Millisecond 50 } 51 52 return nil 53 } 54 55 // MarshalJSON implements json.Marshaler. 56 func (d Duration) MarshalJSON() ([]byte, error) { 57 return json.Marshal(d.Duration.Nanoseconds() / int64(time.Millisecond)) 58 }