/
duration.go
49 lines (43 loc) · 1.43 KB
/
duration.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package schema
import (
"fmt"
"regexp"
"strconv"
"time"
)
var durationRegexp = regexp.MustCompile(
`P(?P<years>\d+Y)?(?P<months>\d+M)?(?P<days>\d+D)?T?(?P<hours>\d+H)?(?P<minutes>\d+M)?(?P<seconds>\d+\.?\d*S)?`)
const (
hoursInYear = time.Duration(24*36) * time.Hour
hoursInMonth = time.Duration(24*30) * time.Hour
hoursInDay = time.Duration(24) * time.Hour
)
func castDuration(value string) (time.Duration, error) {
matches := durationRegexp.FindStringSubmatch(value)
if len(matches) == 0 {
return 0, fmt.Errorf("Invalid duration:\"%s\"", value)
}
years := parseIntDuration(matches[1], hoursInYear)
months := parseIntDuration(matches[2], hoursInMonth)
days := parseIntDuration(matches[3], hoursInDay)
hours := parseIntDuration(matches[4], time.Hour)
minutes := parseIntDuration(matches[5], time.Minute)
seconds := parseSeconds(matches[6])
return years + months + days + hours + minutes + seconds, nil
}
func parseIntDuration(v string, multiplier time.Duration) time.Duration {
if len(v) == 0 {
return 0
}
// Ignoring error here because only digits could come from the regular expression.
d, _ := strconv.Atoi(v[0 : len(v)-1])
return time.Duration(d) * multiplier
}
func parseSeconds(v string) time.Duration {
if len(v) == 0 {
return 0
}
// Ignoring error here because only valid arbitrary precision floats could come from the regular expression.
d, _ := strconv.ParseFloat(v[0:len(v)-1], 64)
return time.Duration(d * 10e8)
}