Files
go-tyme/rfc3339.go

80 lines
2.1 KiB
Go

package tyme
import (
"strconv"
"time"
"gopkg.in/yaml.v3"
)
// TimeRFC3339 is a wrapper around time.Time that implements JSON/YAML
// marshaling/unmarshaling interfaces. As opposed to Time, only RFC 3339
// formatted input is accepted when unmarshaling.
//
// It marshals to a string in RFC 3339 format, with sub-second precision added
// if present.
//
// It will only unmarshal from a string in RFC 3339 format. Any other format
// will cause an unmarshaling error.
type TimeRFC3339 time.Time
// RFC3339NanoJSON is the time.RFC3339Nano format with double quotes around it.
const RFC3339NanoJSON = `"` + time.RFC3339Nano + `"`
// MarshalJSON implements the json.Marshaler interface, and formats the time as
// a JSON string in RFC 3339 format, with sub-second precision added if
// present.
func (t TimeRFC3339) MarshalJSON() ([]byte, error) {
return []byte(time.Time(t).Format(RFC3339NanoJSON)), nil
}
// UnmarshalJSON implements the json.Unmarshaler interface, and parses a
// JSON string in RFC 3339 format, with sub-second precision added if
// present.
func (t *TimeRFC3339) UnmarshalJSON(b []byte) error {
s, err := strconv.Unquote(string(b))
if err != nil {
return err
}
nt, err := time.Parse(time.RFC3339Nano, s)
if err != nil {
return err
}
*t = TimeRFC3339(nt)
return err
}
// MarshalYAML implements the yaml.Marshaler interface, and formats the time as
// a YAML timestamp type in RFC 3339 string format, with sub-second precision
// added if present.
func (t TimeRFC3339) MarshalYAML() (interface{}, error) {
return time.Time(t), nil
}
// UnmarshalYAML implements the yaml.Unmarshaler interface, and parses a YAML
// timestamp or string formatted according to RFC 3339, with sub-second
// precision added if present.
func (t *TimeRFC3339) UnmarshalYAML(node *yaml.Node) error {
var nt time.Time
var err error
switch node.Tag {
case "!!timestamp":
err = node.Decode(&nt)
case "!!str":
nt, err = time.Parse(time.RFC3339Nano, node.Value)
default:
return &yaml.TypeError{Errors: []string{"invalid time format"}}
}
if err != nil {
return err
}
*t = TimeRFC3339(nt)
return nil
}