fugit 1.1.9 → 1.1.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 35836e95c82a113fe2e5222a02522ab2bf36f1b0
4
- data.tar.gz: 0fb6db1cb77893af937354da715b2eb8b14403f5
3
+ metadata.gz: a7fb0dc867cacf79033c0f54f5780cdc5a567106
4
+ data.tar.gz: e06aec6abab852f7ea09c459353bbcbb42c007ee
5
5
  SHA512:
6
- metadata.gz: 7de61477e96c9612542641787346fb154394d8388eccccaeb1be257cb57410abe4e23d1377148539d92852674df3c58d0a44c9cc4816c50cd157515f185d59da
7
- data.tar.gz: c1f23c4a8395ddc29a85415300608fbc45d5900cbb42c502fd51f02f7f8c5f6fe945fe9b010349e9bde6fc1df6f3ec105a977c8705722820be41c65b47656ff7
6
+ metadata.gz: 55c7bdcaa5820e11f83b5d61e66bf44a6de98cd778e1ca80daefacf2e71fd0707696ec1161896738b4934125ba63881fc7023e89fbe27a1be24495dabc6a0ae5
7
+ data.tar.gz: 8b3471be0e7710016eabcb5ba26ca01463e0463fd370c290d91bea9c41883896cffb03dbc65aad62d8f51a9a8aa821ab02b6020dfda67725908357902ebd3b97
@@ -2,6 +2,12 @@
2
2
  # CHANGELOG.md
3
3
 
4
4
 
5
+ ## fugit 1.1.10 released 2019-04-12
6
+
7
+ * Implement `"0 9 * * sun%2+1"`
8
+ * Simplify cron parser
9
+
10
+
5
11
  ## fugit 1.1.9 released 2019-03-26
6
12
 
7
13
  * Fix cron `"0 9 29 feb *"` endless loop, gh-18
data/Makefile CHANGED
@@ -11,6 +11,9 @@ count_lines:
11
11
  find spec -name "*_spec.rb" | xargs cat | ruby -e "p STDIN.readlines.count { |l| l = l.strip; l[0, 1] != '#' && l != '' }"
12
12
  cl: count_lines
13
13
 
14
+ scan:
15
+ scan lib/**/*.rb
16
+
14
17
  gemspec_validate:
15
18
  @echo "---"
16
19
  ruby -e "s = eval(File.read(Dir['*.gemspec'].first)); p s.validate"
@@ -48,5 +51,5 @@ tzones:
48
51
  # bundle exec ruby -r tzinfo -r tzinfo-data -e "::TZInfo::Timezone.all.each { |tz| p tz.name }"
49
52
 
50
53
 
51
- .PHONY: count_lines gemspec_validate name cw build push spec info tzones
54
+ .PHONY: count_lines scan gemspec_validate name cw build push spec info tzones
52
55
 
data/README.md CHANGED
@@ -104,6 +104,31 @@ Example of cron strings understood by fugit:
104
104
  # and more...
