ice_cube 0.11.0 → 0.11.1

Sign up to get free protection for your applications and to get access to all the features.
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