fugit 1.3.5 → 1.3.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d2a28ef486584f37659fbcf4e6e4fecfc76aa2a4a6e1fc61d25dd3c44cd3a5c3
4
- data.tar.gz: db726ca071f0f98d0f59c3054fca04a537ec2a17fd302013b354d90e1d7dc3c8
3
+ metadata.gz: 90b61604e15e2cb24d4fb124306affea15a644c2591fc3a49649981616351d66
4
+ data.tar.gz: 235eec423691346077fd9cfdaed895e28843ecf6681b5aa00a83cfcf9ca711a3
5
5
  SHA512:
6
- metadata.gz: d1105627f83fd730a7826047679edfd38ad7deb19960715e93769d5c04e80e0079b02b9513f9e5d01614e2e70b75a016a2e16b7a72f568e2a5d3072c42e7e1dc
7
- data.tar.gz: eb4b14f1f564bd89ae919c16d6c06ef180b725c81b8d78225661b0a0fb34dee067063de9f2b883e6361e51c0db323224b6ee0a80ab3ca80dd9091a0e872ceae4
6
+ metadata.gz: 1fd5abf6871b1cb60220bf7d6089be6bff48dfae80a05db6d031def126275940d50cbc5dfcaad493f2b6d327b66162c2a44329966459bfb3d9d5b912e3b7e68c
7
+ data.tar.gz: '08a846fcce60834f8f0c289e14317249123f1f4028c478953ed04f759e633080c4d843f55c56fb973a104e1b44bbbbc92eecc978a954d7b0b317d7b23b82611b'
@@ -2,6 +2,12 @@
2
2
  # CHANGELOG.md
3
3
 
4
4
 
5
+ ## fugit 1.3.6 released 2020-06-01
6
+
7
+ * Introduce new nat syntaxed, gh-38
8
+ * Rework nat parser
9
+
10
+
5
11
  ## fugit 1.3.5 released 2020-05-07
6
12
 
7
13
  * Implement cron @noon, gh-37
data/CREDITS.md CHANGED
@@ -1,6 +1,7 @@
1
1
 
2
2
  # fugit credits
3
3
 
4
+ * Danny Ben Shitrit https://github.com/DannyBen nat variants, gh-38
4
5
  * Dominik Sander https://github.com/dsander #rough_frequency 0, gh-36
5
6
  * Milovan Zogovic https://github.com/assembler Cron#match? vs TZ, gh-31
6
7
  * Jessica Stokes https://github.com/ticky 0-24 issue with cron, gh-30
data/README.md CHANGED
@@ -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')
@@ -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.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'
@@ -1,7 +1,7 @@
1
1
 
2
2
  module Fugit
3
3
 
4
- VERSION = '1.3.5'
4
+ VERSION = '1.3.6'
5
5
  end
6
6
 
7
7
  require 'time'
@@ -757,7 +757,7 @@ module Fugit
757
757
 
758
758
  def rewrite_tz(t)
759
759
 
760
- s = t.string.strip
760
+ s = t.strim
761
761
  z = EtOrbi.get_tzone(s)
762
762
 
763
763
  [ s, z ]
@@ -16,16 +16,7 @@ module Fugit
16
16
 
17
17
  #p s; Raabro.pp(Parser.parse(s, debug: 3), colours: true)
18
18
  #(p s; Raabro.pp(Parser.parse(s, debug: 1), colours: true)) rescue nil
19
- a = Parser.parse(s)
20
-
21
- return nil unless a
22
-
23
- return parse_crons(s, a, opts) \
24
- if a.include?([ :flag, 'every' ])
25
- return parse_crons(s, a, opts) \
26
- if a.include?([ :flag, 'from' ]) && a.find { |e| e[0] == :day_range }
27
-
28
- nil
19
+ parse_crons(s, Parser.parse(s), opts)
29
20
  end
30
21
 
31
22
  def do_parse(s, opts={})
@@ -38,16 +29,37 @@ module Fugit
38
29
 
39
30
  def parse_crons(s, a, opts)
