ice_cube_conrad 0.8.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.
Files changed (42) hide show
  1. data/lib/ice_cube.rb +80 -0
  2. data/lib/ice_cube/builders/hash_builder.rb +27 -0
  3. data/lib/ice_cube/builders/ical_builder.rb +59 -0
  4. data/lib/ice_cube/builders/string_builder.rb +74 -0
  5. data/lib/ice_cube/deprecated.rb +28 -0
  6. data/lib/ice_cube/errors/count_exceeded.rb +7 -0
  7. data/lib/ice_cube/errors/until_exceeded.rb +7 -0
  8. data/lib/ice_cube/errors/zero_interval.rb +7 -0
  9. data/lib/ice_cube/rule.rb +182 -0
  10. data/lib/ice_cube/rules/daily_rule.rb +14 -0
  11. data/lib/ice_cube/rules/hourly_rule.rb +14 -0
  12. data/lib/ice_cube/rules/minutely_rule.rb +14 -0
  13. data/lib/ice_cube/rules/monthly_rule.rb +14 -0
  14. data/lib/ice_cube/rules/secondly_rule.rb +13 -0
  15. data/lib/ice_cube/rules/weekly_rule.rb +14 -0
  16. data/lib/ice_cube/rules/yearly_rule.rb +14 -0
  17. data/lib/ice_cube/schedule.rb +414 -0
  18. data/lib/ice_cube/single_occurrence_rule.rb +28 -0
  19. data/lib/ice_cube/time_util.rb +250 -0
  20. data/lib/ice_cube/validated_rule.rb +108 -0
  21. data/lib/ice_cube/validations/count.rb +56 -0
  22. data/lib/ice_cube/validations/daily_interval.rb +55 -0
  23. data/lib/ice_cube/validations/day.rb +65 -0
  24. data/lib/ice_cube/validations/day_of_month.rb +52 -0
  25. data/lib/ice_cube/validations/day_of_week.rb +70 -0
  26. data/lib/ice_cube/validations/day_of_year.rb +55 -0
  27. data/lib/ice_cube/validations/hour_of_day.rb +52 -0
  28. data/lib/ice_cube/validations/hourly_interval.rb +57 -0
  29. data/lib/ice_cube/validations/lock.rb +47 -0
  30. data/lib/ice_cube/validations/minute_of_hour.rb +51 -0
  31. data/lib/ice_cube/validations/minutely_interval.rb +57 -0
  32. data/lib/ice_cube/validations/month_of_year.rb +49 -0
  33. data/lib/ice_cube/validations/monthly_interval.rb +51 -0
  34. data/lib/ice_cube/validations/schedule_lock.rb +41 -0
  35. data/lib/ice_cube/validations/second_of_minute.rb +49 -0
  36. data/lib/ice_cube/validations/secondly_interval.rb +54 -0
  37. data/lib/ice_cube/validations/until.rb +51 -0
  38. data/lib/ice_cube/validations/weekly_interval.rb +60 -0
  39. data/lib/ice_cube/validations/yearly_interval.rb +49 -0
  40. data/lib/ice_cube/version.rb +5 -0
  41. data/spec/spec_helper.rb +11 -0
  42. metadata +120 -0
