// these methods does not change the actual instant it represents, only the time
// zone in which to interpret it.
//
-// Representations of a Time value saved by the [Time.GobEncode], [Time.MarshalBinary],
-// [Time.MarshalJSON], and [Time.MarshalText] methods store the [Time.Location]'s offset, but not
-// the location name. They therefore lose information about Daylight Saving Time.
+// Representations of a Time value saved by the [Time.GobEncode], [Time.MarshalBinary], [Time.AppendBinary],
+// [Time.MarshalJSON], [Time.MarshalText] and [Time.AppendText] methods store the [Time.Location]'s offset,
+// but not the location name. They therefore lose information about Daylight Saving Time.
//
// In addition to the required “wall clock” reading, a Time may contain an optional
// reading of the current process's monotonic clock, to provide additional precision
timeBinaryVersionV2 // For LMT only
)
-// MarshalBinary implements the encoding.BinaryMarshaler interface.
-func (t Time) MarshalBinary() ([]byte, error) {
+// AppendBinary implements the [encoding.BinaryAppender] interface.
+func (t Time) AppendBinary(b []byte) ([]byte, error) {
var offsetMin int16 // minutes east of UTC. -1 is UTC.
var offsetSec int8
version := timeBinaryVersionV1
offset /= 60
if offset < -32768 || offset == -1 || offset > 32767 {
- return nil, errors.New("Time.MarshalBinary: unexpected zone offset")
+ return b, errors.New("Time.MarshalBinary: unexpected zone offset")
}
offsetMin = int16(offset)
}
sec := t.sec()
nsec := t.nsec()
- enc := []byte{
- version, // byte 0 : version
- byte(sec >> 56), // bytes 1-8: seconds
- byte(sec >> 48),
- byte(sec >> 40),
- byte(sec >> 32),
- byte(sec >> 24),
- byte(sec >> 16),
- byte(sec >> 8),
+ b = append(b,
+ version, // byte 0 : version
+ byte(sec>>56), // bytes 1-8: seconds
+ byte(sec>>48),
+ byte(sec>>40),
+ byte(sec>>32),
+ byte(sec>>24),
+ byte(sec>>16),
+ byte(sec>>8),
byte(sec),
- byte(nsec >> 24), // bytes 9-12: nanoseconds
- byte(nsec >> 16),
- byte(nsec >> 8),
+ byte(nsec>>24), // bytes 9-12: nanoseconds
+ byte(nsec>>16),
+ byte(nsec>>8),
byte(nsec),
- byte(offsetMin >> 8), // bytes 13-14: zone offset in minutes
+ byte(offsetMin>>8), // bytes 13-14: zone offset in minutes
byte(offsetMin),
- }
+ )
if version == timeBinaryVersionV2 {
- enc = append(enc, byte(offsetSec))
+ b = append(b, byte(offsetSec))
}
+ return b, nil
+}
- return enc, nil
+// MarshalBinary implements the [encoding.BinaryMarshaler] interface.
+func (t Time) MarshalBinary() ([]byte, error) {
+ b, err := t.AppendBinary(make([]byte, 0, 16))
+ if err != nil {
+ return nil, err
+ }
+ return b, nil
}
-// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
+// UnmarshalBinary implements the [encoding.BinaryUnmarshaler] interface.
func (t *Time) UnmarshalBinary(data []byte) error {
buf := data
if len(buf) == 0 {
return err
}
-// MarshalText implements the [encoding.TextMarshaler] interface.
+// AppendText implements the [encoding.TextAppender] interface.
// The time is formatted in RFC 3339 format with sub-second precision.
// If the timestamp cannot be represented as valid RFC 3339
-// (e.g., the year is out of range), then an error is reported.
-func (t Time) MarshalText() ([]byte, error) {
- b := make([]byte, 0, len(RFC3339Nano))
+// (e.g., the year is out of range), then an error is returned.
+func (t Time) AppendText(b []byte) ([]byte, error) {
b, err := t.appendStrictRFC3339(b)
if err != nil {
return nil, errors.New("Time.MarshalText: " + err.Error())
return b, nil
}
+// MarshalText implements the [encoding.TextMarshaler] interface. The output
+// matches that of calling the [Time.AppendText] method.
+//
+// See [Time.AppendText] for more information.
+func (t Time) MarshalText() ([]byte, error) {
+ return t.AppendText(make([]byte, 0, len(RFC3339Nano)))
+}
+
// UnmarshalText implements the [encoding.TextUnmarshaler] interface.
// The time must be in the RFC 3339 format.
func (t *Time) UnmarshalText(data []byte) error {
{"UnixMilli", func(t1, t2 Time) bool { return t1.UnixMilli() == t2.UnixMilli() }},
{"UnixMicro", func(t1, t2 Time) bool { return t1.UnixMicro() == t2.UnixMicro() }},
+ {"AppendBinary", func(t1, t2 Time) bool {
+ buf1 := make([]byte, 4, 32)
+ buf2 := make([]byte, 4, 32)
+ a1, b1 := t1.AppendBinary(buf1)
+ a2, b2 := t2.AppendBinary(buf2)
+ return bytes.Equal(a1[4:], a2[4:]) && b1 == b2
+ }},
{"MarshalBinary", func(t1, t2 Time) bool {
a1, b1 := t1.MarshalBinary()
a2, b2 := t2.MarshalBinary()
a2, b2 := t2.MarshalJSON()
return bytes.Equal(a1, a2) && b1 == b2
}},
+ {"AppendText", func(t1, t2 Time) bool {
+ maxCap := len(RFC3339Nano) + 4
+ buf1 := make([]byte, 4, maxCap)
+ buf2 := make([]byte, 4, maxCap)
+ a1, b1 := t1.AppendText(buf1)
+ a2, b2 := t2.AppendText(buf2)
+ return bytes.Equal(a1[4:], a2[4:]) && b1 == b2
+ }},
{"MarshalText", func(t1, t2 Time) bool {
a1, b1 := t1.MarshalText()
a2, b2 := t2.MarshalText()
}
}
+func BenchmarkMarshalBinary(b *testing.B) {
+ t := Now()
+ for i := 0; i < b.N; i++ {
+ t.MarshalBinary()
+ }
+}
+
func BenchmarkParse(b *testing.B) {
for i := 0; i < b.N; i++ {
Parse(ANSIC, "Mon Jan 2 15:04:05 2006")