40
31
 
41
- hms, aa = a
42
- .partition { |e| e[0] == :point && e[1][0] == :hour }
43
- ms = hms
44
- .inject({}) { |h, e| (h[e[1][1]] ||= []) << e[1][2]; h }
45
- .values
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 || [])
46
52
  .uniq
47
- crons =
48
- ms.size > 1 ?
49
- hms.collect { |e| parse_cron([ e ] + aa, opts) } :
50
- [ parse_cron(a, opts) ]
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
60
+
61
+ crons = hours
62
+ .collect { |hm| assemble_cron(h.merge(hms: hm)) }
51
63
 
52
64
  fail ArgumentError.new(
53
65
  "multiple crons in #{s.inspect} " +
@@ -61,299 +73,451 @@ module Fugit
61
73
  end
62
74
  end
63
75
 
64
- def parse_cron(a, opts)
65
-
66
- h = { min: nil, hou: nil, dom: nil, mon: nil, dow: nil }
67
- hkeys = h.keys
68
-
69
- i0s, es = a.partition { |e| e[0] == :interval0 }
70
- a = es + i0s
71
- # interval0s are fallback
72
-
73
- a.each do |key, val|
74
- case key
75
- when :biz_day
76
- (h[:dow] ||= []) << '1-5'
77
- when :name_day
78
- (h[:dow] ||= []) << val
79
- when :day_range
80
- (h[:dow] ||= []) << val.collect { |v| v.to_s[0, 3] }.join('-')
81
- when :tz
82
- h[:tz] = val
83
- when :point
84
- process_point(h, *val)
85
- when :interval1
86
- process_interval1(h, *val[0].to_h.first)
87
- when :interval0
88
- process_interval0(h, val)
89
- end
76
+ def assemble_cron(h)
77
+
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]
85
+
86
+ Fugit::Cron.parse(s.join(' '))
87
+ end
88
+
89
+ def eone(e); e1 = e[1]; e1 == 1 ? '*' : "*/#{e1}"; end
90
+
91
+ def parse_interval_elt(e, opts, h)
92
+
93
+ e1 = e[1]
94
+
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
+ h[:hms] ||= [ [ '*', eone(e) ] ]
101
+ when 'h', 'hour', 'hours'
102
+ h[:hms] ||= [ [ eone(e), 0 ] ]
103
+ when 'd', 'day', 'days'
104
+ h[:dom] = "*/#{e1}" if e1 > 1
105
+ h[:hms] ||= [ [ 0, 0 ] ]
106
+ when 'w', 'week', 'weeks'
107
+ h[:_fail] = "cannot have crons for \"every #{e1} weeks\"" if e1 > 1
108
+ h[:hms] ||= [ [ 0, 0 ] ]
109
+ h[:dow] ||= 0
110
+ when 'M', 'month', 'months'
111
+ h[:_fail] = "cannot have crons for \"every #{e1} months\"" if e1 > 12
112
+ h[:hms] ||= [ [ 0, 0 ] ]
113
+ h[:dom] = 1
114
+ h[:mon] = eone(e)
115
+ when 'Y', 'y', 'year', 'years'
116
+ h[:_fail] = "cannot have crons for \"every #{e1} years\"" if e1 > 1
117
+ h[:hms] ||= [ [ 0, 0 ] ]
118
+ h[:dom] = 1
119
+ h[:mon] = 1
90
120
  end
121
+ end
91
122
 
92
- return nil if h[:fail]
93
-
94
- h[:min] = (h[:min] || [ 0 ]).uniq
95
- h[:hou] = (h[:hou] || []).uniq.sort
96
- h[:dow].sort! if h[:dow]
123
+ def parse_dow_list_elt(e, opts, h)
97
124
 
98
- a = hkeys
99
- .collect { |k|
100
- v = h[k]
101
- (v && v.any?) ? v.collect(&:to_s).join(',') : '*' }
102
- a.insert(0, h[:sec]) if h[:sec]
103
- a << h[:tz].first if h[:tz]
125
+ h[:hms] ||= [ [ 0, 0 ] ]
126
+ h[:dow] = e[1..-1].collect(&:to_s).sort.join(',')
127
+ end
104
128
 
