montrose 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rubocop.yml +113 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +13 -0
- data/Guardfile +34 -0
- data/LICENSE.txt +21 -0
- data/README.md +191 -0
- data/Rakefile +21 -0
- data/bin/_guard-core +16 -0
- data/bin/console +7 -0
- data/bin/guard +16 -0
- data/bin/m +16 -0
- data/bin/rake +16 -0
- data/bin/rubocop +16 -0
- data/bin/setup +7 -0
- data/lib/montrose.rb +20 -0
- data/lib/montrose/chainable.rb +210 -0
- data/lib/montrose/clock.rb +77 -0
- data/lib/montrose/errors.rb +5 -0
- data/lib/montrose/frequency.rb +63 -0
- data/lib/montrose/frequency/daily.rb +9 -0
- data/lib/montrose/frequency/hourly.rb +9 -0
- data/lib/montrose/frequency/minutely.rb +9 -0
- data/lib/montrose/frequency/monthly.rb +9 -0
- data/lib/montrose/frequency/weekly.rb +19 -0
- data/lib/montrose/frequency/yearly.rb +9 -0
- data/lib/montrose/options.rb +293 -0
- data/lib/montrose/recurrence.rb +67 -0
- data/lib/montrose/rule.rb +47 -0
- data/lib/montrose/rule/after.rb +27 -0
- data/lib/montrose/rule/before.rb +23 -0
- data/lib/montrose/rule/day_of_month.rb +31 -0
- data/lib/montrose/rule/day_of_week.rb +23 -0
- data/lib/montrose/rule/day_of_year.rb +37 -0
- data/lib/montrose/rule/hour_of_day.rb +23 -0
- data/lib/montrose/rule/month_of_year.rb +23 -0
- data/lib/montrose/rule/nth_day_matcher.rb +32 -0
- data/lib/montrose/rule/nth_day_of_month.rb +63 -0
- data/lib/montrose/rule/nth_day_of_year.rb +63 -0
- data/lib/montrose/rule/time_of_day.rb +33 -0
- data/lib/montrose/rule/total.rb +29 -0
- data/lib/montrose/rule/week_of_year.rb +23 -0
- data/lib/montrose/schedule.rb +42 -0
- data/lib/montrose/stack.rb +51 -0
- data/lib/montrose/utils.rb +32 -0
- data/lib/montrose/version.rb +3 -0
- data/montrose.gemspec +32 -0
- metadata +192 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
module Montrose
|
2
|
+
module Rule
|
3
|
+
class After
|
4
|
+
include Montrose::Rule
|
5
|
+
|
6
|
+
def self.apply_options(opts)
|
7
|
+
opts[:starts]
|
8
|
+
end
|
9
|
+
|
10
|
+
# Initializes rule
|
11
|
+
#
|
12
|
+
# @param [Time] start_time - lower bound timestamp
|
13
|
+
#
|
14
|
+
def initialize(start_time)
|
15
|
+
@start_time = start_time
|
16
|
+
end
|
17
|
+
|
18
|
+
def include?(time)
|
19
|
+
time >= @start_time
|
20
|
+
end
|
21
|
+
|
22
|
+
def continue?
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Montrose
|
2
|
+
module Rule
|
3
|
+
class Before
|
4
|
+
include Montrose::Rule
|
5
|
+
|
6
|
+
def self.apply_options(opts)
|
7
|
+
opts[:until]
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(end_time)
|
11
|
+
@end_time = end_time
|
12
|
+
end
|
13
|
+
|
14
|
+
def include?(time)
|
15
|
+
time < @end_time
|
16
|
+
end
|
17
|
+
|
18
|
+
def continue?
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Montrose
|
2
|
+
module Rule
|
3
|
+
class DayOfMonth
|
4
|
+
include Montrose::Rule
|
5
|
+
|
6
|
+
def self.apply_options(opts)
|
7
|
+
opts[:mday]
|
8
|
+
end
|
9
|
+
|
10
|
+
# Initializes rule
|
11
|
+
#
|
12
|
+
# @param [Array<Fixnum>] days - valid days of month, i.e. [1, 2, -1]
|
13
|
+
#
|
14
|
+
def initialize(days)
|
15
|
+
@days = days
|
16
|
+
end
|
17
|
+
|
18
|
+
def include?(time)
|
19
|
+
@days.include?(time.mday) || included_from_end_of_month?(time)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# matches days specified at negative numbers
|
25
|
+
def included_from_end_of_month?(time)
|
26
|
+
month_days = Time.days_in_month(time.month, time.year) # given by activesupport
|
27
|
+
@days.any? { |d| month_days + d + 1 == time.mday }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Montrose
|
2
|
+
module Rule
|
3
|
+
class DayOfWeek
|
4
|
+
include Montrose::Rule
|
5
|
+
|
6
|
+
def self.apply_options(opts)
|
7
|
+
opts[:day]
|
8
|
+
end
|
9
|
+
|
10
|
+
# Initializes rule
|
11
|
+
#
|
12
|
+
# @param [Array<Fixnum>] days - valid days of week, e.g. [1, 2, 7]
|
13
|
+
#
|
14
|
+
def initialize(days)
|
15
|
+
@days = days
|
16
|
+
end
|
17
|
+
|
18
|
+
def include?(time)
|
19
|
+
@days.include?(time.wday)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Montrose
|
2
|
+
module Rule
|
3
|
+
class DayOfYear
|
4
|
+
include Montrose::Rule
|
5
|
+
|
6
|
+
def self.apply_options(opts)
|
7
|
+
opts[:yday]
|
8
|
+
end
|
9
|
+
|
10
|
+
# Initializes rule
|
11
|
+
#
|
12
|
+
# @param [Array<Fixnum>] days - valid days of year, e.g. [1, 2, -1]
|
13
|
+
#
|
14
|
+
def initialize(days)
|
15
|
+
@days = days
|
16
|
+
end
|
17
|
+
|
18
|
+
def include?(time)
|
19
|
+
@days.include?(time.yday) || included_from_end_of_month?(time)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def included_from_end_of_month?(time)
|
25
|
+
year_days = days_in_year(time.year) # given by activesupport
|
26
|
+
@days.any? { |d| year_days + d + 1 == time.yday }
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the number of days in the given year.
|
30
|
+
# If no year is specified, it will use the current year.
|
31
|
+
# https://github.com/rails/rails/pull/22244
|
32
|
+
def days_in_year(year)
|
33
|
+
Time.days_in_month(2, year) + 337
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Montrose
|
2
|
+
module Rule
|
3
|
+
class HourOfDay
|
4
|
+
include Montrose::Rule
|
5
|
+
|
6
|
+
def self.apply_options(opts)
|
7
|
+
opts[:hour]
|
8
|
+
end
|
9
|
+
|
10
|
+
# Initializes rule
|
11
|
+
#
|
12
|
+
# @param [Array<Fixnum>] hour - valid hours of days, e.g. [1, 2, 24]
|
13
|
+
#
|
14
|
+
def initialize(hours)
|
15
|
+
@hours = hours
|
16
|
+
end
|
17
|
+
|
18
|
+
def include?(time)
|
19
|
+
@hours.include?(time.hour)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Montrose
|
2
|
+
module Rule
|
3
|
+
class MonthOfYear
|
4
|
+
include Montrose::Rule
|
5
|
+
|
6
|
+
def self.apply_options(opts)
|
7
|
+
opts[:month]
|
8
|
+
end
|
9
|
+
|
10
|
+
# Initializes rule
|
11
|
+
#
|
12
|
+
# @param [Array] months - valid month numbers
|
13
|
+
#
|
14
|
+
def initialize(months)
|
15
|
+
@months = months
|
16
|
+
end
|
17
|
+
|
18
|
+
def include?(time)
|
19
|
+
@months.include?(time.month)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Montrose
|
2
|
+
module Rule
|
3
|
+
class NthDayMatcher
|
4
|
+
extend Forwardable
|
5
|
+
|
6
|
+
def_delegators :@period_day, :nth_day, :first_wday, :total_days
|
7
|
+
|
8
|
+
def initialize(wday, period_day)
|
9
|
+
@wday = wday
|
10
|
+
@period_day = period_day
|
11
|
+
end
|
12
|
+
|
13
|
+
def matches?(nth_occ)
|
14
|
+
nth_occ == current_occ || (nth_occ < 0 && (total_occ + nth_occ + 1) == current_occ)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def current_occ
|
20
|
+
@current_occ ||= (nth_day - first_occ) / 7 + 1
|
21
|
+
end
|
22
|
+
|
23
|
+
def total_occ
|
24
|
+
@total_occ ||= ((total_days - first_occ + 1) / 7.0).ceil
|
25
|
+
end
|
26
|
+
|
27
|
+
def first_occ
|
28
|
+
@first_occ ||= ((7 - first_wday) + @wday) % 7 + 1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "montrose/rule/nth_day_matcher"
|
2
|
+
|
3
|
+
module Montrose
|
4
|
+
module Rule
|
5
|
+
class NthDayOfMonth
|
6
|
+
include Montrose::Rule
|
7
|
+
|
8
|
+
def self.apply_options?(opts)
|
9
|
+
opts[:every] == :month && opts[:day].is_a?(Hash)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.apply_options(opts)
|
13
|
+
opts[:day]
|
14
|
+
end
|
15
|
+
|
16
|
+
# Initializes rule
|
17
|
+
#
|
18
|
+
# @param [Hash] days - valid days of week to month occurrence pairs
|
19
|
+
#
|
20
|
+
def initialize(days)
|
21
|
+
@days = days
|
22
|
+
end
|
23
|
+
|
24
|
+
def include?(time)
|
25
|
+
@days.key?(time.wday) && nth_day?(time)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def nth_day?(time)
|
31
|
+
expected_occurrences = @days[time.wday]
|
32
|
+
nth_day = NthDayMatcher.new(time.wday, MonthDay.new(time))
|
33
|
+
expected_occurrences.any? { |n| nth_day.matches?(n) }
|
34
|
+
end
|
35
|
+
|
36
|
+
class MonthDay
|
37
|
+
def initialize(time)
|
38
|
+
@time = time
|
39
|
+
end
|
40
|
+
|
41
|
+
def nth_day
|
42
|
+
@time.mday
|
43
|
+
end
|
44
|
+
|
45
|
+
def first_wday
|
46
|
+
@time.beginning_of_month.wday
|
47
|
+
end
|
48
|
+
|
49
|
+
def total_days
|
50
|
+
days_in_month(@time)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Get the days in the month for +time
|
56
|
+
def days_in_month(time)
|
57
|
+
date = Date.new(time.year, time.month, 1)
|
58
|
+
((date >> 1) - date).to_i
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "montrose/rule/nth_day_matcher"
|
2
|
+
|
3
|
+
module Montrose
|
4
|
+
module Rule
|
5
|
+
class NthDayOfYear
|
6
|
+
include Montrose::Rule
|
7
|
+
|
8
|
+
def self.apply_options?(opts)
|
9
|
+
opts[:every] == :year && opts[:day].is_a?(Hash)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.apply_options(opts)
|
13
|
+
opts[:day]
|
14
|
+
end
|
15
|
+
|
16
|
+
# Initializes rule
|
17
|
+
#
|
18
|
+
# @param [Hash] days - valid days of week to year occurrence pairs
|
19
|
+
#
|
20
|
+
def initialize(days)
|
21
|
+
@days = days
|
22
|
+
end
|
23
|
+
|
24
|
+
def include?(time)
|
25
|
+
@days.key?(time.wday) && nth_day?(time)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def nth_day?(time)
|
31
|
+
expected_occurrences = @days[time.wday]
|
32
|
+
nth_day = NthDayMatcher.new(time.wday, YearDay.new(time))
|
33
|
+
expected_occurrences.any? { |n| nth_day.matches?(n) }
|
34
|
+
end
|
35
|
+
|
36
|
+
class YearDay
|
37
|
+
def initialize(time)
|
38
|
+
@time = time
|
39
|
+
end
|
40
|
+
|
41
|
+
def nth_day
|
42
|
+
@time.yday
|
43
|
+
end
|
44
|
+
|
45
|
+
def first_wday
|
46
|
+
@time.beginning_of_year.wday
|
47
|
+
end
|
48
|
+
|
49
|
+
def total_days
|
50
|
+
days_in_year(@time)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Get the days in the month for +time
|
56
|
+
def days_in_year(time)
|
57
|
+
date = time.to_date
|
58
|
+
((date + 1.year) - date).to_i
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Montrose
|
2
|
+
module Rule
|
3
|
+
class TimeOfDay
|
4
|
+
include Montrose::Rule
|
5
|
+
|
6
|
+
def self.apply_options(opts)
|
7
|
+
opts[:at]
|
8
|
+
end
|
9
|
+
|
10
|
+
# Initializes rule
|
11
|
+
#
|
12
|
+
# @param [Array<Time>] times - valid hours of days
|
13
|
+
#
|
14
|
+
def initialize(times)
|
15
|
+
@times = times
|
16
|
+
end
|
17
|
+
|
18
|
+
def include?(time)
|
19
|
+
times_of_day.include?(parts(time))
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def parts(time)
|
25
|
+
[time.hour, time.min]
|
26
|
+
end
|
27
|
+
|
28
|
+
def times_of_day
|
29
|
+
@times_of_day ||= @times.map { |t| parts(t) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Montrose
|
2
|
+
module Rule
|
3
|
+
class Total
|
4
|
+
include Montrose::Rule
|
5
|
+
|
6
|
+
def self.apply_options(opts)
|
7
|
+
opts[:total]
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(max)
|
11
|
+
@max = max
|
12
|
+
@count = 0
|
13
|
+
end
|
14
|
+
|
15
|
+
def include?(_time)
|
16
|
+
continue?
|
17
|
+
end
|
18
|
+
|
19
|
+
def advance!(_time)
|
20
|
+
@count += 1
|
21
|
+
continue?
|
22
|
+
end
|
23
|
+
|
24
|
+
def continue?
|
25
|
+
@count <= @max
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Montrose
|
2
|
+
module Rule
|
3
|
+
class WeekOfYear
|
4
|
+
include Montrose::Rule
|
5
|
+
|
6
|
+
def self.apply_options(opts)
|
7
|
+
opts[:week]
|
8
|
+
end
|
9
|
+
|
10
|
+
# Initializes rule
|
11
|
+
#
|
12
|
+
# @param [Array[Fixnum]] weeks - valid weeks of year
|
13
|
+
#
|
14
|
+
def initialize(weeks)
|
15
|
+
@weeks = weeks
|
16
|
+
end
|
17
|
+
|
18
|
+
def include?(time)
|
19
|
+
@weeks.include?(time.to_date.cweek)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|