diff --git a/model/time.go b/model/time.go index 0854753f..4d572b8a 100644 --- a/model/time.go +++ b/model/time.go @@ -164,6 +164,47 @@ func (t *Time) UnmarshalJSON(b []byte) error { // This type should not propagate beyond the scope of input/output processing. type Duration time.Duration +// Common durations. Day and Week are included because ParseDuration supports +// those units (unlike the standard time package). +// +// To count the number of units in a Duration, divide: +// +// second := model.Second +// fmt.Print(int64(second/model.Millisecond)) // prints 1000 +// +// To convert an integer number of units to a Duration, multiply: +// +// seconds := 10 +// fmt.Print(model.Duration(seconds)*model.Second) // prints 10s +const ( + Nanosecond Duration = 1 + Microsecond = 1000 * Nanosecond + Millisecond = 1000 * Microsecond + Second = 1000 * Millisecond + Minute = 60 * Second + Hour = 60 * Minute + Day = 24 * Hour + Week = 7 * Day +) + +// Nanoseconds returns the duration as an integer nanosecond count. +func (d Duration) Nanoseconds() int64 { return time.Duration(d).Nanoseconds() } + +// Microseconds returns the duration as an integer microsecond count. +func (d Duration) Microseconds() int64 { return time.Duration(d).Microseconds() } + +// Milliseconds returns the duration as an integer millisecond count. +func (d Duration) Milliseconds() int64 { return time.Duration(d).Milliseconds() } + +// Seconds returns the duration as a floating point number of seconds. +func (d Duration) Seconds() float64 { return time.Duration(d).Seconds() } + +// Minutes returns the duration as a floating point number of minutes. +func (d Duration) Minutes() float64 { return time.Duration(d).Minutes() } + +// Hours returns the duration as a floating point number of hours. +func (d Duration) Hours() float64 { return time.Duration(d).Hours() } + // Set implements pflag/flag.Value. func (d *Duration) Set(s string) error { var err error diff --git a/model/time_test.go b/model/time_test.go index 7633b46e..16445400 100644 --- a/model/time_test.go +++ b/model/time_test.go @@ -67,6 +67,42 @@ func TestDuration(t *testing.T) { require.Equalf(t, delta, duration, "Expected %s to be equal to %s", delta, duration) } +func TestDurationConstants(t *testing.T) { + // require.Equal(expected, actual) — expected is the reference time.Duration cast. + require.Equal(t, Nanosecond, Duration(time.Nanosecond)) + require.Equal(t, Microsecond, Duration(time.Microsecond)) + require.Equal(t, Millisecond, Duration(time.Millisecond)) + require.Equal(t, Second, Duration(time.Second)) + require.Equal(t, Minute, Duration(time.Minute)) + require.Equal(t, Hour, Duration(time.Hour)) + require.Equal(t, Day, Duration(24*time.Hour)) + require.Equal(t, Week, Duration(7*24*time.Hour)) + + // Typical usage from the issue: multiply integers by model constants. + require.Equal(t, 15*Day, Duration(15*24*time.Hour)) + require.Equal(t, 5000*Millisecond, Duration(5000*time.Millisecond)) +} + +func TestDurationMethods(t *testing.T) { + d := 2*Hour + 30*Minute + 15*Second + 250*Millisecond + td := time.Duration(d) + + require.Equal(t, td.Nanoseconds(), d.Nanoseconds()) + require.Equal(t, td.Microseconds(), d.Microseconds()) + require.Equal(t, td.Milliseconds(), d.Milliseconds()) + require.Equal(t, td.Seconds(), d.Seconds()) + require.Equal(t, td.Minutes(), d.Minutes()) + require.Equal(t, td.Hours(), d.Hours()) + + require.Equal(t, int64(2*60*60*1000+30*60*1000+15*1000+250), d.Milliseconds()) + require.Equal(t, int64(1500), (1500 * Microsecond).Microseconds()) + require.Equal(t, int64(1500), (1500 * Nanosecond).Nanoseconds()) + + // Negative durations. + require.Equal(t, int64(-1500), (-1500 * Millisecond).Milliseconds()) + require.Equal(t, -1.5, (-1500 * Millisecond).Seconds()) +} + func TestParseDuration(t *testing.T) { type testCase struct { in string