1package cbor
2
3import (
4	"time"
5)
6
7func appendIntegerTimestamp(dst []byte, t time.Time) []byte {
8	major := majorTypeTags
9	minor := additionalTypeTimestamp
10	dst = append(dst, byte(major|minor))
11	secs := t.Unix()
12	var val uint64
13	if secs < 0 {
14		major = majorTypeNegativeInt
15		val = uint64(-secs - 1)
16	} else {
17		major = majorTypeUnsignedInt
18		val = uint64(secs)
19	}
20	dst = appendCborTypePrefix(dst, major, uint64(val))
21	return dst
22}
23
24func (e Encoder) appendFloatTimestamp(dst []byte, t time.Time) []byte {
25	major := majorTypeTags
26	minor := additionalTypeTimestamp
27	dst = append(dst, byte(major|minor))
28	secs := t.Unix()
29	nanos := t.Nanosecond()
30	var val float64
31	val = float64(secs)*1.0 + float64(nanos)*1E-9
32	return e.AppendFloat64(dst, val)
33}
34
35// AppendTime encodes and adds a timestamp to the dst byte array.
36func (e Encoder) AppendTime(dst []byte, t time.Time, unused string) []byte {
37	utc := t.UTC()
38	if utc.Nanosecond() == 0 {
39		return appendIntegerTimestamp(dst, utc)
40	}
41	return e.appendFloatTimestamp(dst, utc)
42}
43
44// AppendTimes encodes and adds an array of timestamps to the dst byte array.
45func (e Encoder) AppendTimes(dst []byte, vals []time.Time, unused string) []byte {
46	major := majorTypeArray
47	l := len(vals)
48	if l == 0 {
49		return e.AppendArrayEnd(e.AppendArrayStart(dst))
50	}
51	if l <= additionalMax {
52		lb := byte(l)
53		dst = append(dst, byte(major|lb))
54	} else {
55		dst = appendCborTypePrefix(dst, major, uint64(l))
56	}
57
58	for _, t := range vals {
59		dst = e.AppendTime(dst, t, unused)
60	}
61	return dst
62}
63
64// AppendDuration encodes and adds a duration to the dst byte array.
65// useInt field indicates whether to store the duration as seconds (integer) or
66// as seconds+nanoseconds (float).
67func (e Encoder) AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool) []byte {
68	if useInt {
69		return e.AppendInt64(dst, int64(d/unit))
70	}
71	return e.AppendFloat64(dst, float64(d)/float64(unit))
72}
73
74// AppendDurations encodes and adds an array of durations to the dst byte array.
75// useInt field indicates whether to store the duration as seconds (integer) or
76// as seconds+nanoseconds (float).
77func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool) []byte {
78	major := majorTypeArray
79	l := len(vals)
80	if l == 0 {
81		return e.AppendArrayEnd(e.AppendArrayStart(dst))
82	}
83	if l <= additionalMax {
84		lb := byte(l)
85		dst = append(dst, byte(major|lb))
86	} else {
87		dst = appendCborTypePrefix(dst, major, uint64(l))
88	}
89	for _, d := range vals {
90		dst = e.AppendDuration(dst, d, unit, useInt)
91	}
92	return dst
93}
94