@@ -18,6 +18,7 @@ import (
18
18
"database/sql/driver"
19
19
"encoding/json"
20
20
"fmt"
21
+ "math"
21
22
"regexp"
22
23
"strconv"
23
24
"strings"
60
61
"w" : hoursInDay * daysInWeek * time .Hour ,
61
62
}
62
63
63
- durationMatcher = regexp .MustCompile (`(((?:-\s?)?\d+)\s*([A-Za-zµ]+))` )
64
+ durationMatcher = regexp .MustCompile (`^ (((?:-\s?)?\d+)(\.\d+)? \s*([A-Za-zµ]+))` )
64
65
)
65
66
66
67
// IsDuration returns true if the provided string is a valid duration
@@ -100,11 +101,24 @@ func ParseDuration(cand string) (time.Duration, error) {
100
101
101
102
var dur time.Duration
102
103
ok := false
104
+ const expectGroups = 4
103
105
for _ , match := range durationMatcher .FindAllStringSubmatch (cand , - 1 ) {
106
+ if len (match ) < expectGroups {
107
+ continue
108
+ }
104
109
105
110
// remove possible leading - and spaces
106
111
value , negative := strings .CutPrefix (match [2 ], "-" )
107
112
113
+ // if the duration contains a decimal separator determine a divising factor
114
+ const neutral = 1.0
115
+ divisor := neutral
116
+ decimal , hasDecimal := strings .CutPrefix (match [3 ], "." )
117
+ if hasDecimal {
118
+ divisor = math .Pow10 (len (decimal ))
119
+ value += decimal // consider the value as an integer: will change units later on
120
+ }
121
+
108
122
// if the string is a valid duration, parse it
109
123
factor , err := strconv .Atoi (strings .TrimSpace (value )) // converts string to int
110
124
if err != nil {
@@ -115,7 +129,7 @@ func ParseDuration(cand string) (time.Duration, error) {
115
129
factor = - factor
116
130
}
117
131
118
- unit := strings .ToLower (strings .TrimSpace (match [3 ]))
132
+ unit := strings .ToLower (strings .TrimSpace (match [4 ]))
119
133
120
134
for _ , variants := range timeUnits {
121
135
last := len (variants ) - 1
@@ -124,6 +138,9 @@ func ParseDuration(cand string) (time.Duration, error) {
124
138
for i , variant := range variants {
125
139
if (last == i && strings .HasPrefix (unit , variant )) || strings .EqualFold (variant , unit ) {
126
140
ok = true
141
+ if divisor != neutral {
142
+ multiplier = time .Duration (float64 (multiplier ) / divisor ) // convert to duration only after having reduced the scale
143
+ }
127
144
dur += (time .Duration (factor ) * multiplier )
128
145
}
129
146
}
0 commit comments