105
- s = a.join(' ')
129
+ def parse_dow_range_elt(e, opts, h)
106
130
 
107
- Fugit::Cron.parse(s)
131
+ h[:hms] ||= [ [ 0, 0 ] ]
132
+ h[:dow] = e[1] == e[2] ? e[1] : "#{e[1]}-#{e[2]}"
108
133
  end
109
134
 
110
- def process_point(h, key, *value)
135
+ def parse_day_of_month_elt(e, opts, h)
111
136
 
112
- case key
113
- when :hour
114
- v0, v1 = value
115
- v0 = v0.to_i if v0.is_a?(String) && v0.match(/^\d+$/)
116
- (h[:hou] ||= []) << v0
117
- (h[:min] ||= []) << v1.to_i if v1
118
- when :sec, :min
119
- (h[key] ||= []) << value[0]
120
- end
137
+ h[:dom] = e[1..-1].join(',')
121
138
  end
122
139
 
123
- def process_interval0(h, value)
124
-
125
- case value
126
- when 'sec', 'second'
127
- h[:min] = [ '*' ]
128
- h[:sec] = [ '*' ]
129
- when 'min', 'minute'
130
- h[:min] = [ '*' ]
131
- when 'hour'
132
- unless h[:min] || h[:hou]
133
- h[:min] = [ 0 ]
134
- h[:hou] = [ '*' ]
135
- end
136
- when 'day'
137
- unless h[:min] || h[:hou]
138
- h[:min] = [ 0 ]
139
- h[:hou] = [ 0 ]
140
- end
141
- when 'week'
142
- unless h[:min] || h[:hou] || h[:dow]
143
- h[:min] = [ 0 ]
144
- h[:hou] = [ 0 ]
145
- h[:dow] = [ 0 ]
146
- end
147
- when 'month'
148
- unless h[:min] || h[:hou]
149
- h[:min] = [ 0 ]
150
- h[:hou] = [ 0 ]
151
- end
152
- (h[:dom] ||= []) << 1
153
- when 'year'
154
- unless h[:min] || h[:hou]
155
- h[:min] = [ 0 ]
156
- h[:hou] = [ 0 ]
157
- end
158
- (h[:dom] ||= []) << 1
159
- (h[:mon] ||= []) << 1
160
- end
140
+ def parse_at_elt(e, opts, h)
141
+
142
+ (h[:hms] ||= []).concat(e[1])
143
+
144
+ l = h[:hms].last
145
+ h[:sec] = l.pop if l.size > 2
161
146
  end
162
147
 
163
- def process_interval1(h, interval, value)
148
+ def parse_on_elt(e, opts, h)
164
149
 
165
- if value != 1 && [ :yea, :wee ].include?(interval)
166
- int = interval == :year ? 'years' : 'weeks'
167
- h[:fail] = "cannot cron for \"every #{value} #{int}\""
168
- return
169
- end
150
+ e1 = e[1]
151
+ h[:dow] = e1[0]
152
+ h[:hms] = [ e1[1] ]
170
153
 
171
- case interval
172
- when :yea
173
- h[:hou] = [ 0 ]
174
- h[:mon] = [ 1 ]
175
- h[:dom] = [ 1 ]
176
- when :mon
177
- h[:hou] = [ 0 ]
178
- h[:dom] = [ 1 ]
179
- h[:mon] = [ value == 1 ? '*' : "*/#{value}" ]
180
- when :wee
181
- h[:hou] = [ 0 ]
182
- h[:dow] = [ 0 ] # Sunday
183
- when :day
184
- h[:hou] = [ 0 ]
185
- h[:dom] = [ value == 1 ? '*' : "*/#{value}" ]
186
- when :hou
187
- h[:hou] = [ value == 1 ? '*' : "*/#{value}" ]
188
- when :min
189
- h[:hou] = [ '*' ]
190
- h[:min] = [ value == 1 ? '*' : "*/#{value}" ]
191
- when :sec
192
- h[:hou] = [ '*' ]
193
- h[:min] = [ '*' ]
194
- h[:sec] = [ value == 1 ? '*' : "*/#{value}" ]
195
- end
154
+ l = h[:hms].last
155
+ h[:sec] = l.pop if l.size > 2
156
+ end
157
+
158
+ def parse_tz_elt(e, opts, h)
159
+
160
+ h[:tz] = e[1]
196
161
  end
