/ internal / flag / timedurationvalue.go
timedurationvalue.go
 1  package flag
 2  
 3  import (
 4  	"fmt"
 5  	"regexp"
 6  	"strconv"
 7  	"strings"
 8  	"time"
 9  )
10  
11  const timeDurationRegexPattern string = `[0-9]{1,4}\s+(days?|hours?|minutes?|seconds?)`
12  
13  type TimeDurationValue struct {
14  	Duration time.Duration
15  }
16  
17  func NewTimeDurationValue() TimeDurationValue {
18  	return TimeDurationValue{
19  		Duration: time.Duration(0),
20  	}
21  }
22  
23  func (v TimeDurationValue) String() string {
24  	return v.Duration.String()
25  }
26  
27  func (v *TimeDurationValue) Set(value string) error {
28  	pattern := regexp.MustCompile(timeDurationRegexPattern)
29  	matches := pattern.FindAllString(value, -1)
30  
31  	days, hours, minutes, seconds := 0, 0, 0, 0
32  
33  	var err error
34  
35  	for ind := range len(matches) {
36  		switch {
37  		case strings.Contains(matches[ind], "day"):
38  			days, err = parseInt(matches[ind])
39  			if err != nil {
40  				return fmt.Errorf("unable to parse the number of days from %s: %w", matches[ind], err)
41  			}
42  		case strings.Contains(matches[ind], "hour"):
43  			hours, err = parseInt(matches[ind])
44  			if err != nil {
45  				return fmt.Errorf("unable to parse the number of hours from %s: %w", matches[ind], err)
46  			}
47  		case strings.Contains(matches[ind], "minute"):
48  			minutes, err = parseInt(matches[ind])
49  			if err != nil {
50  				return fmt.Errorf("unable to parse the number of minutes from %s: %w", matches[ind], err)
51  			}
52  		case strings.Contains(matches[ind], "second"):
53  			seconds, err = parseInt(matches[ind])
54  			if err != nil {
55  				return fmt.Errorf("unable to parse the number of seconds from %s: %w", matches[ind], err)
56  			}
57  		}
58  	}
59  
60  	durationValue := (days * 86400) + (hours * 3600) + (minutes * 60) + seconds
61  
62  	v.Duration = time.Duration(durationValue) * time.Second
63  
64  	return nil
65  }
66  
67  func parseInt(text string) (int, error) {
68  	split := strings.SplitN(text, " ", 2)
69  	if len(split) != 2 {
70  		return 0, fmt.Errorf("unexpected number of split for %s: want 2, got %d", text, len(split))
71  	}
72  
73  	output, err := strconv.Atoi(split[0])
74  	if err != nil {
75  		return 0, fmt.Errorf("unable to convert %s to an integer: %w", text, err)
76  	}
77  
78  	return output, nil
79  }