87 lines
2.5 KiB
Go
87 lines
2.5 KiB
Go
package format
|
|
|
|
import (
|
|
"math"
|
|
"time"
|
|
)
|
|
|
|
const fractionDivisor = 0x10000
|
|
|
|
// Timestamp represents a point in time using fixed resolution.
|
|
type Timestamp struct {
|
|
Second uint8
|
|
Fraction uint16
|
|
}
|
|
|
|
// TimestampLimit returns the highest possible timestamp value.
|
|
func TimestampLimit() Timestamp {
|
|
return Timestamp{
|
|
Second: math.MaxUint8,
|
|
Fraction: math.MaxUint16,
|
|
}
|
|
}
|
|
|
|
// TimestampFromSeconds creates a timestamp instance from given floating point value.
|
|
func TimestampFromSeconds(value float32) Timestamp {
|
|
second := uint8(value)
|
|
return Timestamp{
|
|
Second: second,
|
|
Fraction: uint16((value - float32(second)) * fractionDivisor),
|
|
}
|
|
}
|
|
|
|
// TimestampFromDuration creates a timestamp instance from given duration value.
|
|
func TimestampFromDuration(d time.Duration) Timestamp {
|
|
limit := TimestampLimit()
|
|
if d >= limit.ToDuration() {
|
|
return limit
|
|
}
|
|
return Timestamp{
|
|
Second: uint8(d / time.Second),
|
|
Fraction: uint16(((d - time.Second) * fractionDivisor) / time.Second),
|
|
}
|
|
}
|
|
|
|
// ToDuration returns the equivalent duration for this timestamp.
|
|
func (ts Timestamp) ToDuration() time.Duration {
|
|
return (time.Duration(ts.Second) * time.Second) + (time.Duration(ts.Fraction)*time.Second)/fractionDivisor
|
|
}
|
|
|
|
// IsAfter returns true if this timestamp is later than the given one.
|
|
func (ts Timestamp) IsAfter(other Timestamp) bool {
|
|
return (ts.Second > other.Second) || ((ts.Second == other.Second) && (ts.Fraction > other.Fraction))
|
|
}
|
|
|
|
// IsBefore returns true if this timestamp is before the given one.
|
|
func (ts Timestamp) IsBefore(other Timestamp) bool {
|
|
return (ts.Second < other.Second) || ((ts.Second == other.Second) && (ts.Fraction < other.Fraction))
|
|
}
|
|
|
|
// Plus returns a timestamp with the given one added to the current one.
|
|
// The result is saturated if the addition is larger than the timestamp can hold.
|
|
func (ts Timestamp) Plus(other Timestamp) Timestamp {
|
|
return TimestampFromDuration(ts.ToDuration() + other.ToDuration())
|
|
}
|
|
|
|
// Minus returns a timestamp with given one removed from the current one.
|
|
// The result is clipped to 0 if subtraction would result in a negative number.
|
|
func (ts Timestamp) Minus(other Timestamp) Timestamp {
|
|
otherLinear := other.toLinear()
|
|
tsLinear := ts.toLinear()
|
|
if otherLinear >= tsLinear {
|
|
return timestampFromLinear(0)
|
|
}
|
|
return timestampFromLinear(tsLinear - otherLinear)
|
|
}
|
|
|
|
func (ts Timestamp) toLinear() uint32 {
|
|
return uint32(ts.Second)<<16 + uint32(ts.Fraction)
|
|
}
|
|
|
|
func timestampFromLinear(value uint32) Timestamp {
|
|
return Timestamp{
|
|
Second: uint8(value >> 16),
|
|
Fraction: uint16(value),
|
|
}
|
|
}
|