Skip to content

Instantly share code, notes, and snippets.

@wttw
Created October 1, 2018 17:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wttw/cecd90e4b793ad1bee2f95fb79221321 to your computer and use it in GitHub Desktop.
Save wttw/cecd90e4b793ad1bee2f95fb79221321 to your computer and use it in GitHub Desktop.
// Package friendly maps user-friendly strings to time.Duration
package friendly
import (
"fmt"
"regexp"
"strconv"
"strings"
"time"
)
var durationUnitsRe = regexp.MustCompile(`([+-]?[0-9.]+)\s*((?:m[io]|[ywhsd])[a-z]*)`)
// ToDuration converts a string to a time.Duration
func ToDuration(s string) (time.Duration, error) {
var ret int64
parts := durationUnitsRe.FindAllStringSubmatch(strings.ToLower(s), -1)
for _, part := range parts {
num, err := strconv.ParseFloat(part[1], 64)
if err != nil {
return 0, fmt.Errorf("Invalid 8601 duration '%s': %s", s, err.Error())
}
unit := part[2]
switch unit[:1] {
case "m":
if strings.HasPrefix("minutes", unit) {
ret = ret + int64(num*(60.0*1000000000.0))
} else if strings.HasPrefix("months", unit) {
ret = ret + int64(num*(30.0*24.0*60.0*60.0*1000000000.0))
} else {
return 0, fmt.Errorf("Invalid 8601 duration '%s'", s)
}
case "y":
if strings.HasPrefix("years", unit) {
ret = ret + int64(num*(365.0*24.0*60.0*60.0*1000000000.0))
} else {
return 0, fmt.Errorf("Invalid 8601 duration '%s'", s)
}
case "w":
if strings.HasPrefix("weeks", unit) {
ret = ret + int64(num*(7.0*24.0*60.0*60.0*1000000000.0))
} else {
return 0, fmt.Errorf("Invalid 8601 duration '%s'", s)
}
case "h":
if strings.HasPrefix("hours", unit) {
ret = ret + int64(num*(60.0*60.0*1000000000.0))
} else {
return 0, fmt.Errorf("Invalid 8601 duration '%s'", s)
}
case "s":
if strings.HasPrefix("seconds", unit) {
ret = ret + int64(num*(1000000000.0))
} else {
return 0, fmt.Errorf("Invalid 8601 duration '%s'", s)
}
case "d":
if strings.HasPrefix("days", unit) {
ret = ret + int64(num*(24.0*60.0*60.0*1000000000.0))
} else {
return 0, fmt.Errorf("Invalid 8601 duration '%s'", s)
}
default:
return 0, fmt.Errorf("Invalid 8601 duration '%s'", s)
}
}
return time.Duration(ret), nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment