diff --git a/timeutils/utils.go b/timeutils/utils.go index 6af16a1..8437f12 100644 --- a/timeutils/utils.go +++ b/timeutils/utils.go @@ -6,10 +6,17 @@ import ( "time" ) -// GetTimestamp tries to parse given string as RFC3339 time -// or Unix timestamp (with seconds precision), if successful -//returns a Unix timestamp as string otherwise returns value back. -func GetTimestamp(value string) string { +// GetTimestamp tries to parse given string as golang duration, +// then RFC3339 time and finally as a Unix timestamp. If +// any of these were successful, it returns a Unix timestamp +// as string otherwise returns the given value back. +// In case of duration input, the returned timestamp is computed +// as the given reference time minus the amount of the duration. +func GetTimestamp(value string, reference time.Time) string { + if d, err := time.ParseDuration(value); value != "0" && err == nil { + return strconv.FormatInt(reference.Add(-d).Unix(), 10) + } + var format string if strings.Contains(value, ".") { format = time.RFC3339Nano diff --git a/timeutils/utils_test.go b/timeutils/utils_test.go index 1d724fb..f71dcb5 100644 --- a/timeutils/utils_test.go +++ b/timeutils/utils_test.go @@ -1,10 +1,13 @@ package timeutils import ( + "fmt" "testing" + "time" ) func TestGetTimestamp(t *testing.T) { + now := time.Now() cases := []struct{ in, expected string }{ {"0", "-62167305600"}, // 0 gets parsed year 0 @@ -23,12 +26,17 @@ func TestGetTimestamp(t *testing.T) { // unix timestamps returned as is {"1136073600", "1136073600"}, + // Durations + {"1m", fmt.Sprintf("%d", now.Add(-1*time.Minute).Unix())}, + {"1.5h", fmt.Sprintf("%d", now.Add(-90*time.Minute).Unix())}, + {"1h30m", fmt.Sprintf("%d", now.Add(-90*time.Minute).Unix())}, + // String fallback {"invalid", "invalid"}, } for _, c := range cases { - o := GetTimestamp(c.in) + o := GetTimestamp(c.in, now) if o != c.expected { t.Fatalf("wrong value for '%s'. expected:'%s' got:'%s'", c.in, c.expected, o) }