99 lines
1.9 KiB
Go
99 lines
1.9 KiB
Go
package query
|
|
|
|
import (
|
|
"math"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
MinTime = Time{
|
|
Absolute: time.Unix(0, math.MinInt64),
|
|
}
|
|
MaxTime = Time{
|
|
Absolute: time.Unix(0, math.MaxInt64),
|
|
}
|
|
Now = Time{
|
|
IsRelative: true,
|
|
}
|
|
)
|
|
|
|
// Time represents either a relavite or absolute time.
|
|
// If Time is its zero value then it represents a time.Time{}.
|
|
// To represent the now time you must set IsRelative to true.
|
|
type Time struct {
|
|
IsRelative bool
|
|
Relative time.Duration
|
|
Absolute time.Time
|
|
}
|
|
|
|
// Time returns the time specified relative to now.
|
|
func (t Time) Time(now time.Time) time.Time {
|
|
if t.IsRelative {
|
|
return now.Add(t.Relative)
|
|
}
|
|
return t.Absolute
|
|
}
|
|
|
|
func (t Time) IsZero() bool {
|
|
return !t.IsRelative && t.Absolute.IsZero()
|
|
}
|
|
|
|
func (t *Time) UnmarshalText(data []byte) error {
|
|
if len(data) == 0 {
|
|
t.Absolute = time.Time{}
|
|
t.Relative = 0
|
|
t.IsRelative = false
|
|
return nil
|
|
}
|
|
|
|
str := string(data)
|
|
if str == "now" {
|
|
t.Relative = 0
|
|
t.Absolute = time.Time{}
|
|
t.IsRelative = true
|
|
return nil
|
|
}
|
|
d, err := time.ParseDuration(str)
|
|
if err == nil {
|
|
t.Relative = d
|
|
t.Absolute = time.Time{}
|
|
t.IsRelative = true
|
|
return nil
|
|
}
|
|
t.IsRelative = false
|
|
t.Relative = 0
|
|
t.Absolute, err = time.Parse(time.RFC3339Nano, str)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
t.Absolute = t.Absolute.UTC()
|
|
return nil
|
|
}
|
|
|
|
func (t Time) MarshalText() ([]byte, error) {
|
|
if t.IsRelative {
|
|
if t.Relative == 0 {
|
|
return []byte("now"), nil
|
|
}
|
|
return []byte(t.Relative.String()), nil
|
|
}
|
|
return []byte(t.Absolute.Format(time.RFC3339Nano)), nil
|
|
}
|
|
|
|
// Duration is a marshalable duration type.
|
|
//TODO make this the real duration parsing not just time.ParseDuration
|
|
type Duration time.Duration
|
|
|
|
func (d *Duration) UnmarshalText(data []byte) error {
|
|
dur, err := time.ParseDuration(string(data))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*d = Duration(dur)
|
|
return nil
|
|
}
|
|
|
|
func (d Duration) MarshalText() ([]byte, error) {
|
|
return []byte(time.Duration(d).String()), nil
|
|
}
|