fugit 1.3.4 → 1.3.9
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fugit might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -0
- data/CREDITS.md +4 -1
- data/README.md +24 -1
- data/fugit.gemspec +1 -1
- data/lib/fugit.rb +1 -1
- data/lib/fugit/cron.rb +12 -3
- data/lib/fugit/nat.rb +417 -154
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ff6ed980e9137d5c51dda0b2ca0a66dffb35ae99352168a50e92fadbf272442a
|
4
|
+
data.tar.gz: '00977091b588564591b180debb728806bce562eaf2145b413e752c2eda90652e'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c9290c85529fefb3ec1d8c664f4dabaa0e1bbe8d9430555a1af1c5c382e15afeb9f729fbc4b9eba00bf7db0a47625daf0f12a5328743b3f25af66728bd3d0b2
|
7
|
+
data.tar.gz: 67e65d620ebfb16c4c9d649e61ac743691c1bb77a2573ce750d8202bf5bb4f090a8d1feb86aab362b6916de9b028c3e7e00bdad8a708d3397736ede1c14f1b61
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,33 @@
|
|
2
2
|
# CHANGELOG.md
|
3
3
|
|
4
4
|
|
5
|
+
## fugit 1.3.9 released 2020-09-17
|
6
|
+
|
7
|
+
* Prevent "New York skip", gh-43, thanks @honglooker
|
8
|
+
|
9
|
+
|
10
|
+
## fugit 1.3.8 released 2020-08-06
|
11
|
+
|
12
|
+
* Parse 'every day at 8:30' and ' at 8:30 pm', gh-42
|
13
|
+
|
14
|
+
|
15
|
+
## fugit 1.3.7 released 2020-08-05
|
16
|
+
|
17
|
+
* Parse 'every 12 hours at minute 50', gh-41
|
18
|
+
|
19
|
+
|
20
|
+
## fugit 1.3.6 released 2020-06-01
|
21
|
+
|
22
|
+
* Introduce new nat syntaxed, gh-38
|
23
|
+
* Rework nat parser
|
24
|
+
|
25
|
+
|
26
|
+
## fugit 1.3.5 released 2020-05-07
|
27
|
+
|
28
|
+
* Implement cron @noon, gh-37
|
29
|
+
* Normalize "every x", gh-37
|
30
|
+
|
31
|
+
|
5
32
|
## fugit 1.3.4 released 2020-04-06
|
6
33
|
|
7
34
|
* Prevent #rough_frequency returning 0, gh-36
|
data/CREDITS.md
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
|
2
2
|
# fugit credits
|
3
3
|
|
4
|
+
* Honglooker https://github.com/honglooker gh-43, New York cron skip
|
5
|
+
* Jérôme Dalbert https://github.com/jeromedalbert gh-41, gh-42
|
6
|
+
* Danny Ben Shitrit https://github.com/DannyBen nat variants, gh-38
|
4
7
|
* Dominik Sander https://github.com/dsander #rough_frequency 0, gh-36
|
5
8
|
* Milovan Zogovic https://github.com/assembler Cron#match? vs TZ, gh-31
|
6
9
|
* Jessica Stokes https://github.com/ticky 0-24 issue with cron, gh-30
|
7
|
-
* Shai Coleman https://github.com/shaicoleman parse_nat enhancements, gh-24, gh-25, and gh-
|
10
|
+
* Shai Coleman https://github.com/shaicoleman parse_nat enhancements, gh-24, gh-25, gh-28, and gh-37
|
8
11
|
* Jan Stevens https://github.com/JanStevens Fugit.parse('every 15 minutes') gh-22
|
9
12
|
* Fabio Pitino https://github.com/hspazio nil on February 30 gh-21
|
10
13
|
* Cristian Oneț https://github.com/conet #previous_time vs 1/-1 endless loop gh-15
|
data/README.md
CHANGED
@@ -9,7 +9,7 @@ Time tools for [flor](https://github.com/floraison/flor) and the floraison group
|
|
9
9
|
|
10
10
|
It uses [et-orbi](https://github.com/floraison/et-orbi) to represent time instances and [raabro](https://github.com/floraison/raabro) as a basis for its parsers.
|
11
11
|
|
12
|
-
Fugit is a core dependency of [rufus-scheduler](https://github.com/jmettraux/rufus-scheduler) 3.5.
|
12
|
+
Fugit is a core dependency of [rufus-scheduler](https://github.com/jmettraux/rufus-scheduler) >= 3.5.
|
13
13
|
|
14
14
|
|
15
15
|
## Related projects
|
@@ -232,6 +232,29 @@ p d.to_plain_s # => "2Y2M1D5h3600s"
|
|
232
232
|
p Fugit::Duration.parse('1y2M1d4h').to_sec # => 36820800
|
233
233
|
```
|
234
234
|
|
235
|
+
There is a `#deflate` method
|
236
|
+
|
237
|
+
```ruby
|
238
|
+
Fugit::Duration.parse(1000).to_plain_s # => "1000s"
|
239
|
+
Fugit::Duration.parse(3600).to_plain_s # => "3600s"
|
240
|
+
Fugit::Duration.parse(1000).deflate.to_plain_s # => "16m40s"
|
241
|
+
Fugit::Duration.parse(3600).deflate.to_plain_s # => "1h"
|
242
|
+
|
243
|
+
# or event shorter
|
244
|
+
Fugit.parse(1000).deflate.to_plain_s # => "16m40s"
|
245
|
+
Fugit.parse(3600).deflate.to_plain_s # => "1h"
|
246
|
+
```
|
247
|
+
|
248
|
+
There is also an `#inflate` method
|
249
|
+
|
250
|
+
```ruby
|
251
|
+
Fugit::Duration.parse('1h30m12').inflate.to_plain_s # => "5412s"
|
252
|
+
Fugit.parse('1h30m12').inflate.to_plain_s # => "5412s"
|
253
|
+
|
254
|
+
Fugit.parse('1h30m12').to_sec # => 5412
|
255
|
+
Fugit.parse('1h30m12').to_sec.to_s + 's' # => "5412s"
|
256
|
+
```
|
257
|
+
|
235
258
|
The `to_*_s` methods are also available as class methods:
|
236
259
|
```ruby
|
237
260
|
p Fugit::Duration.to_plain_s('1y2M1d4h')
|
data/fugit.gemspec
CHANGED
@@ -40,7 +40,7 @@ Time tools for flor and the floraison project. Cron parsing and occurrence compu
|
|
40
40
|
#s.add_runtime_dependency 'tzinfo'
|
41
41
|
# this dependency appears in 'et-orbi'
|
42
42
|
|
43
|
-
s.add_runtime_dependency 'raabro', '~> 1.
|
43
|
+
s.add_runtime_dependency 'raabro', '~> 1.3'
|
44
44
|
s.add_runtime_dependency 'et-orbi', '~> 1.1', '>= 1.1.8'
|
45
45
|
|
46
46
|
s.add_development_dependency 'rspec', '~> 3.8'
|
data/lib/fugit.rb
CHANGED
data/lib/fugit/cron.rb
CHANGED
@@ -11,6 +11,7 @@ module Fugit
|
|
11
11
|
'@weekly' => '0 0 * * 0',
|
12
12
|
'@daily' => '0 0 * * *',
|
13
13
|
'@midnight' => '0 0 * * *',
|
14
|
+
'@noon' => '0 12 * * *',
|
14
15
|
'@hourly' => '0 * * * *' }
|
15
16
|
MAXDAYS = [
|
16
17
|
nil, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]
|
@@ -235,6 +236,8 @@ module Fugit
|
|
235
236
|
# the translation occurs in the timezone of
|
236
237
|
# this Fugit::Cron instance
|
237
238
|
|
239
|
+
zfrom = t.time.strftime('%z|%Z')
|
240
|
+
|
238
241
|
loop do
|
239
242
|
|
240
243
|
fail RuntimeError.new(
|
@@ -250,8 +253,14 @@ module Fugit
|
|
250
253
|
min_match?(t) || (t.inc_min; next)
|
251
254
|
sec_match?(t) || (t.inc_sec; next)
|
252
255
|
|
253
|
-
|
254
|
-
|
256
|
+
tt = t.time
|
257
|
+
st = tt.strftime('%F|%T')
|
258
|
+
zt = tt.strftime('%z|%Z')
|
259
|
+
#
|
260
|
+
if st == sfrom && zt != zfrom
|
261
|
+
from, sfrom, zfrom, ifrom = tt, st, zt, t.to_i
|
262
|
+
next
|
263
|
+
end
|
255
264
|
#
|
256
265
|
# when transitioning out of DST, this prevents #next_time from
|
257
266
|
# yielding the same literal time twice in a row, see gh-6
|
@@ -756,7 +765,7 @@ module Fugit
|
|
756
765
|
|
757
766
|
def rewrite_tz(t)
|
758
767
|
|
759
|
-
s = t.
|
768
|
+
s = t.strim
|
760
769
|
z = EtOrbi.get_tzone(s)
|
761
770
|
|
762
771
|
[ s, z ]
|
data/lib/fugit/nat.rb
CHANGED
@@ -15,16 +15,8 @@ module Fugit
|
|
15
15
|
return nil unless s.is_a?(String)
|
16
16
|
|
17
17
|
#p s; Raabro.pp(Parser.parse(s, debug: 3), colours: true)
|
18
|
-
|
19
|
-
|
20
|
-
return nil unless a
|
21
|
-
|
22
|
-
return parse_crons(s, a, opts) \
|
23
|
-
if a.include?([ :flag, 'every' ])
|
24
|
-
return parse_crons(s, a, opts) \
|
25
|
-
if a.include?([ :flag, 'from' ]) && a.find { |e| e[0] == :day_range }
|
26
|
-
|
27
|
-
nil
|
18
|
+
#(p s; Raabro.pp(Parser.parse(s, debug: 1), colours: true)) rescue nil
|
19
|
+
parse_crons(s, Parser.parse(s), opts)
|
28
20
|
end
|
29
21
|
|
30
22
|
def do_parse(s, opts={})
|
@@ -37,20 +29,37 @@ module Fugit
|
|
37
29
|
|
38
30
|
def parse_crons(s, a, opts)
|
39
31
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
.
|
32
|
+
#p a
|
33
|
+
return nil unless a
|
34
|
+
|
35
|
+
h = a
|
36
|
+
.reverse
|
37
|
+
.inject({}) { |r, e| send("parse_#{e[0]}_elt", e, opts, r); r }
|
38
|
+
#
|
39
|
+
# the reverse ensure that in "every day at five", the
|
40
|
+
# "at five" is placed before the "every day" so that
|
41
|
+
# parse_x_elt calls have the right sequence
|
42
|
+
#p h
|
43
|
+
|
44
|
+
if f = h[:_fail]
|
45
|
+
#fail ArgumentError.new(f)
|
46
|
+
return nil
|
47
|
+
end
|
48
|
+
|
49
|
+
hms = h[:hms]
|
50
|
+
|
51
|
+
hours = (hms || [])
|
45
52
|
.uniq
|
53
|
+
.inject({}) { |r, hm| (r[hm[1]] ||= []) << hm[0]; r }
|
54
|
+
.inject({}) { |r, (m, hs)| (r[hs.sort] ||= []) << m; r }
|
55
|
+
.to_a
|
56
|
+
.sort_by { |hs, ms| -hs.size }
|
57
|
+
if hours.empty?
|
58
|
+
hours << (h[:dom] ? [ [ '0' ], [ '0' ] ] : [ [ '*' ], [ '*' ] ])
|
59
|
+
end
|
46
60
|
|
47
|
-
crons =
|
48
|
-
|
49
|
-
if ms.size <= 1
|
50
|
-
[ parse_cron(a, opts) ]
|
51
|
-
else
|
52
|
-
dhs.collect { |dh| parse_cron([ dh ] + aa, opts) }
|
53
|
-
end
|
61
|
+
crons = hours
|
62
|
+
.collect { |hm| assemble_cron(h.merge(hms: hm)) }
|
54
63
|
|
55
64
|
fail ArgumentError.new(
|
56
65
|
"multiple crons in #{s.inspect} " +
|
@@ -64,207 +73,461 @@ module Fugit
|
|
64
73
|
end
|
65
74
|
end
|
66
75
|
|
67
|
-
def
|
68
|
-
|
69
|
-
h = { min: nil, hou: [], dom: nil, mon: nil, dow: nil }
|
70
|
-
hkeys = h.keys
|
71
|
-
|
72
|
-
a.each do |key, val|
|
73
|
-
if key == :biz_day
|
74
|
-
(h[:dow] ||= []) << '1-5'
|
75
|
-
elsif key == :simple_hour || key == :numeral_hour
|
76
|
-
h[:hou] << val
|
77
|
-
elsif key == :digital_hour
|
78
|
-
(h[:hou] ||= []) << val[0].to_i
|
79
|
-
(h[:min] ||= []) << val[1].to_i
|
80
|
-
elsif key == :name_day
|
81
|
-
(h[:dow] ||= []) << val
|
82
|
-
elsif key == :day_range
|
83
|
-
(h[:dow] ||= []) << val.collect { |v| v.to_s[0, 3] }.join('-')
|
84
|
-
elsif key == :tz
|
85
|
-
h[:tz] = val
|
86
|
-
elsif key == :duration
|
87
|
-
process_duration(h, *val[0].to_h.first)
|
88
|
-
end
|
89
|
-
end
|
76
|
+
def assemble_cron(h)
|
90
77
|
|
91
|
-
|
92
|
-
|
78
|
+
#puts "ac: " + h.inspect
|
79
|
+
s = []
|
80
|
+
s << h[:sec] if h[:sec]
|
81
|
+
s << h[:hms][1].join(',')
|
82
|
+
s << h[:hms][0].join(',')
|
83
|
+
s << (h[:dom] || '*') << (h[:mon] || '*') << (h[:dow] || '*')
|
84
|
+
s << h[:tz] if h[:tz]
|
93
85
|
|
94
|
-
|
95
|
-
|
86
|
+
Fugit::Cron.parse(s.join(' '))
|
87
|
+
end
|
96
88
|
|
97
|
-
|
89
|
+
def eone(e); e1 = e[1]; e1 == 1 ? '*' : "*/#{e1}"; end
|
98
90
|
|
99
|
-
|
100
|
-
.collect { |k|
|
101
|
-
v = h[k]
|
102
|
-
(v && v.any?) ? v.collect(&:to_s).join(',') : '*' }
|
103
|
-
a.insert(0, h[:sec]) if h[:sec]
|
104
|
-
a << h[:tz].first if h[:tz]
|
91
|
+
def parse_interval_elt(e, opts, h)
|
105
92
|
|
106
|
-
|
93
|
+
e1 = e[1]
|
107
94
|
|
108
|
-
|
95
|
+
case e[2]
|
96
|
+
when 's', 'sec', 'second', 'seconds'
|
97
|
+
h[:sec] = eone(e)
|
98
|
+
when 'm', 'min', 'mins', 'minute', 'minutes'
|
99
|
+
h[:hms] ||= [ [ '*', eone(e) ] ]
|
100
|
+
when 'h', 'hour', 'hours'
|
101
|
+
hms = h[:hms]
|
102
|
+
if hms && hms.size == 1 && hms.first.first == '*'
|
103
|
+
hms.first[0] = eone(e)
|
104
|
+
elsif ! hms
|
105
|
+
h[:hms] = [ [ eone(e), 0 ] ]
|
106
|
+
end
|
107
|
+
when 'd', 'day', 'days'
|
108
|
+
h[:dom] = "*/#{e1}" if e1 > 1
|
109
|
+
h[:hms] ||= [ [ 0, 0 ] ]
|
110
|
+
when 'w', 'week', 'weeks'
|
111
|
+
h[:_fail] = "cannot have crons for \"every #{e1} weeks\"" if e1 > 1
|
112
|
+
h[:hms] ||= [ [ 0, 0 ] ]
|
113
|
+
h[:dow] ||= 0
|
114
|
+
when 'M', 'month', 'months'
|
115
|
+
h[:_fail] = "cannot have crons for \"every #{e1} months\"" if e1 > 12
|
116
|
+
h[:hms] ||= [ [ 0, 0 ] ]
|
117
|
+
h[:dom] = 1
|
118
|
+
h[:mon] = eone(e)
|
119
|
+
when 'Y', 'y', 'year', 'years'
|
120
|
+
h[:_fail] = "cannot have crons for \"every #{e1} years\"" if e1 > 1
|
121
|
+
h[:hms] ||= [ [ 0, 0 ] ]
|
122
|
+
h[:dom] = 1
|
123
|
+
h[:mon] = 1
|
124
|
+
end
|
109
125
|
end
|
110
126
|
|
111
|
-
def
|
127
|
+
def parse_dow_list_elt(e, opts, h)
|
112
128
|
|
113
|
-
|
129
|
+
h[:hms] ||= [ [ 0, 0 ] ]
|
130
|
+
h[:dow] = e[1..-1].collect(&:to_s).sort.join(',')
|
114
131
|
end
|
115
132
|
|
116
|
-
def
|
133
|
+
def parse_dow_range_elt(e, opts, h)
|
117
134
|
|
118
|
-
h[:
|
119
|
-
h[:
|
120
|
-
h[:mon] = [ value == 1 ? '*' : "*/#{value}" ]
|
135
|
+
h[:hms] ||= [ [ 0, 0 ] ]
|
136
|
+
h[:dow] = e[1] == e[2] ? e[1] : "#{e[1]}-#{e[2]}"
|
121
137
|
end
|
122
138
|
|
123
|
-
def
|
139
|
+
def parse_day_of_month_elt(e, opts, h)
|
124
140
|
|
125
|
-
h[:
|
126
|
-
h[:dom] = [ value == 1 ? '*' : "*/#{value}" ]
|
141
|
+
h[:dom] = e[1..-1].join(',')
|
127
142
|
end
|
128
143
|
|
129
|
-
def
|
144
|
+
def parse_at_elt(e, opts, h)
|
130
145
|
|
131
|
-
h[:
|
146
|
+
(h[:hms] ||= []).concat(e[1])
|
147
|
+
|
148
|
+
l = h[:hms].last
|
149
|
+
h[:sec] = l.pop if l.size > 2
|
132
150
|
end
|
133
151
|
|
134
|
-
def
|
152
|
+
def parse_on_elt(e, opts, h)
|
153
|
+
|
154
|
+
e1 = e[1]
|
155
|
+
h[:dow] = e1[0]
|
156
|
+
h[:hms] = [ e1[1] ]
|
135
157
|
|
136
|
-
|
137
|
-
h[:
|
158
|
+
l = h[:hms].last
|
159
|
+
h[:sec] = l.pop if l.size > 2
|
138
160
|
end
|
139
161
|
|
140
|
-
def
|
162
|
+
def parse_tz_elt(e, opts, h)
|
141
163
|
|
142
|
-
h[:
|
143
|
-
h[:min] = [ '*' ]
|
144
|
-
h[:sec] = [ value == 1 ? '*' : "*/#{value}" ]
|
164
|
+
h[:tz] = e[1]
|
145
165
|
end
|
146
166
|
end
|
147
167
|
|
148
168
|
module Parser include Raabro
|
149
169
|
|
150
170
|
NUMS = %w[
|
151
|
-
zero
|
152
|
-
one two three four five six seven eight nine
|
153
|
-
ten eleven twelve ]
|
171
|
+
zero one two three four five six seven eight nine ten eleven twelve ]
|
154
172
|
|
155
173
|
WEEKDAYS =
|
156
174
|
Fugit::Cron::Parser::WEEKDS + Fugit::Cron::Parser::WEEKDAYS
|
157
175
|
|
158
|
-
NHOURS =
|
159
|
-
|
176
|
+
NHOURS = {
|
177
|
+
'noon' => [ 12, 0 ],
|
178
|
+
'midnight' => [ 0, 0 ], 'oh' => [ 0, 0 ] }
|
179
|
+
NMINUTES = {
|
180
|
+
"o'clock" => 0, 'five' => 5,
|
181
|
+
'ten' => 10, 'fifteen' => 15,
|
182
|
+
'twenty' => 20, 'twenty-five' => 25,
|
183
|
+
'thirty' => 30, 'thirty-five' => 35,
|
184
|
+
'fourty' => 40, 'fourty-five' => 45,
|
185
|
+
'fifty' => 50, 'fifty-five' => 55 }
|
186
|
+
|
187
|
+
oh = {
|
188
|
+
'1st' => 1, '2nd' => 2, '3rd' => 3, '21st' => 21, '22nd' => 22,
|
189
|
+
'23rd' => 23, '31st' => 31 }
|
190
|
+
%w[ 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 24 25 26 27 28 29 30 ]
|
191
|
+
.each { |i| oh["#{i}th"] = i.to_i }
|
192
|
+
%w[
|
193
|
+
first second third fourth fifth sixth seventh eighth ninth tenth
|
194
|
+
eleventh twelfth thirteenth fourteenth fifteenth sixteenth seventeenth
|
195
|
+
eighteenth nineteenth twentieth twenty-first twenty-second twenty-third
|
196
|
+
twenty-fourth twenty-fifth twenty-fifth twenty-sixth twenty-seventh
|
197
|
+
twenty-eighth twenty-ninth thirtieth thirty-first ]
|
198
|
+
.each_with_index { |e, i| oh[e] = i + 1 }
|
199
|
+
ORDINALS = oh
|
160
200
|
|
161
201
|
# piece parsers bottom to top
|
162
202
|
|
203
|
+
def _from(i); rex(nil, i, /\s*from\s+/i); end
|
204
|
+
def _every(i); rex(nil, i, /\s*(every)\s+/i); end
|
205
|
+
def _at(i); rex(nil, i, /\s*at\s+/i); end
|
206
|
+
def _in(i); rex(nil, i, /\s*(in|on)\s+/i); end
|
207
|
+
def _to(i); rex(nil, i, /\s*to\s+/i); end
|
208
|
+
def _dash(i); rex(nil, i, /-\s*/i); end
|
209
|
+
def _and(i); rex(nil, i, /\s*and\s+/i); end
|
210
|
+
def _on(i); rex(nil, i, /\s*on\s+/i); end
|
211
|
+
|
212
|
+
def _and_or_comma(i)
|
213
|
+
rex(nil, i, /\s*(,?\s*and\s|,?\s*or\s|,)\s*/i)
|
214
|
+
end
|
215
|
+
def _at_comma(i)
|
216
|
+
rex(nil, i, /\s*(at\s|,|)\s*/i)
|
217
|
+
end
|
218
|
+
def _to_through(i)
|
219
|
+
rex(nil, i, /\s*(to|through)\s+/i)
|
220
|
+
end
|
221
|
+
|
222
|
+
def integer(i); rex(:int, i, /\d+\s*/); end
|
223
|
+
|
224
|
+
def tz_name(i)
|
225
|
+
rex(nil, i,
|
226
|
+
/\s*[A-Z][a-zA-Z0-9+\-]+(\/[A-Z][a-zA-Z0-9+\-_]+){0,2}(\s+|$)/)
|
227
|
+
end
|
228
|
+
def tz_delta(i)
|
229
|
+
rex(nil, i,
|
230
|
+
/\s*[-+]([01][0-9]|2[0-4]):?(00|15|30|45)(\s+|$)/)
|
231
|
+
end
|
232
|
+
def tzone(i)
|
233
|
+
alt(:tzone, i, :tz_delta, :tz_name)
|
234
|
+
end
|
235
|
+
|
236
|
+
def and_named_digits(i)
|
237
|
+
rex(:xxx, i, 'TODO')
|
238
|
+
end
|
239
|
+
|
240
|
+
def dname(i)
|
241
|
+
rex(:dname, i, /(s(ec(onds?)?)?|m(in(utes?)?)?)\s+/i)
|
242
|
+
end
|
243
|
+
def named_digit(i)
|
244
|
+
seq(:named_digit, i, :dname, :integer)
|
245
|
+
end
|
246
|
+
def named_digits(i)
|
247
|
+
seq(nil, i, :named_digit, '+', :and_named_digits, '*')
|
248
|
+
end
|
249
|
+
|
163
250
|
def am_pm(i)
|
164
|
-
rex(:am_pm, i,
|
251
|
+
rex(:am_pm, i, /\s*(am|pm|dark)\s*/i)
|
165
252
|
end
|
166
253
|
|
167
|
-
def
|
168
|
-
rex(:
|
254
|
+
def nminute(i)
|
255
|
+
rex(:nminute, i, /(#{NMINUTES.keys.join('|')})\s*/i)
|
256
|
+
end
|
257
|
+
def nhour(i)
|
258
|
+
rex(:nhour, i, /(#{NUMS.join('|')})\s*/i)
|
259
|
+
end
|
260
|
+
def numeral_hour(i)
|
261
|
+
seq(:numeral_hour, i, :nhour, :am_pm, '?', :nminute, '?')
|
262
|
+
end
|
263
|
+
|
264
|
+
def named_hour(i)
|
265
|
+
rex(:named_hour, i, /(#{NHOURS.keys.join('|')})/i)
|
169
266
|
end
|
170
267
|
|
171
|
-
def
|
172
|
-
rex(:
|
268
|
+
def shour(i)
|
269
|
+
rex(:shour, i, /(2[0-4]|[01]?[0-9])/)
|
173
270
|
end
|
174
271
|
def simple_hour(i)
|
175
|
-
seq(:simple_hour, i, :
|
272
|
+
seq(:simple_hour, i, :shour, :am_pm, '?')
|
176
273
|
end
|
177
274
|
|
178
|
-
def
|
179
|
-
|
275
|
+
def dig_hour_b(i); rex(nil, i, /(2[0-4]|[01][0-9]|[0-9]):[0-5]\d/); end
|
276
|
+
def dig_hour_a(i); rex(nil, i, /(2[0-4]|[01][0-9])[0-5]\d/); end
|
277
|
+
def dig_hour(i); alt(nil, i, :dig_hour_a, :dig_hour_b); end
|
278
|
+
#
|
279
|
+
def digital_hour(i)
|
280
|
+
seq(:digital_hour, i, :dig_hour, :am_pm, '?')
|
180
281
|
end
|
181
|
-
|
182
|
-
|
282
|
+
|
283
|
+
def at_point(i)
|
284
|
+
alt(nil, i,
|
285
|
+
:digital_hour, :simple_hour, :named_hour, :numeral_hour,
|
286
|
+
:named_digits)
|
183
287
|
end
|
184
288
|
|
185
|
-
def
|
186
|
-
rex(:
|
289
|
+
def weekday(i)
|
290
|
+
rex(:weekday, i, /(#{WEEKDAYS.reverse.join('|')})\s*/i)
|
187
291
|
end
|
188
292
|
|
189
|
-
def
|
190
|
-
|
191
|
-
|
293
|
+
def and_at(i)
|
294
|
+
seq(nil, i, :_and_or_comma, :at_point)
|
295
|
+
end
|
192
296
|
|
193
|
-
def
|
297
|
+
def _intervals(i)
|
298
|
+
rex(:intervals, i,
|
299
|
+
/(
|
300
|
+
y(ears?)?|months?|w(eeks?)?|d(ays?)?|
|
301
|
+
h(ours?)?|m(in(ute)?s?)?|s(ec(ond)?s?)?
|
302
|
+
)(\s+|$)/ix)
|
303
|
+
end
|
194
304
|
|
195
|
-
def
|
196
|
-
|
305
|
+
def sinterval(i)
|
306
|
+
rex(:sinterval, i,
|
307
|
+
/(year|month|week|day|hour|min(ute)?|sec(ond)?)(\s+|$)/i)
|
308
|
+
end
|
309
|
+
def ninterval(i)
|
310
|
+
seq(:ninterval, i, :integer, :_intervals)
|
197
311
|
end
|
198
312
|
|
199
|
-
def
|
200
|
-
rex(
|
313
|
+
def ordinal(i)
|
314
|
+
rex(:ordinal, i, /\s*(#{ORDINALS.keys.join('|')})\s*/)
|
201
315
|
end
|
202
|
-
|
203
|
-
|
316
|
+
|
317
|
+
def _mod(i); rex(nil, i, /\s*month\s+on\s+days?\s+/i); end
|
318
|
+
def _oftm(i); rex(nil, i, /\s*(day\s)?\s*of\s+the\s+month\s*/i); end
|
319
|
+
|
320
|
+
def dom(i)
|
321
|
+
rex(:int, i, /([12][0-9]|3[01]|[0-9])/)
|
322
|
+
end
|
323
|
+
def and_or_dom(i)
|
324
|
+
seq(nil, i, :_and_or_comma, :dom)
|
325
|
+
end
|
326
|
+
def dom_list(i)
|
327
|
+
seq(:dom_list, i, :dom, :and_or_dom, '*')
|
204
328
|
end
|
205
|
-
def _tz(i); alt(:tz, i, :_tz_delta, :_tz_name); end
|
206
329
|
|
207
|
-
def
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
330
|
+
def dom_mod(i) # every month on day
|
331
|
+
seq(:dom, i, :_mod, :dom_list)
|
332
|
+
end
|
333
|
+
def dom_noftm(i) # every nth of month
|
334
|
+
seq(:dom, i, :ordinal, :_oftm)
|
335
|
+
end
|
336
|
+
def day_of_month(i)
|
337
|
+
alt(nil, i, :dom_noftm, :dom_mod)
|
215
338
|
end
|
216
339
|
|
217
|
-
def
|
340
|
+
def dow_class(i)
|
341
|
+
rex(:dow_class, i, /(weekday)(\s+|$)/i)
|
342
|
+
end
|
218
343
|
|
219
|
-
def
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
344
|
+
def dow(i)
|
345
|
+
seq(:dow, i, :weekday)
|
346
|
+
end
|
347
|
+
def and_or_dow(i)
|
348
|
+
seq(nil, i, :_and_or_comma, :dow)
|
349
|
+
end
|
350
|
+
def dow_list(i)
|
351
|
+
seq(:dow_list, i, :dow, :and_or_dow, '*')
|
352
|
+
end
|
353
|
+
|
354
|
+
def to_dow_range(i)
|
355
|
+
seq(:dow_range, i, :weekday, :_to_through, :weekday)
|
356
|
+
end
|
357
|
+
def dash_dow_range(i)
|
358
|
+
seq(:dow_range, i, :weekday, :_dash, :weekday)
|
359
|
+
end
|
360
|
+
def dow_range(i)
|
361
|
+
alt(nil, i, :to_dow_range, :dash_dow_range)
|
362
|
+
end
|
363
|
+
|
364
|
+
def day_of_week(i)
|
365
|
+
alt(nil, i, :dow_range, :dow_list, :dow_class)
|
366
|
+
end
|
367
|
+
|
368
|
+
def interval(i)
|
369
|
+
alt(nil, i, :sinterval, :ninterval)
|
370
|
+
end
|
371
|
+
|
372
|
+
def every_object(i)
|
373
|
+
alt(nil, i, :day_of_month, :interval, :day_of_week)
|
374
|
+
end
|
375
|
+
def from_object(i)
|
376
|
+
alt(nil, i, :interval, :to_dow_range)
|
377
|
+
end
|
378
|
+
|
379
|
+
def tz(i)
|
380
|
+
seq(nil, i, :_in, '?', :tzone)
|
381
|
+
end
|
382
|
+
def on(i)
|
383
|
+
seq(:on, i, :_on, :weekday, :at_point, :and_at, '*')
|
384
|
+
end
|
385
|
+
def at(i)
|
386
|
+
seq(:at, i, :_at_comma, :at_point, :and_at, '*')
|
387
|
+
end
|
388
|
+
def from(i)
|
389
|
+
seq(:from, i, :_from, :from_object)
|
390
|
+
end
|
391
|
+
def every(i)
|
392
|
+
seq(:every, i, :_every, :every_object)
|
393
|
+
end
|
394
|
+
|
395
|
+
def at_from(i)
|
396
|
+
seq(nil, i, :at, :from, :tz, '?')
|
397
|
+
end
|
398
|
+
def at_every(i)
|
399
|
+
seq(nil, i, :at, :every, :tz, '?')
|
400
|
+
end
|
401
|
+
|
402
|
+
def from_at(i)
|
403
|
+
seq(nil, i, :from, :at, '?', :tz, '?')
|
227
404
|
end
|
228
405
|
|
229
|
-
def
|
406
|
+
def every_(i)
|
407
|
+
seq(nil, i, :every, :tz, '?')
|
408
|
+
end
|
409
|
+
def every_on(i)
|
410
|
+
seq(nil, i, :every, :on, :tz, '?')
|
411
|
+
end
|
412
|
+
def every_at(i)
|
413
|
+
seq(nil, i, :every, :at, :tz, '?')
|
414
|
+
end
|
230
415
|
|
231
|
-
def
|
232
|
-
|
416
|
+
def nat(i)
|
417
|
+
alt(:nat, i,
|
418
|
+
:every_at, :every_on, :every_,
|
419
|
+
:from_at,
|
420
|
+
:at_every, :at_from)
|
421
|
+
end
|
233
422
|
|
234
423
|
# rewrite parsed tree
|
235
424
|
|
236
|
-
def
|
425
|
+
#def _rewrite_single(t)
|
426
|
+
# [ t.name, rewrite(t.sublookup(nil)) ]
|
427
|
+
#end
|
428
|
+
def _rewrite_children(t)
|
429
|
+
t.subgather(nil).collect { |tt| rewrite(tt) }
|
430
|
+
end
|
431
|
+
def _rewrite_multiple(t)
|
432
|
+
[ t.name, _rewrite_children(t) ]
|
433
|
+
end
|
434
|
+
def _rewrite_child(t)
|
435
|
+
rewrite(t.sublookup(nil))
|
436
|
+
end
|
437
|
+
|
438
|
+
def rewrite_int(t); t.string.to_i; end
|
439
|
+
|
440
|
+
def rewrite_tzone(t)
|
441
|
+
|
442
|
+
[ :tz, t.strim ]
|
443
|
+
end
|
444
|
+
|
445
|
+
def rewrite_sinterval(t)
|
446
|
+
|
447
|
+
[ :interval, 1, t.strim ]
|
448
|
+
end
|
449
|
+
|
450
|
+
def rewrite_ninterval(t)
|
451
|
+
|
452
|
+
[ :interval,
|
453
|
+
t.sublookup(:int).string.to_i,
|
454
|
+
t.sublookup(:intervals).strim ]
|
455
|
+
end
|
456
|
+
|
457
|
+
def rewrite_named_digit(t)
|
458
|
+
|
459
|
+
i = t.sublookup(:int).string.to_i
|
460
|
+
|
461
|
+
case n = t.sublookup(:dname).strim
|
462
|
+
when /^s/ then [ '*', '*', i ]
|
463
|
+
when /^m/ then [ '*', i ]
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
def rewrite_named_hour(t)
|
468
|
+
NHOURS[t.strim.downcase]
|
469
|
+
end
|
470
|
+
def rewrite_numeral_hour(t)
|
471
|
+
vs = t.subgather(nil).collect { |st| st.strim.downcase }
|
472
|
+
v = NUMS.index(vs[0])
|
473
|
+
v += 12 if vs[1] == 'pm'
|
474
|
+
m = NMINUTES[vs[2]] || 0
|
475
|
+
[ v, m ]
|
476
|
+
end
|
477
|
+
def rewrite_simple_hour(t)
|
478
|
+
vs = t.subgather(nil).collect { |st| st.strim.downcase }
|
479
|
+
v = vs[0].to_i
|
480
|
+
v += 12 if vs[1] == 'pm'
|
481
|
+
[ v, 0 ]
|
482
|
+
end
|
483
|
+
def rewrite_digital_hour(t)
|
484
|
+
m = t.string.match(/(\d\d?):?(\d\d)(\s+pm)?/i)
|
485
|
+
hou = m[1].to_i; hou += 12 if m[3] && hou < 12
|
486
|
+
min = m[2].to_i
|
487
|
+
[ hou, min ]
|
488
|
+
end
|
489
|
+
|
490
|
+
def rewrite_weekday(t)
|
491
|
+
|
492
|
+
WEEKDAYS.index(t.strim.downcase[0, 3])
|
493
|
+
end
|
494
|
+
|
495
|
+
def rewrite_ordinal(t); ORDINALS[t.strim]; end
|
496
|
+
|
497
|
+
def rewrite_dom(t)
|
237
498
|
|
238
499
|
#Raabro.pp(t, colours: true)
|
239
|
-
|
240
|
-
.
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
500
|
+
[ :day_of_month,
|
501
|
+
*_rewrite_children(t).flatten.select { |e| e.is_a?(Integer) } ]
|
502
|
+
end
|
503
|
+
|
504
|
+
alias rewrite_dow _rewrite_child
|
505
|
+
|
506
|
+
def rewrite_dom_list(t); [ :dom_list, *_rewrite_children(t) ]; end
|
507
|
+
def rewrite_dow_list(t); [ :dow_list, *_rewrite_children(t) ]; end
|
508
|
+
|
509
|
+
def rewrite_dow_class(t)
|
510
|
+
|
511
|
+
[ :dow_range, 1, 5 ] # only "weekday" for now
|
512
|
+
end
|
513
|
+
|
514
|
+
def rewrite_dow_range(t)
|
515
|
+
|
516
|
+
tts = t.subgather(nil)
|
517
|
+
|
518
|
+
[ :dow_range, rewrite(tts[0]), rewrite(tts[1]) ]
|
519
|
+
end
|
520
|
+
|
521
|
+
alias rewrite_on _rewrite_multiple
|
522
|
+
alias rewrite_at _rewrite_multiple
|
523
|
+
|
524
|
+
alias rewrite_from _rewrite_child
|
525
|
+
alias rewrite_every _rewrite_child
|
526
|
+
|
527
|
+
def rewrite_nat(t)
|
528
|
+
|
529
|
+
t.subgather(nil).collect { |tt| rewrite(tt) }
|
530
|
+
#.tap { |x| pp x }
|
268
531
|
end
|
269
532
|
end
|
270
533
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fugit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Mettraux
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: raabro
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.3'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
26
|
+
version: '1.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: et-orbi
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -117,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
117
117
|
- !ruby/object:Gem::Version
|
118
118
|
version: '0'
|
119
119
|
requirements: []
|
120
|
-
rubygems_version: 3.
|
120
|
+
rubygems_version: 3.1.2
|
121
121
|
signing_key:
|
122
122
|
specification_version: 4
|
123
123
|
summary: time tools for flor
|