Browse Source

tstime: add ParseDuration helper function

More expressive than time.ParseDuration, also accepting d (days) and
w (weeks) literals.

Signed-off-by: Mihai Parparita <[email protected]>
Mihai Parparita 3 years ago
parent
commit
9214b293e3
2 changed files with 47 additions and 0 deletions
  1. 24 0
      tstime/tstime.go
  2. 23 0
      tstime/tstime_test.go

+ 24 - 0
tstime/tstime.go

@@ -8,6 +8,8 @@ package tstime
 import (
 	"errors"
 	"fmt"
+	"strconv"
+	"strings"
 	"sync"
 	"time"
 
@@ -141,3 +143,25 @@ func Parse3339(s string) (time.Time, error) {
 func Parse3339B(b []byte) (time.Time, error) {
 	return parse3339m(mem.B(b))
 }
+
+// ParseDuration is more expressive than time.ParseDuration, also accepting d
+// (days) and w (weeks) literals.
+func ParseDuration(s string) (time.Duration, error) {
+	for {
+		end := strings.IndexAny(s, "dw")
+		if end < 0 {
+			break
+		}
+		start := end - (len(s[:end]) - len(strings.TrimRight(s[:end], "012345789")))
+		n, err := strconv.Atoi(s[start:end])
+		if err != nil {
+			return 0, err
+		}
+		hours := 24
+		if s[end] == 'w' {
+			hours *= 7
+		}
+		s = s[:start] + s[end+1:] + strconv.Itoa(n*hours) + "h"
+	}
+	return time.ParseDuration(s)
+}

+ 23 - 0
tstime/tstime_test.go

@@ -102,6 +102,29 @@ func TestParseInt(t *testing.T) {
 	}
 }
 
+func TestParseDuration(t *testing.T) {
+	tests := []struct {
+		in   string
+		want time.Duration
+	}{
+		{"1h", time.Hour},
+		{"1d", 24 * time.Hour},
+		{"1d1d", 48 * time.Hour},
+		{"1h1d", 25 * time.Hour},
+		{"1d1h", 25 * time.Hour},
+		{"1w", 7 * 24 * time.Hour},
+		{"1w1d1h", 8*24*time.Hour + time.Hour},
+		{"1w1d1h", 8*24*time.Hour + time.Hour},
+		{"1y", 0},
+		{"", 0},
+	}
+	for _, tt := range tests {
+		if got, _ := ParseDuration(tt.in); got != tt.want {
+			t.Errorf("ParseDuration(%q) = %d; want %d", tt.in, got, tt.want)
+		}
+	}
+}
+
 func BenchmarkGoParse3339(b *testing.B) {
 	run := func(in string) func(*testing.B) {
 		return func(b *testing.B) {