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  }