ice_cube 0.6.14 → 0.7.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 (43) hide show
  1. data/lib/ice_cube.rb +63 -37
  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/errors/count_exceeded.rb +7 -0
  6. data/lib/ice_cube/errors/until_exceeded.rb +7 -0
  7. data/lib/ice_cube/rule.rb +85 -147
  8. data/lib/ice_cube/rules/daily_rule.rb +5 -27
  9. data/lib/ice_cube/rules/hourly_rule.rb +6 -26
  10. data/lib/ice_cube/rules/minutely_rule.rb +5 -25
  11. data/lib/ice_cube/rules/monthly_rule.rb +6 -30
  12. data/lib/ice_cube/rules/secondly_rule.rb +5 -26
  13. data/lib/ice_cube/rules/weekly_rule.rb +5 -36
  14. data/lib/ice_cube/rules/yearly_rule.rb +8 -34
  15. data/lib/ice_cube/schedule.rb +257 -229
  16. data/lib/ice_cube/single_occurrence_rule.rb +28 -0
  17. data/lib/ice_cube/time_util.rb +202 -76
  18. data/lib/ice_cube/validated_rule.rb +107 -0
  19. data/lib/ice_cube/validations/count.rb +56 -0
  20. data/lib/ice_cube/validations/daily_interval.rb +51 -0
  21. data/lib/ice_cube/validations/day.rb +45 -31
  22. data/lib/ice_cube/validations/day_of_month.rb +44 -44
  23. data/lib/ice_cube/validations/day_of_week.rb +60 -47
  24. data/lib/ice_cube/validations/day_of_year.rb +48 -44
  25. data/lib/ice_cube/validations/hour_of_day.rb +42 -30
  26. data/lib/ice_cube/validations/hourly_interval.rb +50 -0
  27. data/lib/ice_cube/validations/lock.rb +47 -0
  28. data/lib/ice_cube/validations/minute_of_hour.rb +42 -31
  29. data/lib/ice_cube/validations/minutely_interval.rb +50 -0
  30. data/lib/ice_cube/validations/month_of_year.rb +39 -30
  31. data/lib/ice_cube/validations/monthly_interval.rb +47 -0
  32. data/lib/ice_cube/validations/schedule_lock.rb +41 -0
  33. data/lib/ice_cube/validations/second_of_minute.rb +39 -30
  34. data/lib/ice_cube/validations/secondly_interval.rb +50 -0
  35. data/lib/ice_cube/validations/until.rb +49 -0
  36. data/lib/ice_cube/validations/weekly_interval.rb +50 -0
  37. data/lib/ice_cube/validations/yearly_interval.rb +45 -0
  38. data/lib/ice_cube/version.rb +2 -2
  39. data/spec/spec_helper.rb +13 -0
  40. metadata +50 -9
  41. data/lib/ice_cube/rule_occurrence.rb +0 -94
  42. data/lib/ice_cube/validation.rb +0 -44
  43. data/lib/ice_cube/validation_types.rb +0 -137
@@ -1,40 +1,49 @@
1
1
  module IceCube
2
2
 
3
- class SecondOfMinuteValidation < Validation
3
+ module Validations::SecondOfMinute
4
4
 
5
- attr_reader :seconds_of_minute
6
-
7
- def initialize(rule)
8
- @seconds_of_minute = rule.validations[:second_of_minute]
9
- end
10
-
11
- def validate(date)
12
- return true if !@seconds_of_minute || @seconds_of_minute.empty?
13
- @seconds_of_minute.include?(date.sec)
14
- end
15
-
16
- def closest(date)
17
- return nil if !@seconds_of_minute || @seconds_of_minute.empty?
18
- # turn seconds into seconds of minute
19
- # second >= 60 should fall into the next minute
20
- seconds = @seconds_of_minute.map do |s|
21
- s > date.sec ? s - date.sec : 60 - date.sec + s
5
+ def second_of_minute(*seconds)
6
+ seconds.each do |second|
7
+ validations_for(:second_of_minute) << Validation.new(second)
22
8
  end
