diff --git a/http/bucket_test.go b/http/bucket_test.go index 4c0cb5c740..5eeafe7314 100644 --- a/http/bucket_test.go +++ b/http/bucket_test.go @@ -516,7 +516,7 @@ func TestService_handlePatchBucket(t *testing.T) { "id": "020f755c3c082000", "organizationID": "020f755c3c082000", "name": "example", - "retentionPeriod": "1u" + "retentionPeriod": "1234ns" } `, }, diff --git a/http/duration.go b/http/duration.go index 56bb0f756e..3b2dc0acef 100644 --- a/http/duration.go +++ b/http/duration.go @@ -61,6 +61,13 @@ func ParseDuration(s string) (time.Duration, error) { // Extract the unit of measure. unit = string(a[i]) switch a[i] { + case 'n': + d += time.Duration(n) * time.Nanosecond + if i+1 < len(a) && a[i+1] == 's' { + unit = string(a[i : i+2]) + i += 2 + continue + } case 'u', 'µ': d += time.Duration(n) * time.Microsecond if i+1 < len(a) && a[i+1] == 's' { @@ -118,6 +125,8 @@ func FormatDuration(d time.Duration) string { return "0s" } else if d%(365*24*time.Hour) == 0 { return fmt.Sprintf("%dy", d/(365*24*time.Hour)) + } else if d%(30*24*time.Hour) == 0 { + return fmt.Sprintf("%dmo", d/(30*24*time.Hour)) } else if d%(7*24*time.Hour) == 0 { return fmt.Sprintf("%dw", d/(7*24*time.Hour)) } else if d%(24*time.Hour) == 0 { @@ -130,11 +139,10 @@ func FormatDuration(d time.Duration) string { return fmt.Sprintf("%ds", d/time.Second) } else if d%time.Millisecond == 0 { return fmt.Sprintf("%dms", d/time.Millisecond) + } else if d%time.Microsecond == 0 { + return fmt.Sprintf("%dus", d/time.Microsecond) } - // Although we accept both "u" and "µ" when reading microsecond durations, - // we output with "u", which can be represented in 1 byte, - // instead of "µ", which requires 2 bytes. - return fmt.Sprintf("%du", d/time.Microsecond) + return fmt.Sprintf("%dns", d/time.Nanosecond) } // split splits a string into a slice of runes. diff --git a/http/duration_test.go b/http/duration_test.go index 1d23cd074f..5e5cbf33f3 100644 --- a/http/duration_test.go +++ b/http/duration_test.go @@ -13,6 +13,8 @@ func TestParseDuration(t *testing.T) { want time.Duration wantErr bool }{ + {s: `10n`, want: 10 * time.Nanosecond}, + {s: `10ns`, want: 10 * time.Nanosecond}, {s: `10u`, want: 10 * time.Microsecond}, {s: `10µ`, want: 10 * time.Microsecond}, {s: `10us`, want: 10 * time.Microsecond}, @@ -32,6 +34,7 @@ func TestParseDuration(t *testing.T) { {s: ``, wantErr: true}, {s: `3`, wantErr: true}, {s: `3mm`, wantErr: true}, + {s: `3nm`, wantErr: true}, {s: `1000`, wantErr: true}, {s: `w`, wantErr: true}, {s: `ms`, wantErr: true}, @@ -60,14 +63,16 @@ func TestFormatDuration(t *testing.T) { d time.Duration want string }{ - {d: 3 * time.Microsecond, want: `3u`}, - {d: 1001 * time.Microsecond, want: `1001u`}, + {d: 3 * time.Nanosecond, want: `3ns`}, + {d: 3 * time.Microsecond, want: `3us`}, + {d: 1001 * time.Microsecond, want: `1001us`}, {d: 15 * time.Millisecond, want: `15ms`}, {d: 100 * time.Second, want: `100s`}, {d: 2 * time.Minute, want: `2m`}, {d: 2 * time.Hour, want: `2h`}, {d: 2 * 24 * time.Hour, want: `2d`}, {d: 2 * 7 * 24 * time.Hour, want: `2w`}, + {d: 2 * 30 * 24 * time.Hour, want: `2mo`}, {d: 2 * 365 * 24 * time.Hour, want: `2y`}, }