197
162
  end
198
163
 
199
164
  module Parser include Raabro
200
165
 
201
166
  NUMS = %w[
202
- zero
203
- one two three four five six seven eight nine
204
- ten eleven twelve ]
167
+ zero one two three four five six seven eight nine ten eleven twelve ]
205
168
 
206
169
  WEEKDAYS =
207
170
  Fugit::Cron::Parser::WEEKDS + Fugit::Cron::Parser::WEEKDAYS
208
171
 
209
- NHOURS =
210
- { 'noon' => [ 12, 0 ], 'midnight' => [ 0, 0 ] }
172
+ NHOURS = {
173
+ 'noon' => [ 12, 0 ],
174
+ 'midnight' => [ 0, 0 ], 'oh' => [ 0, 0 ] }
175
+ NMINUTES = {
176
+ "o'clock" => 0, 'five' => 5,
177
+ 'ten' => 10, 'fifteen' => 15,
178
+ 'twenty' => 20, 'twenty-five' => 25,
179
+ 'thirty' => 30, 'thirty-five' => 35,
180
+ 'fourty' => 40, 'fourty-five' => 45,
181
+ 'fifty' => 50, 'fifty-five' => 55 }
182
+
183
+ oh = {
184
+ '1st' => 1, '2nd' => 2, '3rd' => 3, '21st' => 21, '22nd' => 22,
185
+ '23rd' => 23, '31st' => 31 }
186
+ %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 ]
187
+ .each { |i| oh["#{i}th"] = i.to_i }
188
+ %w[
189
+ first second third fourth fifth sixth seventh eighth ninth tenth
190
+ eleventh twelfth thirteenth fourteenth fifteenth sixteenth seventeenth
191
+ eighteenth nineteenth twentieth twenty-first twenty-second twenty-third
192
+ twenty-fourth twenty-fifth twenty-fifth twenty-sixth twenty-seventh
193
+ twenty-eighth twenty-ninth thirtieth thirty-first ]
194
+ .each_with_index { |e, i| oh[e] = i + 1 }
195
+ ORDINALS = oh
211
196
 
212
197
  # piece parsers bottom to top
213
198
 
214
- def interval0(i)
215
- rex(:interval0, i,
216
- /(year|month|week|day|hour|min(ute)?|sec(ond)?)(?![a-z])/i)
199
+ def _from(i); rex(nil, i, /\s*from\s+/i); end
200
+ def _every(i); rex(nil, i, /\s*(every)\s+/i); end
201
+ def _at(i); rex(nil, i, /\s*at\s+/i); end
202
+ def _in(i); rex(nil, i, /\s*(in|on)\s+/i); end
203
+ def _to(i); rex(nil, i, /\s*to\s+/i); end
204
+ def _dash(i); rex(nil, i, /-\s*/i); end
205
+ def _and(i); rex(nil, i, /\s*and\s+/i); end
206
+ def _on(i); rex(nil, i, /\s*on\s+/i); end
207
+
208
+ def _and_or_comma(i)
209
+ rex(nil, i, /\s*(,?\s*and\s|,?\s*or\s|,)\s*/i)
210
+ end
211
+ def _at_comma(i)
212
+ rex(nil, i, /\s*(at\s|,|)\s*/i)
213
+ end
214
+ def _to_through(i)
215
+ rex(nil, i, /\s*(to|through)\s+/i)
216
+ end
217
+
218
+ def integer(i); rex(:int, i, /\d+\s*/); end
219
+
220
+ def tz_name(i)
221
+ rex(nil, i,
222
+ /\s*[A-Z][a-zA-Z0-9+\-]+(\/[A-Z][a-zA-Z0-9+\-_]+){0,2}(\s+|$)/)
223
+ end
224
+ def tz_delta(i)
225
+ rex(nil, i,
226
+ /\s*[-+]([01][0-9]|2[0-4]):?(00|15|30|45)(\s+|$)/)
227
+ end
228
+ def tzone(i)
229
+ alt(:tzone, i, :tz_delta, :tz_name)
230
+ end
231
+
232
+ def and_named_digits(i)
233
+ rex(:xxx, i, 'TODO')
234
+ end
235
+
236
+ def dname(i)
237
+ rex(:dname, i, /(s(ec(onds?)?)?|m(in(utes?)?)?)\s+/i)
238
+ end
239
+ def named_digit(i)
240
+ seq(:named_digit, i, :dname, :integer)
241
+ end
242
+ def named_digits(i)
243
+ seq(nil, i, :named_digit, '+', :and_named_digits, '*')
217
244
  end