23
- seconds.compact!
24
- # go to the closest distance away
25
- closest_second = seconds.min
26
- goal = date + closest_second
27
- self.class.adjust(goal, date)
9
+ clobber_base_validations :sec
10
+ self
28
11
  end
29
12
 
30
- def to_s
31
- 'on the ' << self.class.nice_numbers(@seconds_of_minute) << (@seconds_of_minute.size == 1 ? ' second' : ' seconds') << ' of the minute' unless @seconds_of_minute.empty?
32
- end
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
33
44
 
34
- def to_ical
35
- 'BYSECOND=' << @seconds_of_minute.join(',') unless @seconds_of_minute.empty?
36
45
  end
37
-
46
+
38
47
  end
39
-
48
+
40
49
  end
@@ -0,0 +1,50 @@
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
+ end
30
+
31
+ def build_hash(builder)
32
+ builder.validations[:interval] = interval
33
+ end
34
+
35
+ def initialize(interval)
36
+ @interval = interval
37
+ end
38
+
39
+ def validate(time, schedule)
40
+ seconds = time.to_i - schedule.start_time.to_i
41
+ unless seconds % interval == 0
42
+ interval - (seconds % interval)
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
50
+ end
@@ -0,0 +1,49 @@
1
+ module IceCube
2
+
3
+ module Validations::Until
4
+
5
+ # accessor
6
+ def until_time
7
+ @until
8
+ end
9
+ alias :until_date :until_time
10
+
11
+ def until(time)
12
+ @until = time
13
+ replace_validations_for(:until, [Validation.new(time)])
14
+ self
15
+ end
16
+
17
+ class Validation
18
+
19
+ attr_reader :time
20
+
21
+ def type
22
+ :dealbreaker
23
+ end
24
+
25
+ def initialize(time)
26
+ @time = time
27
+ end
28
+
29
+ def build_ical(builder)
30
+ builder['UNTIL'] << IcalBuilder.ical_utc_format(time)
31
+ end
32
+
33
+ def build_hash(builder)
34
+ builder[:until] = TimeUtil.serialize_time(time)
35
+ end
36
+
37
+ def build_s(builder)
38
+ builder.piece(:until) << "until #{time.strftime(TO_S_TIME_FORMAT)}"
39
+ end
40
+
41
+ def validate(t, schedule)
42
+ raise UntilExceeded if t > time
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,50 @@
1
+ require 'date'
2
+
3
+ module IceCube
4
+
5
+ module Validations::WeeklyInterval
6
+
7
+ def interval(interval)
8
+ validations_for(:interval) << Validation.new(interval)
9
+ clobber_base_validations(:day)
10
+ end
11
+
12
+ class Validation
13
+
14
+ attr_reader :interval
15
+
16
+ def type
17
+ :day
18
+ end
19
+
20
+ def build_s(builder)
21
+ builder.base = interval == 1 ? 'Weekly' : "Every #{interval} weeks"
22
+ end
23
+
24
+ def build_ical(builder)
25
+ builder['FREQ'] << 'WEEKLY'
26
+ end
27
+
28
+ def build_hash(builder)
29
+ builder.validations[:interval] = interval
30
+ end
31
+
32
+ def initialize(interval)
33
+ @interval = interval
34
+ end
35
+
36
+ def validate(time, schedule)
37
+ date = Date.new(time.year, time.month, time.day)
38
+ st = schedule.start_time
39
+ start_date = Date.new(st.year, st.month, st.day)
40
+ weeks = ((date - date.wday) - (start_date - start_date.wday)) / 7
41
+ unless weeks % interval == 0
42
+ (interval - (weeks % interval)) * 7
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
50
+ end
@@ -0,0 +1,45 @@
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.validations[:interval] = interval
24
+ end
25
+
26
+ def build_ical(builder)
27
+ builder['FREQ'] << 'YEARLY'
28
+ end
29
+
30
+ def initialize(interval)
31
+ @interval = interval
32
+ end
33
+
34
+ def validate(time, schedule)
35
+ years_to_start = time.year - schedule.start_time.year
36
+ unless years_to_start % interval == 0
37
+ interval - (years_to_start % interval)
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+
45
+ end
@@ -1,5 +1,5 @@
1
1
  module IceCube