105
105
  ```
106
106
 
107
+ ### the modulo extension
108
+
109
+ Fugit, since 1.1.10, also understands cron strings like "`9 0 * * sun%2`" which can be read as "every other Sunday at 9am".
110
+
111
+ For odd Sundays, one can write `9 0 * * sun%2+1`.
112
+
113
+ It can be combined, as in `9 0 * * sun%2,tue%3+2`
114
+
115
+ But what does it references to? It starts at 1 on 2019-01-01.
116
+
117
+ ```ruby
118
+ require 'et-orbi' # >= 1.1.8
119
+
120
+ # the reference
121
+ p EtOrbi.parse('2019-01-01').wday # => 2
122
+ p EtOrbi.parse('2019-01-01').rweek # => 1
123
+ p EtOrbi.parse('2019-01-01').rweek % 2 # => 1
124
+
125
+ # today (as of this coding...)
126
+ p EtOrbi.parse('2019-04-11').wday # => 4
127
+ p EtOrbi.parse('2019-04-11').rweek # => 15
128
+ p EtOrbi.parse('2019-04-11').rweek % 2 # => 1
129
+ ```
130
+
131
+
107
132
  ## `Fugit::Duration`
108
133
 
109
134
  A class `Fugit::Duration` to parse duration strings (vanilla [rufus-scheduler](https://github.com/jmettraux/rufus-scheduler) ones and [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) ones).
@@ -41,7 +41,7 @@ Time tools for flor and the floraison project. Cron parsing and occurrence compu
41
41
  # this dependency appears in 'et-orbi'
42
42
 
43
43
  s.add_runtime_dependency 'raabro', '~> 1.1'
44
- s.add_runtime_dependency 'et-orbi', '~> 1.1', '>= 1.1.7'
44
+ s.add_runtime_dependency 'et-orbi', '~> 1.1', '>= 1.1.8'
45
45
 
46
46
  s.add_development_dependency 'rspec', '~> 3.7'
47
47
  s.add_development_dependency 'chronic', '~> 0.10'
@@ -1,7 +1,7 @@
1
1
 
2
2
  module Fugit
3
3
 
4
- VERSION = '1.1.9'
4
+ VERSION = '1.1.10'
5
5
  end
6
6
 
7
7
  require 'time'
@@ -11,8 +11,7 @@ module Fugit
11
11
  '@weekly' => '0 0 * * 0',
12
12
  '@daily' => '0 0 * * *',
13
13
  '@midnight' => '0 0 * * *',
14
- '@hourly' => '0 * * * *',
15
- }
14
+ '@hourly' => '0 * * * *' }
16
15
 
17
16
  attr_reader :original, :zone
18
17
  attr_reader :seconds, :minutes, :hours, :monthdays, :months, :weekdays, :timezone
@@ -49,17 +48,15 @@ module Fugit
49
48
 
50
49
  def to_cron_s
51
50
 
52
- @cron_s ||= begin
53
- [
54
- @seconds == [ 0 ] ? nil : (@seconds || [ '*' ]).join(','),
55
- (@minutes || [ '*' ]).join(','),
56
- (@hours || [ '*' ]).join(','),
57
- (@monthdays || [ '*' ]).join(','),
58
- (@months || [ '*' ]).join(','),
59
- (@weekdays || [ [ '*' ] ]).map { |d| d.compact.join('#') }.join(','),
60
- @timezone ? @timezone.name : nil
61
- ].compact.join(' ')
62
- end
51
+ @cron_s ||= [
52
+ @seconds == [ 0 ] ? nil : (@seconds || [ '*' ]).join(','),
53
+ (@minutes || [ '*' ]).join(','),
54
+ (@hours || [ '*' ]).join(','),
55
+ (@monthdays || [ '*' ]).join(','),
56
+ (@months || [ '*' ]).join(','),
57
+ (@weekdays || [ [ '*' ] ]).map { |d| d.compact.join('#') }.join(','),
58
+ @timezone ? @timezone.name : nil
59
+ ].compact.join(' ')
63
60
  end
64
61
 
65
62
  class TimeCursor
@@ -73,7 +70,7 @@ module Fugit
73
70
  def time; @t; end
74
71
  def to_i; @t.to_i; end
75
72
 
76
- %w[ year month day wday hour min sec wday_in_month ]
73
+ %w[ year month day wday hour min sec wday_in_month rweek rday ]
77
74
  .collect(&:to_sym).each { |k| define_method(k) { @t.send(k) } }
78
75
 
79
76
  def inc(i)
@@ -140,21 +137,35 @@ module Fugit
140
137
  def min_match?(nt); ( ! @minutes) || @minutes.include?(nt.min); end
141
138
  def sec_match?(nt); ( ! @seconds) || @seconds.include?(nt.sec); end
142
139
 
140
+ def weekday_hash_match?(nt, hsh)
141
+
142
+ phsh, nhsh = nt.wday_in_month
143
+
144
+ if hsh > 0
145
+ hsh == phsh # positive wday, from the beginning of the month
146
+ else
147
+ hsh == nhsh # negative wday, from the end of the month, -1 == last
148
+ end
149
+ end
150
+
151
+ def weekday_modulo_match?(nt, mod)
152
+
153
+ nt.rweek % mod[0] == mod[1]
154
+ end
155
+
143
156
  def weekday_match?(nt)
144
157
 
145
158
  return true if @weekdays.nil?
146
159
 
147
- wd, hsh = @weekdays.find { |d, _| d == nt.wday }
160
+ wd, hom = @weekdays.find { |d, _| d == nt.wday }
148
161
 
149
162
  return false unless wd
150
- return true if hsh.nil?
163
+ return true if hom.nil?
151
164
 
152
- phsh, nhsh = nt.wday_in_month
153
-
154
- if hsh > 0
155
- hsh == phsh # positive wday, from the beginning of the month
165
+ if hom.is_a?(Array)
166
+ weekday_modulo_match?(nt, hom)
156
167
  else
157
- hsh == nhsh # negative wday, from the end of the month, -1 == last
168
+ weekday_hash_match?(nt, hom)
158
169
  end
159
170
  end
160
171
 
@@ -487,11 +498,11 @@ module Fugit
487
498
 
488
499
  @weekdays = []
489
500
 
490
- arr.each do |a, z, s, h| # a to z, slash and hash
491
- if h
492
- @weekdays << [ a, h ]
493
- elsif s
494
- ((a || 0)..(z || (a ? a : 6))).step(s < 1 ? 1 : s)
501
+ arr.each do |a, z, sl, ha, mo| # a to z, slash, hash, and mod
502
+ if ha || mo
503
+ @weekdays << [ a, ha || mo ]
504
+ elsif sl
505
+ ((a || 0)..(z || (a ? a : 6))).step(sl < 1 ? 1 : sl)
495
506
  .each { |i| @weekdays << [ i ] }
496
507
  elsif z
497
508
  (a..z).each { |i| @weekdays << [ i ] }
@@ -527,20 +538,14 @@ module Fugit
527
538
 
528
539
  def slash(i); rex(:slash, i, /\/\d\d?/); end
529
540
 
530
- def core_mos(i); rex(:mos, i, /[0-5]?\d/); end # min or sec
531
- def core_hou(i); rex(:hou, i, /(2[0-4]|[01]?[0-9])/); end
532
- def core_dom(i); rex(:dom, i, /(-?(3[01]|[12][0-9]|0?[1-9])|last|l)/i); end
533
- def core_mon(i); rex(:mon, i, /(1[0-2]|0?[1-9]|#{MONTHS[1..-1].join('|')})/i); end
534
- def core_dow(i); rex(:dow, i, /([0-7]|#{WEEKDS.join('|')})/i); end
541
+ def mos(i); rex(:mos, i, /[0-5]?\d/); end # min or sec
542
+ def hou(i); rex(:hou, i, /(2[0-4]|[01]?[0-9])/); end
543
+ def dom(i); rex(:dom, i, /(-?(3[01]|[12][0-9]|0?[1-9])|last|l)/i); end
544
+ def mon(i); rex(:mon, i, /(1[0-2]|0?[1-9]|#{MONTHS[1..-1].join('|')})/i); end
545
+ def dow(i); rex(:dow, i, /([0-7]|#{WEEKDS.join('|')})/i); end
535
546
 
536
547
  def dow_hash(i); rex(:hash, i, /#(-?[1-5]|last|l)/i); end
537
548
 
538
- def mos(i); core_mos(i); end
539
- def hou(i); core_hou(i); end
540
- def dom(i); core_dom(i); end
541
- def mon(i); core_mon(i); end
542
- def dow(i); core_dow(i); end
543
-
544
549
  def _mos(i); seq(nil, i, :hyphen, :mos); end
545
550
  def _hou(i); seq(nil, i, :hyphen, :hou); end
546
551
  def _dom(i); seq(nil, i, :hyphen, :dom); end
@@ -568,9 +573,12 @@ module Fugit
568
573
  def sorws_mon(i); seq(:elt, i, :sor_mon, :slash, '?'); end
569
574
  def sorws_dow(i); seq(:elt, i, :sor_dow, :slash, '?'); end
570
575
 
571
- def h_dow(i); seq(:elt, i, :core_dow, :dow_hash); end
576
+ def mod(i); rex(:mod, i, /%\d+(\+\d+)?/); end
577
+
578
+ def mod_dow(i); seq(:elt, i, :dow, :mod); end
579
+ def h_dow(i); seq(:elt, i, :dow, :dow_hash); end
572
580
 
573
- def _sorws_dow(i); alt(nil, i, :h_dow, :sorws_dow); end
581
+ def _sorws_dow(i); alt(nil, i, :h_dow, :mod_dow, :sorws_dow); end
574
582
 
575
583
  def list_sec(i); jseq(:sec, i, :sorws_mos, :comma); end
576
584
  def list_min(i); jseq(:min, i, :sorws_mos, :comma); end
@@ -607,7 +615,7 @@ module Fugit
607
615
 
608
616
  # rewriting the parsed tree
609
617
 
610
- def to_i(k, t)
618
+ def rewrite_bound(k, t)
611
619
 
612
620
  s = t.string.downcase
613
621
 
@@ -617,23 +625,38 @@ module Fugit
617
625
  s.to_i
618
626
  end
619
627
 
628
+ def rewrite_mod(k, t)
629
+
630
+ mod, plus = t.string
631
+ .split(/[%+]/).reject(&:empty?).collect(&:to_i)
632
+
633
+ [ mod, plus || 0 ]
634
+ end
635
+
620
636
  def rewrite_elt(k, t)
621
637
 
622
- (a, z), others = t
623
- .subgather(nil)
624
- .partition { |tt| ![ :hash, :slash ].include?(tt.name) }
625
- s = others.find { |tt| tt.name == :slash }
626
- h = others.find { |tt| tt.name == :hash }
638
+ at, zt, slt, hat, mot = nil; t.subgather(nil).each do |tt|
639
+ case tt.name
640
+ when :slash then slt = tt
641
+ when :hash then hat = tt
642
+ when :mod then mot = tt
643
+ else if at; zt ||= tt; else; at = tt; end
644
+ end
645
+ end
646
+
647
+ sl = slt ? slt.string[1..-1].to_i : nil
648
+
649
+ ha = hat ? hat.string[1..-1] : nil
650
+ ha = -1 if ha && ha.upcase[0, 1] == 'L'
651
+ ha = ha.to_i if ha
627
652
 
628
- h = h ? h.string[1..-1] : nil
629
- h = -1 if h && h.upcase[0, 1] == 'L'
630
- h = h.to_i if h
653
+ mo = mot ? rewrite_mod(k, mot) : nil
631
654
 
632
- a = a ? to_i(k, a) : nil
633
- z = z ? to_i(k, z) : nil
655
+ a = at ? rewrite_bound(k, at) : nil
656
+ z = zt ? rewrite_bound(k, zt) : nil
634
657
  a, z = z, a if a && z && a > z
635
658
 
636
- [ a, z, s ? s.string[1..-1].to_i : nil, h ]
659
+ [ a, z, sl, ha, mo ]
637
660
  end
638
661
 
639
662
  def rewrite_entry(t)
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.1.9
4
+ version: 1.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Mettraux
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-25 00:00:00.000000000 Z
11
+ date: 2019-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: raabro
@@ -33,7 +33,7 @@ dependencies:
33
33
  version: '1.1'
34
34
  - - ">="
35
35
  - !ruby/object:Gem::Version
36
- version: 1.1.7
36
+ version: 1.1.8
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '1.1'
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: 1.1.7
46
+ version: 1.1.8
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rspec
49
49
  requirement: !ruby/object:Gem::Requirement