Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4137,25 +4137,25 @@ func TestDecodeTime(t *testing.T) {
name: "time without fractional seconds", // positive integer
cborRFC3339Time: mustHexDecode("74323031332d30332d32315432303a30343a30305a"),
cborUnixTime: mustHexDecode("1a514b67b0"),
wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
wantTime: mustParseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
},
{
name: "time with fractional seconds", // float
cborRFC3339Time: mustHexDecode("7819313937302d30312d30315432313a34363a34302d30363a3030"),
cborUnixTime: mustHexDecode("fa47c35000"),
wantTime: parseTime(time.RFC3339Nano, "1970-01-01T21:46:40-06:00"),
wantTime: mustParseTime(time.RFC3339Nano, "1970-01-01T21:46:40-06:00"),
},
{
name: "time with fractional seconds", // float
cborRFC3339Time: mustHexDecode("76323031332d30332d32315432303a30343a30302e355a"),
cborUnixTime: mustHexDecode("fb41d452d9ec200000"),
wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00.5Z"),
wantTime: mustParseTime(time.RFC3339Nano, "2013-03-21T20:04:00.5Z"),
},
{
name: "time before January 1, 1970 UTC without fractional seconds", // negative integer
cborRFC3339Time: mustHexDecode("74313936392d30332d32315432303a30343a30305a"),
cborUnixTime: mustHexDecode("3a0177f2cf"),
wantTime: parseTime(time.RFC3339Nano, "1969-03-21T20:04:00Z"),
wantTime: mustParseTime(time.RFC3339Nano, "1969-03-21T20:04:00Z"),
},
}
for _, tc := range testCases {
Expand Down Expand Up @@ -4187,19 +4187,19 @@ func TestDecodeTimeWithTag(t *testing.T) {
name: "time without fractional seconds", // positive integer
cborRFC3339Time: mustHexDecode("c074323031332d30332d32315432303a30343a30305a"),
cborUnixTime: mustHexDecode("c11a514b67b0"),
wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
wantTime: mustParseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
},
{
name: "time with fractional seconds", // float
cborRFC3339Time: mustHexDecode("c076323031332d30332d32315432303a30343a30302e355a"),
cborUnixTime: mustHexDecode("c1fb41d452d9ec200000"),
wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00.5Z"),
wantTime: mustParseTime(time.RFC3339Nano, "2013-03-21T20:04:00.5Z"),
},
{
name: "time before January 1, 1970 UTC without fractional seconds", // negative integer
cborRFC3339Time: mustHexDecode("c074313936392d30332d32315432303a30343a30305a"),
cborUnixTime: mustHexDecode("c13a0177f2cf"),
wantTime: parseTime(time.RFC3339Nano, "1969-03-21T20:04:00Z"),
wantTime: mustParseTime(time.RFC3339Nano, "1969-03-21T20:04:00Z"),
},
}
for _, tc := range testCases {
Expand Down Expand Up @@ -4570,14 +4570,14 @@ func TestDecTimeTagOption(t *testing.T) {
cborRFC3339Time: mustHexDecode("74323031332d30332d32315432303a30343a30305a"),
cborUnixTime: mustHexDecode("1a514b67b0"),
decMode: timeTagIgnoredDecMode,
wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
wantTime: mustParseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
},
{
name: "not-tagged data with timeTagOptionalDecMode option",
cborRFC3339Time: mustHexDecode("74323031332d30332d32315432303a30343a30305a"),
cborUnixTime: mustHexDecode("1a514b67b0"),
decMode: timeTagOptionalDecMode,
wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
wantTime: mustParseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
},
{
name: "not-tagged data with timeTagRequiredDecMode option",
Expand All @@ -4592,29 +4592,29 @@ func TestDecTimeTagOption(t *testing.T) {
cborRFC3339Time: mustHexDecode("c074323031332d30332d32315432303a30343a30305a"),
cborUnixTime: mustHexDecode("c11a514b67b0"),
decMode: timeTagIgnoredDecMode,
wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
wantTime: mustParseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
},
{
name: "tagged data with timeTagOptionalDecMode option",
cborRFC3339Time: mustHexDecode("c074323031332d30332d32315432303a30343a30305a"),
cborUnixTime: mustHexDecode("c11a514b67b0"),
decMode: timeTagOptionalDecMode,
wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
wantTime: mustParseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
},
{
name: "tagged data with timeTagRequiredDecMode option",
cborRFC3339Time: mustHexDecode("c074323031332d30332d32315432303a30343a30305a"),
cborUnixTime: mustHexDecode("c11a514b67b0"),
decMode: timeTagRequiredDecMode,
wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
wantTime: mustParseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
},
// mis-tagged time CBOR data
{
name: "mis-tagged data with timeTagIgnoredDecMode option",
cborRFC3339Time: mustHexDecode("c8c974323031332d30332d32315432303a30343a30305a"),
cborUnixTime: mustHexDecode("c8c91a514b67b0"),
decMode: timeTagIgnoredDecMode,
wantTime: parseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
wantTime: mustParseTime(time.RFC3339Nano, "2013-03-21T20:04:00Z"),
},
{
name: "mis-tagged data with timeTagOptionalDecMode option",
Expand Down
14 changes: 11 additions & 3 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,17 +343,21 @@ const (
// non-UTC timezone then a "localtime - UTC" numeric offset will be included as specified in RFC3339.
// NOTE: User applications can avoid including the RFC3339 numeric offset by:
// - providing a time.Time value set to UTC, or
// - using the TimeUnix, TimeUnixMicro, or TimeUnixDynamic option instead of TimeRFC3339.
// - using the TimeUnix, TimeUnixMicro, TimeUnixDynamic, or TimeRFC3339NanoUTC option.
TimeRFC3339

// TimeRFC3339Nano causes time.Time to encode to a CBOR time (tag 0) with a text string content
// representing the time using 1-nanosecond precision in RFC3339 format. If the time.Time has a
// non-UTC timezone then a "localtime - UTC" numeric offset will be included as specified in RFC3339.
// NOTE: User applications can avoid including the RFC3339 numeric offset by:
// - providing a time.Time value set to UTC, or
// - using the TimeUnix, TimeUnixMicro, or TimeUnixDynamic option instead of TimeRFC3339Nano.
// - using the TimeUnix, TimeUnixMicro, TimeUnixDynamic, or TimeRFC3339NanoUTC option.
TimeRFC3339Nano

// TimeRFC3339NanoUTC causes time.Time to encode to a CBOR time (tag 0) with a text string content
// representing UTC time using nanosecond precision in RFC3339 format.
TimeRFC3339NanoUTC

maxTimeMode
)

Expand Down Expand Up @@ -1633,7 +1637,7 @@ func encodeTime(e *bytes.Buffer, em *encMode, v reflect.Value) error {
}
if em.timeTag == EncTagRequired {
tagNumber := 1
if em.time == TimeRFC3339 || em.time == TimeRFC3339Nano {
if em.time == TimeRFC3339 || em.time == TimeRFC3339Nano || em.time == TimeRFC3339NanoUTC {
tagNumber = 0
}
encodeHead(e, byte(cborTypeTag), uint64(tagNumber))
Expand Down Expand Up @@ -1661,6 +1665,10 @@ func encodeTime(e *bytes.Buffer, em *encMode, v reflect.Value) error {
s := t.Format(time.RFC3339)
return encodeString(e, em, reflect.ValueOf(s))

case TimeRFC3339NanoUTC:
s := t.UTC().Format(time.RFC3339Nano)
return encodeString(e, em, reflect.ValueOf(s))

default: // TimeRFC3339Nano
s := t.Format(time.RFC3339Nano)
return encodeString(e, em, reflect.ValueOf(s))
Expand Down
Loading
Loading