2
-
3
- VERSION = '0.6.14'
2
+
3
+ VERSION = '0.7.0'
4
4
 
5
5
  end
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + '/../lib/ice_cube'
2
+
3
+ begin
4
+ require 'cover_me'
5
+ # https://github.com/markbates/cover_me/issues/50
6
+ at_exit do
7
+ CoverMe.complete!
8
+ end
9
+ rescue LoadError
10
+ end
11
+
12
+ DAY = Time.utc(2010, 3, 1)
13
+ WEDNESDAY = Time.utc(2010, 6, 23, 5, 0, 0)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ice_cube
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.14
4
+ version: 0.7.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-14 00:00:00.000000000Z
12
+ date: 2011-12-08 00:00:00.000000000 -05:00
13
+ default_executable:
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: rspec
16
- requirement: &70254752836240 !ruby/object:Gem::Requirement
17
+ requirement: &70154139759660 !ruby/object:Gem::Requirement
17
18
  none: false
18
19
  requirements:
19
20
  - - ! '>='
@@ -21,7 +22,29 @@ dependencies:
21
22
  version: '0'
22
23
  type: :development
23
24
  prerelease: false
24
- version_requirements: *70254752836240
25
+ version_requirements: *70154139759660
26
+ - !ruby/object:Gem::Dependency
27
+ name: active_support
28
+ requirement: &70154139758460 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 3.0.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *70154139758460
37
+ - !ruby/object:Gem::Dependency
38
+ name: tzinfo
39
+ requirement: &70154139757400 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *70154139757400
25
48
  description: ice_cube is a recurring date library for Ruby. It allows for quick,
26
49
  programatic expansion of recurring date rules.
27
50
  email: john@crepezzi.com
@@ -29,8 +52,12 @@ executables: []
29
52
  extensions: []
30
53
  extra_rdoc_files: []
31
54
  files:
55
+ - lib/ice_cube/builders/hash_builder.rb
56
+ - lib/ice_cube/builders/ical_builder.rb
57
+ - lib/ice_cube/builders/string_builder.rb
58
+ - lib/ice_cube/errors/count_exceeded.rb
59
+ - lib/ice_cube/errors/until_exceeded.rb
32
60
  - lib/ice_cube/rule.rb
33
- - lib/ice_cube/rule_occurrence.rb
34
61
  - lib/ice_cube/rules/daily_rule.rb
35
62
  - lib/ice_cube/rules/hourly_rule.rb
36
63
  - lib/ice_cube/rules/minutely_rule.rb
@@ -39,19 +66,32 @@ files:
39
66
  - lib/ice_cube/rules/weekly_rule.rb
40
67
  - lib/ice_cube/rules/yearly_rule.rb
41
68
  - lib/ice_cube/schedule.rb
69
+ - lib/ice_cube/single_occurrence_rule.rb
42
70
  - lib/ice_cube/time_util.rb
43
- - lib/ice_cube/validation.rb
44
- - lib/ice_cube/validation_types.rb
71
+ - lib/ice_cube/validated_rule.rb
72
+ - lib/ice_cube/validations/count.rb
73
+ - lib/ice_cube/validations/daily_interval.rb
45
74
  - lib/ice_cube/validations/day.rb
46
75
  - lib/ice_cube/validations/day_of_month.rb
47
76
  - lib/ice_cube/validations/day_of_week.rb
48
77
  - lib/ice_cube/validations/day_of_year.rb
49
78
  - lib/ice_cube/validations/hour_of_day.rb
79
+ - lib/ice_cube/validations/hourly_interval.rb
80
+ - lib/ice_cube/validations/lock.rb
50
81
  - lib/ice_cube/validations/minute_of_hour.rb
82
+ - lib/ice_cube/validations/minutely_interval.rb
51
83
  - lib/ice_cube/validations/month_of_year.rb
84
+ - lib/ice_cube/validations/monthly_interval.rb
85
+ - lib/ice_cube/validations/schedule_lock.rb
52
86
  - lib/ice_cube/validations/second_of_minute.rb
