Skip to content

Commit

Permalink
Let & in cron, day-of-month AND day-of-week, gh-78
Browse files Browse the repository at this point in the history
  • Loading branch information
jmettraux committed Sep 14, 2022
1 parent 980f4a5 commit 29c9874
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

## fugit 1.7.0 not yet released

* Introduce the & cron syntax (day-of-month AND day-of-week), gh-78
* Change how cron deals with modulo and offset, gh-76
* Be liberal with extra commas, gh-77

Expand Down
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,34 @@ The man page says:
Fugit follows this specification.

There is a solution though, please read on.
Since fugit 1.7.0, by adding `&` right after a day specifier, the `day-of-month OR day-of-week` becomes `day-of-month AND day-of-week`.

```ruby
# standard cron

p Fugit.parse_cron('0 0 */2 * 1-5').next_time('2022-08-09').to_s
# ==> "2022-08-10 00:00:00 +0900"

# with an &

p Fugit.parse_cron('0 0 */2 * 1-5&').next_time('2022-08-09').to_s # or
p Fugit.parse_cron('0 0 */2& * 1-5').next_time('2022-08-09').to_s
p Fugit.parse_cron('0 0 */2& * 1-5&').next_time('2022-08-09').to_s
# ==> "2022-08-11 00:00:00 +0900"


# standard cron

p Fugit.parse_cron('59 6 1-7 * 2').next_time('2020-03-15').to_s
# ==> "2020-03-17 06:59:00 +0900"

# with an &

p Fugit.parse_cron('59 6 1-7 * 2&').next_time('2020-03-15').to_s
p Fugit.parse_cron('59 6 1-7& * 2').next_time('2020-03-15').to_s
p Fugit.parse_cron('59 6 1-7& * 2&').next_time('2020-03-15').to_s
# ==> "2020-04-07 06:59:00 +0900"
```

### the hash extension

Expand Down
25 changes: 19 additions & 6 deletions lib/fugit/cron.rb
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,14 @@ def monthday_match?(nt)

def day_match?(nt)

return weekday_match?(nt) || monthday_match?(nt) \
if @weekdays && @monthdays
if @weekdays && @monthdays

return weekday_match?(nt) && monthday_match?(nt) \
if @day_and
#
# extension for fugit, gh-78

return weekday_match?(nt) || monthday_match?(nt)
#
# From `man 5 crontab`
#
Expand All @@ -212,6 +218,8 @@ def day_match?(nt)
# at 4:30 am on the 1st and 15th of each month, plus every Friday.
#
# as seen in gh-5 and gh-35
end


return false unless weekday_match?(nt)
return false unless monthday_match?(nt)
Expand Down Expand Up @@ -482,6 +490,7 @@ def init(original, h)

@original = original
@cron_s = nil # just to be sure
@day_and = h[:&]

determine_seconds(h[:sec])
determine_minutes(h[:min])
Expand Down Expand Up @@ -662,6 +671,7 @@ def star(i); str(nil, i, '*'); end
def hyphen(i); str(nil, i, '-'); end
def comma(i); rex(nil, i, /,([ \t]*,)*/); end
def comma?(i); rex(nil, i, /([ \t]*,)*/); end
def and?(i); rex(nil, i, /&?/); end

def slash(i); rex(:slash, i, /\/\d\d?/); end

Expand Down Expand Up @@ -724,9 +734,9 @@ def list_dow(i); jseq(:dow, i, :dow_elt_, :comma); end
def lsec_(i); seq(nil, i, :comma?, :list_sec, :comma?, :s); end
def lmin_(i); seq(nil, i, :comma?, :list_min, :comma?, :s); end
def lhou_(i); seq(nil, i, :comma?, :list_hou, :comma?, :s); end
def ldom_(i); seq(nil, i, :comma?, :list_dom, :comma?, :s); end
def ldom_(i); seq(nil, i, :comma?, :list_dom, :comma?, :and?, :s); end
def lmon_(i); seq(nil, i, :comma?, :list_mon, :comma?, :s); end
def ldow(i); seq(nil, i, :comma?, :list_dow, :comma?); end
def ldow(i); seq(nil, i, :comma?, :list_dow, :comma?, :and?); end

def _tz_name(i)
rex(nil, i, / +[A-Z][a-zA-Z0-9+\-]+(\/[A-Z][a-zA-Z0-9+\-_]+){0,2}/)
Expand All @@ -737,10 +747,12 @@ def _tz_delta(i)
def _tz(i); alt(:tz, i, :_tz_delta, :_tz_name); end

def classic_cron(i)
seq(:ccron, i, :lmin_, :lhou_, :ldom_, :lmon_, :ldow, :_tz, '?')
seq(:ccron, i,
:lmin_, :lhou_, :ldom_, :lmon_, :ldow, :_tz, '?')
end
def second_cron(i)
seq(:scron, i, :lsec_, :lmin_, :lhou_, :ldom_, :lmon_, :ldow, :_tz, '?')
seq(:scron, i,
:lsec_, :lmin_, :lhou_, :ldom_, :lmon_, :ldow, :_tz, '?')
end

def cron(i)
Expand Down Expand Up @@ -822,6 +834,7 @@ def rewrite_cron(t)
.inject({}) { |h, tt|
h[tt.name] = tt.name == :tz ? rewrite_tz(tt) : rewrite_entry(tt)
h }
hcron[:&] = true if t.string.index('&')

z, tz = hcron[:tz]; return nil if z && ! tz

Expand Down
15 changes: 15 additions & 0 deletions spec/cron_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,21 @@
[ '30 18 * * 2#5', '2022-03-29 18:30', '2022-03-08', 'UTC' ],
[ '30 18 * * 2#5', '2022-03-29 18:30', '2022-03-08', 'Europe/Paris' ],
[ '30 18 * * 2#5 Europe/Paris', '2022-03-29 16:30', '2022-03-08', 'UTC' ],

# gh-78
# by way of gh-75

[ '0 0 */2 * 1-5', '2022-08-10 00:00', '2022-08-09', 'UTC' ],
[ '0 0 */2 * 1-5&', '2022-08-11 00:00', '2022-08-09', 'UTC' ],
[ '0 0 */2& * 1-5', '2022-08-11 00:00', '2022-08-09', 'UTC' ],
[ '0 0 */2& * 1-5&', '2022-08-11 00:00', '2022-08-09', 'UTC' ],

# by way of gh-35

[ '59 6 1-7 * 2', '2020-03-17 06:59', '2020-03-15', 'UTC' ],
[ '59 6 1-7 * 2&', '2020-04-07 06:59', '2020-03-15', 'UTC' ],
[ '59 6 1-7& * 2', '2020-04-07 06:59', '2020-03-15', 'UTC' ],
[ '59 6 1-7& * 2&', '2020-04-07 06:59', '2020-03-15', 'UTC' ],
]

describe '#next_time' do
Expand Down

0 comments on commit 29c9874

Please sign in to comment.