ice_cube 0.11.0 → 0.11.1

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.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/lib/ice_cube.rb +0 -11
  3. data/lib/ice_cube/builders/string_builder.rb +15 -23
  4. data/lib/ice_cube/deprecated.rb +26 -24
  5. data/lib/ice_cube/enumerator.rb +1 -3
  6. data/lib/ice_cube/hash_input.rb +71 -0
  7. data/lib/ice_cube/rule.rb +4 -6
  8. data/lib/ice_cube/rules/daily_rule.rb +1 -1
  9. data/lib/ice_cube/rules/hourly_rule.rb +1 -1
  10. data/lib/ice_cube/rules/minutely_rule.rb +1 -1
  11. data/lib/ice_cube/rules/monthly_rule.rb +1 -1
  12. data/lib/ice_cube/rules/secondly_rule.rb +1 -1
  13. data/lib/ice_cube/rules/yearly_rule.rb +1 -1
  14. data/lib/ice_cube/schedule.rb +4 -4
  15. data/lib/ice_cube/string_helpers.rb +10 -0
  16. data/lib/ice_cube/time_util.rb +14 -5
  17. data/lib/ice_cube/validations/count.rb +4 -6
  18. data/lib/ice_cube/validations/daily_interval.rb +13 -18
  19. data/lib/ice_cube/validations/day.rb +4 -4
  20. data/lib/ice_cube/validations/day_of_month.rb +8 -10
  21. data/lib/ice_cube/validations/day_of_week.rb +24 -26
  22. data/lib/ice_cube/validations/day_of_year.rb +11 -12
  23. data/lib/ice_cube/validations/hour_of_day.rb +9 -11
  24. data/lib/ice_cube/validations/hourly_interval.rb +18 -21
  25. data/lib/ice_cube/validations/lock.rb +35 -14
  26. data/lib/ice_cube/validations/minute_of_hour.rb +9 -11
  27. data/lib/ice_cube/validations/minutely_interval.rb +16 -19
  28. data/lib/ice_cube/validations/month_of_year.rb +4 -4
  29. data/lib/ice_cube/validations/monthly_interval.rb +15 -17
  30. data/lib/ice_cube/validations/schedule_lock.rb +12 -11
  31. data/lib/ice_cube/validations/second_of_minute.rb +5 -5
  32. data/lib/ice_cube/validations/secondly_interval.rb +13 -16
  33. data/lib/ice_cube/validations/until.rb +12 -12
  34. data/lib/ice_cube/validations/weekly_interval.rb +20 -23
  35. data/lib/ice_cube/validations/yearly_interval.rb +10 -11
  36. data/lib/ice_cube/version.rb +1 -1
  37. metadata +20 -33
@@ -10,8 +10,6 @@ module IceCube
10
10
  self
11
11
  end
12
12
 
13
- # A validation for checking to make sure that a time
14
- # is inside of a certain DailyInterval
15
13
  class Validation
16
14
 
17
15
  attr_reader :interval
@@ -20,6 +18,18 @@ module IceCube
20
18
  @interval = interval
21
19
  end
22
20
 
21
+ def type
22
+ :day
23
+ end
24
+
25
+ def validate(step_time, schedule)
26
+ t0, t1 = schedule.start_time, step_time
27
+ days = Date.new(t1.year, t1.month, t1.day) -
28
+ Date.new(t0.year, t0.month, t0.day)
29
+ offset = (days % interval).nonzero?
30
+ interval - offset if offset
31
+ end
32
+
23
33
  def build_s(builder)
24
34
  builder.base = interval == 1 ? 'Daily' : "Every #{interval} days"
25
35
  end
@@ -30,22 +40,7 @@ module IceCube
30
40
 
31
41
  def build_ical(builder)
32
42
  builder['FREQ'] << 'DAILY'
