-
Notifications
You must be signed in to change notification settings - Fork 0
/
tparse.go
117 lines (110 loc) · 2.56 KB
/
tparse.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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package cmd
import (
"fmt"
"log"
"regexp"
"strconv"
"time"
)
var relTimeRegexp = regexp.MustCompile(`^([ymwdHM])-(\d+)(?:T(\d\d:\d\d))?$`)
func ParseRelativeTime(rt string) (time.Time, bool, error) {
match := relTimeRegexp.FindStringSubmatch(rt)
if match == nil {
return time.Time{}, false, nil
}
diff, err := strconv.Atoi(match[2])
if err != nil {
return time.Time{}, false, err
}
res := time.Now()
if match[3] != "" {
t, err := time.ParseInLocation("15:04", match[3], res.Location())
if err != nil {
log.Fatal(err)
}
res = time.Date(
res.Year(), res.Month(), res.Day(),
t.Hour(), t.Minute(), res.Second(), res.Nanosecond(),
res.Location())
}
ye, mo, da := res.Date()
ho, mi, se := res.Clock()
switch match[1] {
case "M":
mi -= diff
case "H":
ho -= diff
case "d":
da -= diff
case "w":
da -= 7 * diff
case "m":
mo -= time.Month(diff)
case "y":
ye -= diff
}
res = time.Date(
ye, mo, da,
ho, mi, se, res.Nanosecond(),
res.Location())
return res, true, nil
}
func ParseTime(tstr string) (time.Time, error) {
if tstr == "" {
return time.Now().Round(time.Second), nil
}
if res, ok, err := ParseRelativeTime(tstr); err != nil {
return time.Time{}, err
} else if ok {
return res, nil
}
t, err := time.ParseInLocation("2006-01-02T15:04", tstr, time.Local)
if err == nil {
return t, nil
}
t, err = time.ParseInLocation("15:04", tstr, time.Local)
if err == nil {
n := time.Now()
return time.Date(
n.Year(), n.Month(), n.Day(),
t.Hour(), t.Minute(), n.Second(),
0, n.Location(),
), nil
}
t, err = time.ParseInLocation("01/2006", tstr, time.Local)
if err != nil {
log.Fatal(err)
}
n := time.Now()
return time.Date(
t.Year(), t.Month(),
n.Day(), n.Hour(), n.Minute(), n.Second(),
0, n.Location(),
), nil
}
var durRegexp = regexp.MustCompile(`^(\d+)([smh]?)$`)
func ParseDuration(s string) (time.Duration, error) {
match := durRegexp.FindStringSubmatch(s)
if match == nil {
return 0, fmt.Errorf("invalid duration: '%s'", s)
}
res := time.Minute
switch match[2] {
case "s":
res = time.Second
case "h":
res = time.Hour
}
n, err := strconv.Atoi(match[1])
if err != nil {
return 0, err
}
return time.Duration(n) * res, nil
}
const TimeFlagDoc = `Set current time for operation. Missing elements are taken from now.
Formats:
- HH:MM : Local wall clock.
- {MHdwmy}-n[Thh:mm] : Go back n days, weeks, months or years
and optionally set wall clock time.
- mm/yyyy : Month and year.
- yyyy-mm-ddTHH:MM : Local wall clock time on a specific date.`