@@ -18,6 +18,7 @@ import (
1818 "database/sql/driver"
1919 "encoding/json"
2020 "fmt"
21+ "math"
2122 "regexp"
2223 "strconv"
2324 "strings"
6061 "w" : hoursInDay * daysInWeek * time .Hour ,
6162 }
6263
63- durationMatcher = regexp .MustCompile (`(((?:-\s?)?\d+)\s*([A-Za-zµ]+))` )
64+ durationMatcher = regexp .MustCompile (`^ (((?:-\s?)?\d+)(\.\d+)? \s*([A-Za-zµ]+))` )
6465)
6566
6667// IsDuration returns true if the provided string is a valid duration
@@ -100,11 +101,24 @@ func ParseDuration(cand string) (time.Duration, error) {
100101
101102 var dur time.Duration
102103 ok := false
104+ const expectGroups = 4
103105 for _ , match := range durationMatcher .FindAllStringSubmatch (cand , - 1 ) {
106+ if len (match ) < expectGroups {
107+ continue
108+ }
104109
105110 // remove possible leading - and spaces
106111 value , negative := strings .CutPrefix (match [2 ], "-" )
107112
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+
108122 // if the string is a valid duration, parse it
109123 factor , err := strconv .Atoi (strings .TrimSpace (value )) // converts string to int
110124 if err != nil {
@@ -115,7 +129,7 @@ func ParseDuration(cand string) (time.Duration, error) {
115129 factor = - factor
116130 }
117131
118- unit := strings .ToLower (strings .TrimSpace (match [3 ]))
132+ unit := strings .ToLower (strings .TrimSpace (match [4 ]))
119133
120134 for _ , variants := range timeUnits {
121135 last := len (variants ) - 1
@@ -124,6 +138,9 @@ func ParseDuration(cand string) (time.Duration, error) {
124138 for i , variant := range variants {
125139 if (last == i && strings .HasPrefix (unit , variant )) || strings .EqualFold (variant , unit ) {
126140 ok = true
141+ if divisor != neutral {
142+ multiplier = time .Duration (float64 (multiplier ) / divisor ) // convert to duration only after having reduced the scale
143+ }
127144 dur += (time .Duration (factor ) * multiplier )
128145 }
129146 }
0 commit comments