33
- unless interval == 1
34
- builder['INTERVAL'] << interval
35
- end
36
- end
37
-
38
- def type
39
- :day
40
- end
41
-
42
- def validate(time, schedule)
43
- time_date = Date.new(time.year, time.month, time.day)
44
- start_date = Date.new(schedule.start_time.year, schedule.start_time.month, schedule.start_time.day)
45
- days = time_date - start_date
46
- unless days % interval === 0
47
- interval - (days % interval)
48
- end
43
+ builder['INTERVAL'] << interval unless interval == 1
49
44
  end
50
45
 
51
46
  end
@@ -27,6 +27,10 @@ module IceCube
27
27
  @day = day
28
28
  end
29
29
 
30
+ def type
31
+ :wday
32
+ end
33
+
30
34
  def build_s(builder)
31
35
  builder.piece(:day) << day
32
36
  end
@@ -43,10 +47,6 @@ module IceCube
43
47
  end
44
48
  end
45
49
 
46
- def type
47
- :wday
48
- end
49
-
50
50
  StringBuilder.register_formatter(:day) do |validation_days|
51
51
  # sort the days
52
52
  validation_days.sort!
@@ -2,8 +2,6 @@ module IceCube
2
2
 
3
3
  module Validations::DayOfMonth
4
4
 
5
- include Validations::Lock
6
-
7
5
  def day_of_month(*days)
8
6
  days.flatten.each do |day|
9
7
  unless day.is_a?(Fixnum)
@@ -19,12 +17,6 @@ module IceCube
19
17
 
20
18
  include Validations::Lock
21
19
 
22
- StringBuilder.register_formatter(:day_of_month) do |entries|
23
- str = "on the #{StringBuilder.sentence(entries)} "
24
- str << (entries.size == 1 ? 'day of the month' : 'days of the month')
25
- str
26
- end
27
-
28
20
  attr_reader :day
29
21
  alias :value :day
30
22
 
@@ -32,6 +24,10 @@ module IceCube
32
24
  @day = day
33
25
  end
34
26
 
27
+ def type
28
+ :day
29
+ end
30
+
35
31
  def build_s(builder)
36
32
  builder.piece(:day_of_month) << StringBuilder.nice_number(day)
37
33
  end
@@ -44,8 +40,10 @@ module IceCube
44
40
  builder['BYMONTHDAY'] << day
45
41
  end
46
42
 
47
- def type
48
- :day
43
+ StringBuilder.register_formatter(:day_of_month) do |entries|
44
+ str = "on the #{StringBuilder.sentence(entries)} "
45
+ str << (entries.size == 1 ? 'day of the month' : 'days of the month')
46
+ str
49
47
  end
50
48
 
51
49
  end
@@ -17,23 +17,31 @@ module IceCube
17
17
 
18
18
  attr_reader :day, :occ
19
19
 
20
- StringBuilder.register_formatter(:day_of_week) do |segments|
21
- 'on the ' + segments.join(' and ')
20
+ def initialize(day, occ)
21
+ @day = day
22
+ @occ = occ
22
23
  end
23
24
 
24
25
  def type
25
26
  :day
26
27
  end
27
28
 
28
- def build_s(builder)
29
- builder.piece(:day_of_week) << "#{StringBuilder.nice_number(occ)} #{Date::DAYNAMES[day]}"
29
+ def validate(step_time, schedule)
30
+ wday = step_time.wday
31
+ offset = (day < wday) ? (7 - wday + day) : (day - wday)
32
+ wrapper = TimeUtil::TimeWrapper.new(step_time)
33
+ wrapper.add :day, offset
34
+ loop do
35
+ which_occ, num_occ = TimeUtil.which_occurrence_in_month(wrapper.to_time, day)
36
+ this_occ = (occ < 0) ? (num_occ + occ + 1) : (occ)
37
+ break offset if which_occ == this_occ
38
+ wrapper.add :day, 7
39
+ offset += 7
40
+ end
30
41
  end
31
42
 
