ice_cube 0.6.14 → 0.7.0

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