-
Notifications
You must be signed in to change notification settings - Fork 4
/
duration.go
147 lines (138 loc) · 4.45 KB
/
duration.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package dateparse
import (
"strings"
"time"
)
var (
seconds = `сек|секунд|sec|seconds`
minutes = `мин|минут|минуту|минуты|min`
hours = `часов|hours|hour|часа|час`
days = `дней|дня|days`
weeksWords = `недель|неделю|недели|неделя|weeks|week`
monthsWords = `месяцев|месяца|month`
years = `лет|года|год|years`
durationTimeWords = strings.Join([]string{seconds, minutes, hours, days, weeksWords, monthsWords, years}, "|")
)
var (
durPrefix = `(через|in|следующ[и]?[й]?[у]?[ю]?|следующий|следующую|next)`
duration = strings.Join([]string{today, tomorrow, afterTomorrow, afterAfterTomorrow, yesterday}, "|")
durationTime = `сек[у]?[н]?[д]?[а]?[у]?|мин[у]?[т]?[у]?[а]?[ы]?|min[u]?[t]?[e]?[s]?|час[о]?[в]?[а]?|hour[s]?|дн[е]?[й]?[я]?|day[s]?|недел[ь]?[я]?[и]?[ю]?|week[s]?|год|year[s]?|месяц[а]?[е]?[в]?|month[s]?`
durationWds = strings.Join([]string{duration, durationTime}, "|")
durationSuffix = `(утр[а]?[о]?[м]?|morning|вечер[а]?[о]?[м]?|evening|\\|/|днем|полдень|полночь|midday|noon|midnight|ночью)`
)
var (
quarter = `quarter|четверть`
half = `half|пол`
one = `one|один`
two = `two|два`
three = `three|три`
four = `four|четыре`
five = `five|пять`
six = `six|шесть`
seven = `seven|семь`
eight = `eight|восемь`
nine = `nine|девять`
ten = `ten|десять`
wordNumbers = strings.Join([]string{quarter, half, one, two, three, four, five, six, seven, eight, nine, ten}, "|")
)
func checkWordNumber(s string) float64 {
if v := forceFloat64(s); v != 0 {
return v
}
switch {
case strings.Contains(quarter, s):
return 0.25
case strings.Contains(half, s):
return 0.5
case strings.Contains(one, s):
return 1
case strings.Contains(two, s):
return 2
case strings.Contains(three, s):
return 3
case strings.Contains(four, s):
return 4
case strings.Contains(five, s):
return 5
case strings.Contains(six, s):
return 6
case strings.Contains(seven, s):
return 7
case strings.Contains(eight, s):
return 8
case strings.Contains(nine, s):
return 9
case strings.Contains(ten, s):
return 10
}
return 0
}
func calculateDuration(m []string, opts Opts, k int) (time.Time, string) {
dur := durationParse(m[k:], opts)
if dur > 0 {
return opts.Now.Add(dur).In(opts.Now.Location()), m[0]
}
return opts.Now, m[0]
}
func durationParse(bits []string, opts Opts) (dur time.Duration) {
if strings.Contains(durPrefix, bits[0]) {
return durationParse(normalizeStrings(bits[1:]), opts)
}
switch len(bits) {
case 1:
word := bits[0]
switch {
case strings.Contains(durationTimeWords, word):
return durationParse([]string{"1", word}, opts)
}
if forceInt64(word) > 0 {
return durationParse([]string{word, "минут"}, opts)
}
case 2:
v := checkWordNumber(bits[0])
if v == 0 {
return
}
word := strings.TrimSpace(bits[1])
if v < 1 && v >= 0 {
div := time.Duration(1 / v)
switch {
case strings.Contains(seconds, word):
return time.Second / div
case strings.Contains(minutes, word):
return time.Minute / div
case strings.Contains(hours, word):
return time.Hour / div
case strings.Contains(days, word):
return time.Hour * 12
case strings.Contains(weeksWords, word):
return time.Hour * 12 * 7
case strings.Contains(monthsWords, word):
return time.Hour * 12 * 31 // XXX:
case strings.Contains(years, word):
return time.Hour * 12 * 365 // XXX:
default:
return durationParse(bits[:1], opts)
}
}
switch {
case strings.Contains(seconds, word):
return time.Duration(v) * time.Second
case strings.Contains(minutes, word):
return time.Duration(v) * time.Minute
case strings.Contains(hours, word):
return time.Duration(v) * time.Hour
case strings.Contains(days, word):
return time.Duration(v) * time.Hour * 24
case strings.Contains(weeksWords, word):
return time.Duration(v) * time.Hour * 24 * 7
case strings.Contains(monthsWords, word):
return time.Duration(v) * time.Hour * 24 * 31 // XXX:
case strings.Contains(years, word):
return time.Duration(v) * time.Hour * 24 * 365 // XXX:
default:
return durationParse(bits[:1], opts)
}
}
return
}