32
- def build_ical(builder)
33
- ical_day = IcalBuilder.fixnum_to_ical_day(day)
34
- # Delete any with this day and no occ first
35
- builder['BYDAY'].delete_if { |d| d == ical_day }
36
- builder['BYDAY'] << "#{occ}#{ical_day}"
43
+ def build_s(builder)
44
+ builder.piece(:day_of_week) << "#{StringBuilder.nice_number(occ)} #{Date::DAYNAMES[day]}"
37
45
  end
38
46
 
39
47
  def build_hash(builder)
@@ -42,25 +50,15 @@ module IceCube
42
50
  arr << occ
43
51
  end
44
52
 
45
- def initialize(day, occ)
46
- @day = day
47
- @occ = occ
53
+ def build_ical(builder)
54
+ ical_day = IcalBuilder.fixnum_to_ical_day(day)
55
+ # Delete any with this day and no occ first
56
+ builder['BYDAY'].delete_if { |d| d == ical_day }
57
+ builder['BYDAY'] << "#{occ}#{ical_day}"
48
58
  end
49
59
 
50
- def validate(time, schedule)
51
- # count the days to the weekday
52
- sum = day >= time.wday ? day - time.wday : 7 - time.wday + day
53
- wrapper = TimeUtil::TimeWrapper.new(time)
54
- wrapper.add :day, sum
55
- # and then count the week until a viable occ
56
- loop do
57
- which_occ, num_occ = TimeUtil.which_occurrence_in_month(wrapper.to_time, day)
58
- this_occ = occ < 0 ? num_occ + occ + 1 : occ
59
- break if which_occ == this_occ
60
- sum += 7
61
- wrapper.add :day, 7 # one week
62
- end
63
- sum
60
+ StringBuilder.register_formatter(:day_of_week) do |segments|
61
+ 'on the ' + segments.join(' and ')
64
62
  end
65
63
 
66
64
  end
@@ -17,12 +17,6 @@ module IceCube
17
17
 
18
18
  attr_reader :day
19
19
 
20
- StringBuilder.register_formatter(:day_of_year) do |entries|
21
- str = "on the #{StringBuilder.sentence(entries)} "
22
- str << (entries.size == 1 ? 'day of the year' : 'days of the year')
23
- str
24
- end
25
-
26
20
  def initialize(day)
27
21
  @day = day
28
22
  end
@@ -31,6 +25,13 @@ module IceCube
31
25
  :day
32
26
  end
33
27
 
28
+ def validate(step_time, schedule)
29
+ days_in_year = TimeUtil.days_in_year(step_time)
30
+ yday = day < 0 ? day + days_in_year : day
31
+ offset = yday - step_time.yday
32
+ offset >= 0 ? offset : offset + days_in_year
33
+ end
34
+
34
35
  def build_s(builder)
35
36
  builder.piece(:day_of_year) << StringBuilder.nice_number(day)
36
37
  end
@@ -43,12 +44,10 @@ module IceCube
43
44
  builder['BYYEARDAY'] << day
44
45
  end
45
46
 
46
- def validate(time, schedule)
47
- days_in_year = TimeUtil.days_in_year(time)
48
- the_day = day < 0 ? day + days_in_year : day
49
- # compute the diff
50
- diff = the_day - time.yday
51
- diff >= 0 ? diff : diff + days_in_year
47
+ StringBuilder.register_formatter(:day_of_year) do |entries|
48
+ str = "on the #{StringBuilder.sentence(entries)} "
49
+ str << (entries.size == 1 ? 'day of the year' : 'days of the year')
50
+ str
52
51
  end
53
52
 
54
53
  end
@@ -2,8 +2,6 @@ module IceCube
2
2
 
3
3
  module Validations::HourOfDay
4
4
 
5
- include Validations::Lock
6
-
7
5
  # Add hour of day validations
8
6
  def hour_of_day(*hours)
9
7
  hours.flatten.each do |hour|
@@ -20,11 +18,6 @@ module IceCube
20
18
 
21
19
  include Validations::Lock
22
20
 
23
- StringBuilder.register_formatter(:hour_of_day) do |segments|
24
- str = "on the #{StringBuilder.sentence(segments)} "
25
- str << (segments.size == 1 ? 'hour of the day' : 'hours of the day')
26
- end
27
-
28
21
  attr_reader :hour
