This commit is contained in:
@@ -3,6 +3,8 @@ package cli
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -63,21 +65,71 @@ func (period *Period) Set(s string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (period *Period) setStartStop(s string) error {
|
func (period *Period) setStartStop(s string) error {
|
||||||
stop, err := period.setT(s, &period.Start)
|
stop, err := period.setT(time.Now(), s, &period.Start)
|
||||||
period.Stop = stop
|
period.Stop = stop
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (period *Period) setStop(s string) error {
|
func (period *Period) setStop(s string) error {
|
||||||
_, err := period.setT(s, &period.Stop)
|
_, err := period.setT(time.Now(), s, &period.Stop)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Period) setT(s string, t *time.Time) (time.Time, error) {
|
func (*Period) setT(now time.Time, s string, t *time.Time) (time.Time, error) {
|
||||||
if s == "" {
|
if s == "" {
|
||||||
*t = time.Unix(0, 0)
|
*t = time.Unix(0, 0)
|
||||||
return time.Now().AddDate(100, 0, 0), nil
|
return time.Now().AddDate(100, 0, 0), nil
|
||||||
}
|
}
|
||||||
|
if submatches := regexp.MustCompile(`[+-]?(?P<years>[0-9]+y)?(?P<months>[0-9]+mo)?(?P<weeks>[0-9]+w)?(?P<days>[0-9]+d)?([0-9]+[a-z])?`).FindStringSubmatch(s); len(submatches) > 0 {
|
||||||
|
s2 := s
|
||||||
|
result := now
|
||||||
|
scalar := time.Duration(1)
|
||||||
|
if strings.HasPrefix(s2, "-") {
|
||||||
|
scalar = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, submatch := range submatches[1 : len(submatches)-1] {
|
||||||
|
if len(submatch) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
unit := submatch[len(submatch)-1]
|
||||||
|
if submatch[len(submatch)-1] == 'o' { // mo
|
||||||
|
submatch = submatch[:len(submatch)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := strconv.Atoi(submatch[:len(submatch)-1])
|
||||||
|
if err != nil {
|
||||||
|
return time.Time{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
switch unit {
|
||||||
|
case 'y':
|
||||||
|
result = result.AddDate(int(scalar*1), 0, 0)
|
||||||
|
case 'o':
|
||||||
|
result = result.AddDate(0, int(scalar*1), 0)
|
||||||
|
case 'w':
|
||||||
|
result = result.AddDate(0, 0, int(scalar*7))
|
||||||
|
case 'd':
|
||||||
|
result = result.AddDate(0, 0, int(scalar*1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s2 = strings.ReplaceAll(s2, submatches[i+1], "")
|
||||||
|
}
|
||||||
|
|
||||||
|
if stdDuration := strings.TrimLeft(s2, "+-"); stdDuration != "" {
|
||||||
|
if d, err := time.ParseDuration(stdDuration); err == nil {
|
||||||
|
result = result.Add(scalar * d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if result != now {
|
||||||
|
*t = result
|
||||||
|
return result.AddDate(100, 0, 0), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
if result, err := time.Parse("2006", s); err == nil {
|
if result, err := time.Parse("2006", s); err == nil {
|
||||||
*t = result
|
*t = result
|
||||||
return result.AddDate(1, 0, 0).Add(-1 * time.Minute), nil
|
return result.AddDate(1, 0, 0).Add(-1 * time.Minute), nil
|
||||||
|
|||||||
41
cmd/cli/flag_test.go
Normal file
41
cmd/cli/flag_test.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPeriodSetT(t *testing.T) {
|
||||||
|
now := time.Date(2010, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
|
cases := map[string]time.Time{
|
||||||
|
"2001-02-03": time.Date(2001, 2, 3, 0, 0, 0, 0, time.UTC),
|
||||||
|
"2001-02": time.Date(2001, 2, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
"2001": time.Date(2001, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
"": time.Unix(0, 0),
|
||||||
|
"1m": now.Add(1 * time.Minute),
|
||||||
|
"+1m": now.Add(1 * time.Minute),
|
||||||
|
"-1m": now.Add(-1 * time.Minute),
|
||||||
|
"1h1m": now.Add(1*time.Hour + 1*time.Minute),
|
||||||
|
"1d": now.Add(24 * time.Hour),
|
||||||
|
"+1d": now.Add(24 * time.Hour),
|
||||||
|
"-1d": now.Add(-24 * time.Hour),
|
||||||
|
"1d1m": now.Add(24*time.Hour + 1*time.Minute),
|
||||||
|
"+1d1m": now.Add(24*time.Hour + 1*time.Minute),
|
||||||
|
"-1d1m": now.Add(-1*24*time.Hour + -1*1*time.Minute),
|
||||||
|
"1y1mo1w1d1h": now.AddDate(1, 1, 7+1).Add(1 * time.Hour),
|
||||||
|
}
|
||||||
|
|
||||||
|
for input, expect := range cases {
|
||||||
|
input, expect := input, expect
|
||||||
|
t.Run(input, func(t *testing.T) {
|
||||||
|
p := &Period{}
|
||||||
|
var got time.Time
|
||||||
|
if _, err := p.setT(now, input, &got); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if got.Unix() != expect.Unix() {
|
||||||
|
t.Errorf("expected %s but got %s", expect.String(), got.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user