@@ -0,0 +1,57 @@
1
+ module IceCube
2
+
3
+ module Validations::MinutelyInterval
4
+
5
+ def interval(interval)
6
+ validations_for(:interval) << Validation.new(interval)
7
+ clobber_base_validations(:min)
8
+ self
9
+ end
10
+
11
+ class Validation
12
+
13
+ attr_reader :interval
14
+
15
+ def type
16
+ :min
17
+ end
18
+
19
+ def dst_adjust?
20
+ false
21
+ end
22
+
23
+ def build_s(builder)
24
+ builder.base = interval == 1 ? 'Minutely' : "Every #{interval} minutes"
25
+ end
26
+
27
+ def build_ical(builder)
28
+ builder['FREQ'] << 'MINUTELY'
29
+ unless interval == 1
30
+ builder['INTERVAL'] << interval
31
+ end
32
+ end
33
+
34
+ def build_hash(builder)
35
+ builder[:interval] = interval
36
+ end
37
+
38
+ def initialize(interval)
39
+ @interval = interval
40
+ end
41
+
42
+ def validate(time, schedule)
43
+ raise ZeroInterval if interval == 0
44
+ start_time = schedule.start_time
45
+ sec = (time.to_i - time.to_i % ONE_MINUTE) -
46
+ (start_time.to_i - start_time.to_i % ONE_MINUTE)
47
+ minutes = sec / ONE_MINUTE
48
+ unless minutes % interval == 0
49
+ interval - (minutes % interval)
50
+ end
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,49 @@
1
+ module IceCube
2
+
3
+ module Validations::MonthOfYear
4
+
5
+ def month_of_year(*months)
6
+ months.each do |month|
7
+ month = TimeUtil.symbol_to_month(month.to_sym) if month.is_a?(Symbol) or month.is_a?(String)
8
+ validations_for(:month_of_year) << Validation.new(month)
9
+ end
10
+ clobber_base_validations :month
11
+ self
12
+ end
13
+
14
+ class Validation
15
+
16
+ include Validations::Lock
17
+
18
+ attr_reader :month
19
+ alias :value :month
20
+
21
+ def initialize(month)
22
+ @month = month
23
+ end
24
+
25
+ def build_s(builder)
26
+ builder.piece(:month_of_year) << Date::MONTHNAMES[month]
27
+ end
28
+
29
+ def build_hash(builder)
30
+ builder.validations_array(:month_of_year) << month
31
+ end
32
+
33
+ def build_ical(builder)
34
+ builder['BYMONTH'] << month
35
+ end
36
+
37
+ def type
38
+ :month
39
+ end
40
+
41
+ StringBuilder.register_formatter(:month_of_year) do |segments|
42
+ "in #{StringBuilder.sentence(segments)}"
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,51 @@
1
+ module IceCube
2
+
3
+ module Validations::MonthlyInterval
4
+
5
+ def interval(interval = 1)
6
+ validations_for(:interval) << Validation.new(interval)
7
+ clobber_base_validations(:month)
8
+ self
9
+ end
10
+
11
+ class Validation
12
+
13
+ attr_reader :interval
14
+
15
+ def type
16
+ :month
17
+ end
18
+
19
+ def build_s(builder)
20
+ builder.base = interval == 1 ? 'Monthly' : "Every #{interval} months"
21
+ end
22
+
23
+ def build_ical(builder)
24
+ builder['FREQ'] << 'MONTHLY'
25
+ unless interval == 1
26
+ builder['INTERVAL'] << interval
27
+ end
28
+ end
29
+
30
+ def build_hash(builder)
31
+ builder[:interval] = interval
32
+ end
33
+
34
+ def initialize(interval)
35
+ @interval = interval
36
+ end
37
+
38
+ def validate(time, schedule)
39
+ raise ZeroInterval if interval == 0
40
+ start_time = schedule.start_time
41
+ months_to_start = (time.month - start_time.month) + (time.year - start_time.year) * 12
42
+ unless months_to_start % interval == 0
43
+ interval - (months_to_start % interval)
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,41 @@
1
+ module IceCube
2
+
3
+ module Validations::ScheduleLock
4
+
5
+ # Lock the given times down the schedule's start_time for that position
6
+ # These locks are all clobberable by other rules of the same #type
7
+ # using clobber_base_validation
8
+ def schedule_lock(*types)
9
+ types.each do |type|
10
+ validations_for(:"base_#{type}") << Validation.new(type)
11
+ end
12
+ end
13
+
14
+ # A validation used for locking time into a certain value
15
+ class Validation
16
+
17
+ include Validations::Lock
18
+
19
+ attr_reader :type, :value
20
+
21
+ def initialize(type)
22
+ @type = type
23
+ end
24
+
25
+ # no -op
26
+ def build_s(builder)
27
+ end
28
+
29
+ # no -op
30
+ def build_ical(builder)
31
+ end
32
+
33
+ # no -op
34
+ def build_hash(builder)
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,49 @@
1
+ module IceCube
2
+
3
+ module Validations::SecondOfMinute
4
+
5
+ def second_of_minute(*seconds)
6
+ seconds.each do |second|
7
+ validations_for(:second_of_minute) << Validation.new(second)
8
+ end
9
+ clobber_base_validations :sec
10
+ self
11
+ end
12
+
13
+ class Validation
14
+
15
+ include Validations::Lock
16
+
17
+ StringBuilder.register_formatter(:second_of_minute) do |segments|
18
+ str = "on the #{StringBuilder.sentence(segments)} "
19
+ str << (segments.size == 1 ? 'second of the minute' : 'seconds of the minute')
20
+ end
21
+
22
+ attr_reader :second
23
+ alias :value :second
24
+
25
+ def initialize(second)
26
+ @second = second
27
+ end
28
+
29
+ def type
30
+ :sec
31
+ end
32
+
33
+ def build_s(builder)
34
+ builder.piece(:second_of_minute) << StringBuilder.nice_number(second)
35
+ end
36
+
37
+ def build_hash(builder)
38
+ builder.validations_array(:second_of_minute) << second
39
+ end
40
+
41
+ def build_ical(builder)
42
+ builder['BYSECOND'] << second
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,54 @@
1
+ module IceCube
2
+
3
+ module Validations::SecondlyInterval
4
+
5
+ def interval(interval)
6
+ validations_for(:interval) << Validation.new(interval)
7
+ clobber_base_validations(:sec)
8
+ self
9
+ end
10
+
11
+ class Validation
12
+
13
+ attr_reader :interval
14
+
15
+ def type
16
+ :sec
17
+ end
18
+
19
+ def dst_adjust?
20
+ false
21
+ end
22
+
23
+ def build_s(builder)
24
+ builder.base = interval == 1 ? 'Secondly' : "Every #{interval} seconds"
25
+ end
26
+
27
+ def build_ical(builder)
28
+ builder['FREQ'] << 'SECONDLY'
29
+ unless interval == 1
30
+ builder['INTERVAL'] << interval
31
+ end
32
+ end
33
+
34
+ def build_hash(builder)
35
+ builder[:interval] = interval
36
+ end
37
+
38
+ def initialize(interval)
39
+ @interval = interval
40
+ end
41
+
42
+ def validate(time, schedule)
43
+ raise ZeroInterval if interval == 0
44
+ seconds = time.to_i - schedule.start_time.to_i
45
+ unless seconds % interval == 0
46
+ interval - (seconds % interval)
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,51 @@
1
+ module IceCube
2
+
3
+ module Validations::Until
4
+
5
+ extend ::Deprecated
6
+
7
+ # accessor
8
+ def until_time
9
+ @until
10
+ end
11
+ deprecated_alias :until_date, :until_time
12
+
13
+ def until(time)
14
+ @until = time
15
+ replace_validations_for(:until, [Validation.new(time)])
16
+ self
17
+ end
18
+
19
+ class Validation
20
+
21
+ attr_reader :time
22
+
23
+ def type
24
+ :dealbreaker
25
+ end
26
+
27
+ def initialize(time)
28
+ @time = time
29
+ end
30
+
31
+ def build_ical(builder)
32
+ builder['UNTIL'] << IcalBuilder.ical_utc_format(time)
33
+ end
34
+
35
+ def build_hash(builder)
36
+ builder[:until] = TimeUtil.serialize_time(time)
37
+ end
38
+
39
+ def build_s(builder)
40
+ builder.piece(:until) << "until #{time.strftime(TO_S_TIME_FORMAT)}"
41
+ end
42
+
43
+ def validate(t, schedule)
44
+ raise UntilExceeded if t > time
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,60 @@
1
+ require 'date'
2
+
3
+ module IceCube
4
+
5
+ module Validations::WeeklyInterval
6
+
7
+ def interval(interval, week_start = :sunday)
8
+ validations_for(:interval) << Validation.new(interval, week_start)
9
+ clobber_base_validations(:day)
10
+ self
11
+ end
12
+
13
+ class Validation
14
+
15
+ attr_reader :interval, :week_start
16
+
17
+ def type
18
+ :day
19
+ end
20
+
21
+ def build_s(builder)
22
+ builder.base = interval == 1 ? 'Weekly' : "Every #{interval} weeks"
23
+ end
24
+
25
+ def build_ical(builder)
26
+ builder['FREQ'] << 'WEEKLY'
27
+ unless interval == 1
28
+ builder['INTERVAL'] << interval
29
+ builder['WKST'] << TimeUtil.week_start(week_start)
30
+ end
31
+ end
32
+
33
+ def build_hash(builder)
34
+ builder[:interval] = interval
35
+ end
36
+
37
+ def initialize(interval, week_start)
38
+ @interval = interval
39
+ @week_start = week_start
40
+ end
41
+
42
+ def validate(time, schedule)
43
+ raise ZeroInterval if interval == 0
44
+ date = Date.new(time.year, time.month, time.day)
45
+ st = schedule.start_time
46
+ start_date = Date.new(st.year, st.month, st.day)
47
+ weeks = (
48
+ (date - TimeUtil.normalize_weekday(date.wday, week_start)) -
49
+ (start_date - TimeUtil.normalize_weekday(start_date.wday, week_start))
50
+ ) / 7
51
+ unless weeks % interval == 0
52
+ (interval - (weeks % interval)) * 7
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,49 @@
1
+ module IceCube
2
+
3
+ module Validations::YearlyInterval
4
+
5
+ def interval(interval = 1)
6
+ validations_for(:interval) << Validation.new(interval)
7
+ clobber_base_validations(:year)
8
+ end
9
+
10
+ class Validation
11
+
12
+ attr_reader :interval
13
+
14
+ def type
15
+ :year
16
+ end
17
+
18
+ def build_s(builder)
19
+ builder.base = interval == 1 ? 'Yearly' : "Every #{interval} years"
20
+ end
21
+
22
+ def build_hash(builder)
23
+ builder[:interval] = interval
24
+ end
25
+
26
+ def build_ical(builder)
27
+ builder['FREQ'] << 'YEARLY'
28
+ unless interval == 1
29
+ builder['INTERVAL'] << interval
30
+ end
31
+ end
32
+
33
+ def initialize(interval)
34
+ @interval = interval
35
+ end
36
+
37
+ def validate(time, schedule)
38
+ raise ZeroInterval if interval == 0
39
+ years_to_start = time.year - schedule.start_time.year
40
+ unless years_to_start % interval == 0
41
+ interval - (years_to_start % interval)
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+
49
+ end