29
22
  alias :value :hour
30
23
 
@@ -32,14 +25,14 @@ module IceCube
32
25
  @hour = hour
33
26
  end
34
27
 
35
- def build_s(builder)
36
- builder.piece(:hour_of_day) << StringBuilder.nice_number(hour)
37
- end
38
-
39
28
  def type
40
29
  :hour
41
30
  end
42
31
 
32
+ def build_s(builder)
33
+ builder.piece(:hour_of_day) << StringBuilder.nice_number(hour)
34
+ end
35
+
43
36
  def build_hash(builder)
44
37
  builder.validations_array(:hour_of_day) << hour
45
38
  end
@@ -48,6 +41,11 @@ module IceCube
48
41
  builder['BYHOUR'] << hour
49
42
  end
50
43
 
44
+ StringBuilder.register_formatter(:hour_of_day) do |segments|
45
+ str = "on the #{StringBuilder.sentence(segments)} "
46
+ str << (segments.size == 1 ? 'hour of the day' : 'hours of the day')
47
+ end
48
+
51
49
  end
52
50
 
53
51
  end
@@ -13,10 +13,27 @@ module IceCube
13
13
 
14
14
  attr_reader :interval
15
15
 
16
+ def initialize(interval)
17
+ @interval = interval
18
+ end
19
+
16
20
  def type
17
21
  :hour
18
22
  end
19
23
 
24
+ def dst_adjust?
25
+ false
26
+ end
27
+
28
+ def validate(step_time, schedule)
29
+ t0, t1 = schedule.start_time.to_i, step_time.to_i
30
+ sec = (t1 - t1 % ONE_HOUR) -
31
+ (t0 - t0 % ONE_HOUR)
32
+ hours = sec / ONE_HOUR
33
+ offset = (hours % interval).nonzero?
34
+ interval - offset if offset
35
+ end
36
+
20
37
  def build_s(builder)
21
38
  builder.base = interval == 1 ? 'Hourly' : "Every #{interval} hours"
22
39
  end
@@ -27,27 +44,7 @@ module IceCube
27
44
 
28
45
  def build_ical(builder)
29
46
  builder['FREQ'] << 'HOURLY'
30
- unless interval == 1
31
- builder['INTERVAL'] << interval
32
- end
33
- end
34
-
35
- def initialize(interval)
36
- @interval = interval
37
- end
38
-
39
- def dst_adjust?
40
- false
41
- end
42
-
43
- def validate(time, schedule)
44
- start_time = schedule.start_time
45
- sec = (time.to_i - time.to_i % ONE_HOUR) -
46
- (start_time.to_i - start_time.to_i % ONE_HOUR)
47
- hours = sec / ONE_HOUR
48
- unless hours % interval == 0
49
- interval - (hours % interval)
50
- end
47
+ builder['INTERVAL'] << interval unless interval == 1
51
48
  end
52
49
 
53
50
  end
@@ -1,34 +1,49 @@
1
1
  module IceCube
2
2
 
3
- # A validation mixin that will lock the +type field to
4
- # +value or +schedule.start_time.send(type) if value is nil
5
-
3
+ # This validation mixin is used by the various "fixed-time" (e.g. day,
4
+ # day_of_month, hour_of_day) Validation and ScheduleLock::Validation modules.
5
+ # It is not a standalone rule validation like the others.
6
+ #
7
+ # Given the including Validation's defined +type+ field, it will lock
8
+ # to the specified +value+ or else the corresponding time unit from the
9
+ # schedule's start_time
10
+ #
6
11
  module Validations::Lock
7
12
 
8
- INTERVALS = {:min => 60, :sec => 60, :month => 12, :wday => 7}
13
+ INTERVALS = {:min => 60, :sec => 60, :hour => 24, :month => 12, :wday => 7}
9
14
 
10
15
  def validate(time, schedule)