87
+ - lib/ice_cube/validations/secondly_interval.rb
88
+ - lib/ice_cube/validations/until.rb
89
+ - lib/ice_cube/validations/weekly_interval.rb
90
+ - lib/ice_cube/validations/yearly_interval.rb
53
91
  - lib/ice_cube/version.rb
54
92
  - lib/ice_cube.rb
93
+ - spec/spec_helper.rb
94
+ has_rdoc: true
55
95
  homepage: http://seejohnrun.github.com/ice_cube/
56
96
  licenses: []
57
97
  post_install_message:
@@ -72,8 +112,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
112
  version: '0'
73
113
  requirements: []
74
114
  rubyforge_project: ice-cube
75
- rubygems_version: 1.8.10
115
+ rubygems_version: 1.6.2
76
116
  signing_key:
77
117
  specification_version: 3
78
118
  summary: Ruby Date Recurrence Library
79
- test_files: []
119
+ test_files:
120
+ - spec/spec_helper.rb
@@ -1,94 +0,0 @@
1
- module IceCube
2
-
3
- class RuleOccurrence
4
-
5
- def to_time
6
- @date
7
- end
8
-
9
- def all_occurrences
10
- raise ArgumentError.new("Rule must specify either an until date or a count to use 'all_occurrences'") unless @rule.occurrence_count || @rule.until_date || @end_time
11
- find_occurrences { |roc| false }
12
- end
13
-
14
- def between(begin_time, end_time)
15
- find_occurrences { |roc| roc > end_time }.select { |d| d >= begin_time }
16
- end
17
-
18
- def upto(end_date)
19
- find_occurrences { |roc| roc > end_date }
20
- end
21
-
22
- # Break after the first occurrence after now
23
- def next_occurrence(from)
24
- next_occurrences(1, from).first
25
- end
26
-
27
- # Break after the first n occurrences after now
28
- def next_occurrences(n, from, exclude_dates)
29
- found_all = false
30
- num_found = 0
31
- nexts = find_occurrences do |roc|
32
- num_found += 1 if roc > from && !exclude_dates.include?(roc.to_time)
33
- success = found_all
34
- found_all = num_found == n
35
- success
36
- end
37
- #Since the above returns all up to and including the next N that were requested, we need
38
- #to grab the last n, making sure to prune out ones that were actually before the from time
39
- nexts.last(n).select{|occurrence| occurrence > from}
40
- end
41
-
42
- def first(n)
43
- count = 0
44
- find_occurrences { |roc| count += 1; count > n }
45
- end
46
-
47
- #get the next occurrence of this rule
48
- def succ
49
- return nil if @rule.occurrence_count && @index >= @rule.occurrence_count # count check
50
- # get the next date to walk to
51
- if @date.nil?
52
- date = @start_date if @rule.validate_single_date(@start_date)
53
- date = @rule.next_suggestion(@start_date) unless date
54
- else
55
- date = @rule.next_suggestion(@date)
56
- end
57
- # walk through all of the successive dates, looking for the next occurrence (interval-valid), then return it.
58
- begin
59
- return nil if @end_time && date > @end_time
60
- return nil if @rule.until_date && date > @rule.until_date # until check
61
- next unless @rule.in_interval?(date, @start_date)
62
- return nil if yield(date)
63
- return RuleOccurrence.new(@rule, @start_date, @end_time, date, @index + 1)
64
- end while date = @rule.next_suggestion(date)
65
- end
66
-
67
- attr_reader :rule
68
- attr_accessor :start_date
69
-
70
- private
71
-
72
- def find_occurrences(&block)
73
- include_dates = []
74
- roc = self
75
- begin
76
- break if roc.nil? #go until we run out of dates
77
- next if roc.to_time.nil? #handle the case where start_date is not a valid occurrence
78
- include_dates << roc.to_time
79
- end while roc = roc.succ(&block)
80
- include_dates
81
- end
82
-
83
- def initialize(rule, start_date, end_time, date = nil, index = 0)
84
- #set some variables
85
- @rule = rule
86
- @start_date = start_date
87
- @end_time = end_time
88
- @date = date
89
- @index = index
90
- end
91
-
92
- end
93
-
94
- end