2017-08-05 20:30:20 +02:00
|
|
|
package date
|
|
|
|
|
2017-10-22 10:07:36 +02:00
|
|
|
// Copyright 2017 Microsoft Corporation
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2017-08-05 20:30:20 +02:00
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/binary"
|
|
|
|
"encoding/json"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
// unixEpoch is the moment in time that should be treated as timestamp 0.
|
|
|
|
var unixEpoch = time.Date(1970, time.January, 1, 0, 0, 0, 0, time.UTC)
|
|
|
|
|
|
|
|
// UnixTime marshals and unmarshals a time that is represented as the number
|
|
|
|
// of seconds (ignoring skip-seconds) since the Unix Epoch.
|
|
|
|
type UnixTime time.Time
|
|
|
|
|
|
|
|
// Duration returns the time as a Duration since the UnixEpoch.
|
|
|
|
func (t UnixTime) Duration() time.Duration {
|
|
|
|
return time.Time(t).Sub(unixEpoch)
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewUnixTimeFromSeconds creates a UnixTime as a number of seconds from the UnixEpoch.
|
|
|
|
func NewUnixTimeFromSeconds(seconds float64) UnixTime {
|
|
|
|
return NewUnixTimeFromDuration(time.Duration(seconds * float64(time.Second)))
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewUnixTimeFromNanoseconds creates a UnixTime as a number of nanoseconds from the UnixEpoch.
|
|
|
|
func NewUnixTimeFromNanoseconds(nanoseconds int64) UnixTime {
|
|
|
|
return NewUnixTimeFromDuration(time.Duration(nanoseconds))
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewUnixTimeFromDuration creates a UnixTime as a duration of time since the UnixEpoch.
|
|
|
|
func NewUnixTimeFromDuration(dur time.Duration) UnixTime {
|
|
|
|
return UnixTime(unixEpoch.Add(dur))
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnixEpoch retreives the moment considered the Unix Epoch. I.e. The time represented by '0'
|
|
|
|
func UnixEpoch() time.Time {
|
|
|
|
return unixEpoch
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalJSON preserves the UnixTime as a JSON number conforming to Unix Timestamp requirements.
|
|
|
|
// (i.e. the number of seconds since midnight January 1st, 1970 not considering leap seconds.)
|
|
|
|
func (t UnixTime) MarshalJSON() ([]byte, error) {
|
|
|
|
buffer := &bytes.Buffer{}
|
|
|
|
enc := json.NewEncoder(buffer)
|
|
|
|
err := enc.Encode(float64(time.Time(t).UnixNano()) / 1e9)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return buffer.Bytes(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalJSON reconstitures a UnixTime saved as a JSON number of the number of seconds since
|
|
|
|
// midnight January 1st, 1970.
|
|
|
|
func (t *UnixTime) UnmarshalJSON(text []byte) error {
|
|
|
|
dec := json.NewDecoder(bytes.NewReader(text))
|
|
|
|
|
|
|
|
var secondsSinceEpoch float64
|
|
|
|
if err := dec.Decode(&secondsSinceEpoch); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
*t = NewUnixTimeFromSeconds(secondsSinceEpoch)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalText stores the number of seconds since the Unix Epoch as a textual floating point number.
|
|
|
|
func (t UnixTime) MarshalText() ([]byte, error) {
|
|
|
|
cast := time.Time(t)
|
|
|
|
return cast.MarshalText()
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalText populates a UnixTime with a value stored textually as a floating point number of seconds since the Unix Epoch.
|
|
|
|
func (t *UnixTime) UnmarshalText(raw []byte) error {
|
|
|
|
var unmarshaled time.Time
|
|
|
|
|
|
|
|
if err := unmarshaled.UnmarshalText(raw); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
*t = UnixTime(unmarshaled)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalBinary converts a UnixTime into a binary.LittleEndian float64 of nanoseconds since the epoch.
|
|
|
|
func (t UnixTime) MarshalBinary() ([]byte, error) {
|
|
|
|
buf := &bytes.Buffer{}
|
|
|
|
|
|
|
|
payload := int64(t.Duration())
|
|
|
|
|
|
|
|
if err := binary.Write(buf, binary.LittleEndian, &payload); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf.Bytes(), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalBinary converts a from a binary.LittleEndian float64 of nanoseconds since the epoch into a UnixTime.
|
|
|
|
func (t *UnixTime) UnmarshalBinary(raw []byte) error {
|
|
|
|
var nanosecondsSinceEpoch int64
|
|
|
|
|
|
|
|
if err := binary.Read(bytes.NewReader(raw), binary.LittleEndian, &nanosecondsSinceEpoch); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
*t = NewUnixTimeFromNanoseconds(nanosecondsSinceEpoch)
|
|
|
|
return nil
|
|
|
|
}
|