11
- return send(:"validate_#{type}_lock", time, schedule) unless INTERVALS[type]
12
- start = value || schedule.start_time.send(type)
13
- start = INTERVALS[type] + start if start < 0 # handle negative values
14
- start >= time.send(type) ? start - time.send(type) : INTERVALS[type] - time.send(type) + start
16
+ case type
17
+ when :day then validate_day_lock(time, schedule)
18
+ when :hour then validate_hour_lock(time, schedule)
19
+ else validate_interval_lock(time, schedule)
20
+ end
15
21
  end
16
22
 
17
23
  private
18
24
 
25
+ # Validate if the current time unit matches the same unit from the schedule
26
+ # start time, returning the difference to the interval
27
+ #
28
+ def validate_interval_lock(time, schedule)
29
+ t0 = starting_unit(schedule.start_time)
30
+ t1 = time.send(type)
31
+ t0 >= t1 ? t0 - t1 : INTERVALS[type] - t1 + t0
32
+ end
33
+
19
34
  # Lock the hour if explicitly set by hour_of_day, but allow for the nearest
20
35
  # hour during DST start to keep the correct interval.
21
36
  #
22
37
  def validate_hour_lock(time, schedule)
23
- hour = value || schedule.start_time.send(type)
24
- hour = 24 + hour if hour < 0
25
- if hour >= time.hour
26
- hour - time.hour
38
+ h0 = starting_unit(schedule.start_time)
39
+ h1 = time.hour
40
+ if h0 >= h1
41
+ h0 - h1
27
42
  else
28
43
  if dst_offset = TimeUtil.dst_change(time)
29
- hour - time.hour + dst_offset
44
+ h0 - h1 + dst_offset
30
45
  else
31
- 24 - time.hour + hour
46
+ 24 - h1 + h0
32
47
  end
33
48
  end
34
49
  end
@@ -69,6 +84,12 @@ module IceCube
69
84
  sleeps >= 0 ? sleeps : until_next_month
70
85
  end
71
86
 
87
+ def starting_unit(start_time)
88
+ start = value || start_time.send(type)
89
+ start += INTERVALS[type] while start < 0
90
+ start
91
+ end
92
+
72
93
  end
73
94
 
74
95
  end
@@ -2,8 +2,6 @@ module IceCube
2
2
 
3
3
  module Validations::MinuteOfHour
4
4
 
5
- include Validations::Lock
6
-
7
5
  def minute_of_hour(*minutes)
8
6
  minutes.flatten.each do |minute|
9
7
  unless minute.is_a?(Fixnum)
@@ -19,11 +17,6 @@ module IceCube
19
17
 
20
18
  include Validations::Lock
21
19
 
22
- StringBuilder.register_formatter(:minute_of_hour) do |segments|
23
- str = "on the #{StringBuilder.sentence(segments)} "
24
- str << (segments.size == 1 ? 'minute of the hour' : 'minutes of the hour')
25
- end
26
-
27
20
  attr_reader :minute
28
21
  alias :value :minute
29
22
 
@@ -31,14 +24,14 @@ module IceCube
31
24
  @minute = minute
32
25
  end
33
26
 
34
- def build_s(builder)
35
- builder.piece(:minute_of_hour) << StringBuilder.nice_number(minute)
36
- end
37
-
38
27
  def type
39
28
  :min
40
29
  end
41
30
 
31
+ def build_s(builder)
32
+ builder.piece(:minute_of_hour) << StringBuilder.nice_number(minute)
33
+ end
34
+
42
35
  def build_hash(builder)
43
36
  builder.validations_array(:minute_of_hour) << minute
44
37
  end
@@ -47,6 +40,11 @@ module IceCube
47
40
  builder['BYMINUTE'] << minute
48
41
  end
49
42
 
43
+ StringBuilder.register_formatter(:minute_of_hour) do |segments|
44
+ str = "on the #{StringBuilder.sentence(segments)} "
45
+ str << (segments.size == 1 ? 'minute of the hour' : 'minutes of the hour')
46
+ end
47
+
50
48
  end
51
49
 
52
50
  end