218
245
 
219
246
  def am_pm(i)
220
- rex(:am_pm, i, / *(am|pm)/i)
247
+ rex(:am_pm, i, /\s*(am|pm|dark)\s*/i)
248
+ end
249
+
250
+ def nminute(i)
251
+ rex(:nminute, i, /(#{NMINUTES.keys.join('|')})\s*/i)
252
+ end
253
+ def nhour(i)
254
+ rex(:nhour, i, /(#{NUMS.join('|')})\s*/i)
255
+ end
256
+ def numeral_hour(i)
257
+ seq(:numeral_hour, i, :nhour, :am_pm, '?', :nminute, '?')
258
+ end
259
+
260
+ def named_hour(i)
261
+ rex(:named_hour, i, /(#{NHOURS.keys.join('|')})/i)
262
+ end
263
+
264
+ def shour(i)
265
+ rex(:shour, i, /(2[0-4]|[01]?[0-9])/)
266
+ end
267
+ def simple_hour(i)
268
+ seq(:simple_hour, i, :shour, :am_pm, '?')
221
269
  end
222
270
 
223
271
  def digital_hour(i)
224
272
  rex(:digital_hour, i, /(2[0-4]|[01][0-9]):?[0-5]\d/)
225
273
  end
226
274
 
227
- def _simple_hour(i)
228
- rex(:sh, i, /(2[0-4]|[01]?[0-9])/)
275
+ def at_point(i)
276
+ alt(nil, i,
277
+ :digital_hour, :simple_hour, :named_hour, :numeral_hour,
278
+ :named_digits)
229
279
  end
230
- def simple_hour(i)
231
- seq(:simple_hour, i, :_simple_hour, :am_pm, '?')
280
+
281
+ def weekday(i)
282
+ rex(:weekday, i, /(#{WEEKDAYS.reverse.join('|')})\s*/i)
232
283
  end
233
284
 
234
- def _numeral_hour(i)
235
- rex(:nh, i, /(#{NUMS.join('|')})/i)
285
+ def and_at(i)
286
+ seq(nil, i, :_and_or_comma, :at_point)
236
287
  end
237
- def numeral_hour(i)
238
- seq(:numeral_hour, i, :_numeral_hour, :am_pm, '?')
288
+
289
+ def _intervals(i)
290
+ rex(:intervals, i,
291
+ /(
292
+ y(ears?)?|months?|w(eeks?)?|d(ays?)?|
293
+ h(ours?)?|m(in(ute)?s?)?|s(ec(ond)?s?)?
294
+ )(\s+|$)/ix)
295
+ end
296
+
297
+ def sinterval(i)
298
+ rex(:sinterval, i,
299
+ /(year|month|week|day|hour|min(ute)?|sec(ond)?)(\s+|$)/i)
300
+ end
301
+ def ninterval(i)
302
+ seq(:ninterval, i, :integer, :_intervals)
239
303
  end
240
304
 
241
- def name_hour(i)
242
- rex(:name_hour, i, /(#{NHOURS.keys.join('|')})/i)
305
+ def ordinal(i)
306
+ rex(:ordinal, i, /\s*(#{ORDINALS.keys.join('|')})\s*/)
243
307
  end
244
308
 
245
- def biz_day(i); rex(:biz_day, i, /(biz|business|week) *day/i); end
246
- def name_day(i); rex(:name_day, i, /#{WEEKDAYS.reverse.join('|')}/i); end
309
+ def _mod(i); rex(nil, i, /\s*month\s+on\s+days?\s+/i); end
310
+ def _oftm(i); rex(nil, i, /\s*(day\s)?\s*of\s+the\s+month\s*/i); end
247
311
 
248
- def range_sep(i); rex(nil, i, / *- *| +(to|through) +/); end
312
+ def dom(i)
313
+ rex(:int, i, /([12][0-9]|3[01]|[0-9])/)
314
+ end
315
+ def and_or_dom(i)
316
+ seq(nil, i, :_and_or_comma, :dom)
317
+ end
318
+ def dom_list(i)
319
+ seq(:dom_list, i, :dom, :and_or_dom, '*')
320
+ end
321
+
322
+ def dom_mod(i) # every month on day
323
+ seq(:dom, i, :_mod, :dom_list)
324
+ end
325
+ def dom_noftm(i) # every nth of month
326
+ seq(:dom, i, :ordinal, :_oftm)
327
+ end
328
+ def day_of_month(i)
329
+ alt(nil, i, :dom_noftm, :dom_mod)
330
+ end
249
331
 
250
- def day_range(i)
251
- seq(:day_range, i, :name_day, :range_sep, :name_day)
332
+ def dow_class(i)
333
+ rex(:dow_class, i, /(weekday)(\s+|$)/i)
252
334
  end
253
335
 
254
- def _tz_name(i)
255
- rex(nil, i, /[A-Z][a-zA-Z0-9+\-]+(\/[A-Z][a-zA-Z0-9+\-_]+){0,2}/)
336
+ def dow(i)
337
+ seq(:dow, i, :weekday)
256
338
  end
257
- def _tz_delta(i)
258
- rex(nil, i, /[-+]([01][0-9]|2[0-4]):?(00|15|30|45)/)
339
+ def and_or_dow(i)
340
+ seq(nil, i, :_and_or_comma, :dow)
341
+ end
342
+ def dow_list(i)
343
+ seq(:dow_list, i, :dow, :and_or_dow, '*')
259
344
  end
260
- def _tz(i); alt(:tz, i, :_tz_delta, :_tz_name); end
261
345
 
262
- def interval1(i)
263
- rex(:interval1, i,
264
- /
265
- \d+
266
- \s?
267
- (y(ears?)?|months?|w(eeks?)?|d(ays?)?|
268
- h(ours?)?|m(in(ute)?s?)?|s(ec(ond)?s?)?)
269
- /ix)
346
+ def to_dow_range(i)
347
+ seq(:dow_range, i, :weekday, :_to_through, :weekday)
348
+ end
349
+ def dash_dow_range(i)
350
+ seq(:dow_range, i, :weekday, :_dash, :weekday)
351
+ end
352
+ def dow_range(i)
353
+ alt(nil, i, :to_dow_range, :dash_dow_range)
270
354
  end
271
355
 
272
- def min_or_sec(i)
273
- rex(:min_or_sec, i, /(min(ute)?|sec(ond)?)\s+\d+/i)
356
+ def day_of_week(i)
357
+ alt(nil, i, :dow_range, :dow_list, :dow_class)
274
358
  end
275
359
 
276
- def point(i)
277
- alt(:point, i,
278
- :min_or_sec,
279
- :name_hour, :numeral_hour, :digital_hour, :simple_hour)
360
+ def interval(i)
361
+ alt(nil, i, :sinterval, :ninterval)
280
362
  end
281
363
 
282
- def flag(i); rex(:flag, i, /(every|from|at|after|on|in)/i); end
364
+ def every_object(i)
365
+ alt(nil, i, :day_of_month, :interval, :day_of_week)
366
+ end
367
+ def from_object(i)
368
+ alt(nil, i, :interval, :to_dow_range)
369
+ end
283
370
 
284
- def datum(i)
285
- alt(nil, i,
286
- :flag,
287
- :interval1,
288
- :point,
289
- :interval0,
290
- :day_range, :biz_day, :name_day,
291
- :_tz)
371
+ def tz(i)
372
+ seq(nil, i, :_in, '?', :tzone)
373
+ end
374
+ def on(i)
375
+ seq(:on, i, :_on, :weekday, :at_point, :and_at, '*')
376
+ end
377
+ def at(i)
378
+ seq(:at, i, :_at_comma, :at_point, :and_at, '*')
379
+ end
380
+ def from(i)
381
+ seq(:from, i, :_from, :from_object)
382
+ end
383
+ def every(i)
384
+ seq(:every, i, :_every, :every_object)
292
385
  end
293
386
 
294
- def sugar(i); rex(nil, i, /(and|or|[, \t]+)/i); end
387
+ def at_from(i)
388
+ seq(nil, i, :at, :from, :tz, '?')
389
+ end
390
+ def at_every(i)
391
+ seq(nil, i, :at, :every, :tz, '?')
392
+ end
393
+
394
+ def from_at(i)
395
+ seq(nil, i, :from, :at, '?', :tz, '?')
396
+ end
397
+
398
+ def every_(i)
399
+ seq(nil, i, :every, :tz, '?')
400
+ end
401
+ def every_on(i)
402
+ seq(nil, i, :every, :on, :tz, '?')
403
+ end
404
+ def every_at(i)
405
+ seq(nil, i, :every, :at, :tz, '?')
406
+ end
295
407
 
296
- def elt(i); alt(nil, i, :sugar, :datum); end
297
- def nat(i); rep(:nat, i, :elt, 1); end
408
+ def nat(i)
409
+ alt(:nat, i,
410
+ :every_at, :every_on, :every_,
411
+ :from_at,
412
+ :at_every, :at_from)
413
+ end
298
414
 
299
415
  # rewrite parsed tree
300
416
 
301
- def _rewrite(t)
302
- [ t.name, t.string.downcase ]
417
+ #def _rewrite_single(t)
418
+ # [ t.name, rewrite(t.sublookup(nil)) ]
419
+ #end
420
+ def _rewrite_children(t)
421
+ t.subgather(nil).collect { |tt| rewrite(tt) }
422
+ end
423
+ def _rewrite_multiple(t)
424
+ [ t.name, _rewrite_children(t) ]
425
+ end
426
+ def _rewrite_child(t)
427
+ rewrite(t.sublookup(nil))
428
+ end
429
+
430
+ def rewrite_int(t); t.string.to_i; end
431
+
432
+ def rewrite_tzone(t)
433
+
434
+ [ :tz, t.strim ]
303
435
  end
304
- alias rewrite_flag _rewrite
305
- alias rewrite_interval0 _rewrite
306
- alias rewrite_biz_day _rewrite
307
436
 
308
- def rewrite_name_day(t)
309
- [ :name_day, WEEKDAYS.index(t.string.downcase[0, 3]) ]
437
+ def rewrite_sinterval(t)
438
+
439
+ [ :interval, 1, t.strim ]
310
440
  end
311
441
 
312
- def rewrite_day_range(t)
313
- [ :day_range, t.subgather(nil).collect { |st| st.string.downcase } ]
442
+ def rewrite_ninterval(t)
443
+
444
+ [ :interval,
445
+ t.sublookup(:int).string.to_i,
446
+ t.sublookup(:intervals).strim ]
314
447
  end
315
448
 
316
- def rewrite_name_hour(t)
317
- [ :hour, *NHOURS[t.string.strip.downcase] ]
449
+ def rewrite_named_digit(t)
450
+
451
+ i = t.sublookup(:int).string.to_i
452
+
453
+ case n = t.sublookup(:dname).strim
454
+ when /^s/ then [ '*', '*', i ]
455
+ when /^m/ then [ '*', i ]
456
+ end
457
+ end
458
+
459
+ def rewrite_named_hour(t)
460
+ NHOURS[t.strim.downcase]
318
461
  end
319
462
  def rewrite_numeral_hour(t)
320
- vs = t.subgather(nil).collect { |st| st.string.downcase.strip }
463
+ vs = t.subgather(nil).collect { |st| st.strim.downcase }
321
464
  v = NUMS.index(vs[0])
322
465
  v += 12 if vs[1] == 'pm'
323
- [ :hour, v, 0 ]
466
+ m = NMINUTES[vs[2]] || 0
467
+ [ v, m ]
324
468
  end
325
469
  def rewrite_simple_hour(t)
326
- vs = t.subgather(nil).collect { |st| st.string.downcase.strip }
470
+ vs = t.subgather(nil).collect { |st| st.strim.downcase }
327
471
  v = vs[0].to_i
328
472
  v += 12 if vs[1] == 'pm'
329
- [ :hour, v, 0 ]
473
+ [ v, 0 ]
330
474
  end
331
475
  def rewrite_digital_hour(t)
332
- v = t.string.gsub(/:/, '')
333
- [ :hour, v[0, 2], v[2, 2] ]
476
+ m = t.string.match(/(\d\d?):?(\d\d)/)
477
+ [ m[1].to_i, m[2].to_i ]
334
478
  end
335
479
 
336
- def rewrite_min_or_sec(t)
337
- unit, num = t.string.split(/\s+/)
338
- [ unit[0, 3].to_sym, num.to_i ]
480
+ def rewrite_weekday(t)
481
+
482
+ WEEKDAYS.index(t.strim.downcase[0, 3])
339
483
  end
340
484
 
341
- def rewrite_point(t)
342
- [ :point, rewrite(t.sublookup) ]
485
+ def rewrite_ordinal(t); ORDINALS[t.strim]; end
486
+
487
+ def rewrite_dom(t)
488
+
489
+ #Raabro.pp(t, colours: true)
490
+ [ :day_of_month,
491
+ *_rewrite_children(t).flatten.select { |e| e.is_a?(Integer) } ]
343
492
  end
344
493
 
345
- def rewrite_tz(t)
346
- [ :tz, [ t.string.strip, EtOrbi.get_tzone(t.string.strip) ] ]
494
+ alias rewrite_dow _rewrite_child
495
+
496
+ def rewrite_dom_list(t); [ :dom_list, *_rewrite_children(t) ]; end
497
+ def rewrite_dow_list(t); [ :dow_list, *_rewrite_children(t) ]; end
498
+
499
+ def rewrite_dow_class(t)
500
+
501
+ [ :dow_range, 1, 5 ] # only "weekday" for now
347
502
  end
348
503
 
349
- def rewrite_interval1(t)
350
- [ t.name, [ Fugit::Duration.parse(t.string.strip) ] ]
504
+ def rewrite_dow_range(t)
505
+
506
+ tts = t.subgather(nil)
507
+
508
+ [ :dow_range, rewrite(tts[0]), rewrite(tts[1]) ]
351
509
  end
352
510
 
511
+ alias rewrite_on _rewrite_multiple
512
+ alias rewrite_at _rewrite_multiple
513
+
514
+ alias rewrite_from _rewrite_child
515
+ alias rewrite_every _rewrite_child
516
+
353
517
  def rewrite_nat(t)
354
518
 
355
- #Raabro.pp(t, colours: true)
356
519
  t.subgather(nil).collect { |tt| rewrite(tt) }
520
+ #.tap { |x| pp x }
357
521
  end
358
522
  end
359
523
  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.5
4
+ version: 1.3.6
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-05-07 00:00:00.000000000 Z
11
+ date: 2020-06-01 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.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.1'
26
+ version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: et-orbi
29
29
  requirement: !ruby/object:Gem::Requirement