ice_cube 0.10.1 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,65 @@
1
+ module IceCube
2
+ class Enumerator < ::Enumerator
3
+
4
+ def initialize(schedule, from_time, to_time)
5
+ @schedule = schedule
6
+ @from_time = TimeUtil.ensure_time(from_time)
7
+ @to_time = TimeUtil.ensure_time(to_time)
8
+ align_start_time
9
+ @cursor = @from_time
10
+ end
11
+
12
+ def each
13
+ while res = self.find_next && @to_time.nil? || res <= @to_time
14
+ yield Occurrence.new(res, res + schedule.duration)
15
+ end
16
+ raise StopIteration
17
+ end
18
+
19
+ def find_next
20
+ loop do
21
+ min_time = recurrence_rules.reduce(nil) do |min_time, rule|
22
+ begin
23
+ new_time = rule.next_time(time, schedule, min_time || @to_time)
24
+ [min_time, new_time].compact.min
25
+ rescue CountExceeded, UntilExceeded
26
+ min_time
27
+ end
28
+ end
29
+ break nil unless min_time
30
+ @cursor = min_time + 1
31
+ next if exception_time?(min_time)
32
+ break min_time
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def align_start_time
39
+ if @from_time <= schedule.start_time || full_required?
40
+ @from_time = schedule.start_time
41
+ else
42
+ @from_time += @schedule.start_time.subsec - @from_time.subsec rescue 0
43
+ end
44
+ end
45
+
46
+ # Return a boolean indicating if any rule needs to be run from the start of time
47
+ def full_required?
48
+ recurrence_rules.any?(&:full_required?) ||
49
+ exception_rules.any?(&:full_required?)
50
+ end
51
+
52
+ def exception_rules
53
+ schedule.instance_variable_get(:@all_exception_rules)
54
+ end
55
+
56
+ def recurrence_rules
57
+ @recurrence_rules ||= if recurrence_rules.empty?
58
+ [SingleOccurrenceRule.new(schedule.start_time)].concat schedule.instance_variable_get(:@all_recurrence_rules)
59
+ else
60
+ schedule.instance_variable_get(:@all_recurrence_rules)
61
+ end
62
+ end
63
+
64
+ end
65
+ end
@@ -28,7 +28,7 @@ module IceCube
28
28
 
29
29
  # Optimize for common methods to avoid method_missing
30
30
  extend Forwardable
31
- def_delegators :start_time, :to_s, :to_i, :<=>, :==
31
+ def_delegators :start_time, :to_i, :<=>, :==
32
32
  def_delegators :to_range, :cover?, :include?, :each, :first, :last
33
33
 
34
34
  attr_reader :start_time, :end_time
@@ -79,12 +79,17 @@ module IceCube
79
79
  start_time
80
80
  end
81
81
 
82
- def to_s
83
- if duration > 0
84
- "#{start_time} - #{end_time}"
82
+ # Shows both the start and end time if there is a duration.
83
+ # Optional format argument (e.g. :long, :short) supports Rails
84
+ # time formats and is only used when ActiveSupport is available.
85
+ #
86
+ def to_s(format=nil)
87
+ if format && to_time.public_method(:to_s).arity > 0
88
+ t0, t1 = start_time.to_s(format), end_time.to_s(format)
85
89
  else
86
- "#{start_time}"
90
+ t0, t1 = start_time.to_s, end_time.to_s
87
91
  end
92
+ duration > 0 ? "#{t0} - #{t1}" : t0
88
93
  end
89
94
 
90
95
  def overnight?
@@ -172,6 +172,18 @@ module IceCube
172
172
  find_occurrences(from + 1, nil, 1).first
173
173
  end
174
174
 
175
+ # The previous occurrence from a given time
176
+ def previous_occurrence(from)
177
+ return nil if from <= start_time
178
+ find_occurrences(start_time, from - 1, nil, 1).last
179
+ end
180
+
181
+ # The previous n occurrences before a given time
182
+ def previous_occurrences(num, from)
183
+ return [] if from <= start_time
184
+ find_occurrences(start_time, from - 1, nil, num)
185
+ end
186
+
175
187
  # The remaining occurrences (same requirements as all_occurrences)
176
188
  def remaining_occurrences(from = nil)
177
189
  require_terminating_rules
@@ -268,6 +280,14 @@ module IceCube
268
280
  n.nil? ? occurrences.first : occurrences
269
281
  end
270
282
 
283
+ # Get the final n occurrences of a terminating schedule
284
+ # or the final one if no n is given
285
+ def last(n = nil)
286
+ require_terminating_rules
287
+ occurrences = find_occurrences(start_time, nil, nil, n || 1)
288
+ n.nil? ? occurrences.last : occurrences[-n..-1]
289
+ end
290
+
271
291
  # String serialization
272
292
  def to_s
273
293
  pieces = []
@@ -371,7 +391,7 @@ module IceCube
371
391
 
372
392
  # Find all of the occurrences for the schedule between opening_time
373
393
  # and closing_time
374
- def find_occurrences(opening_time, closing_time = nil, limit = nil, &block)
394
+ def find_occurrences(opening_time, closing_time = nil, limit = nil, tail_limit = nil, &block)
375
395
  opening_time = TimeUtil.ensure_time opening_time
376
396
  closing_time = TimeUtil.ensure_time closing_time
377
397
  opening_time += start_time.subsec - opening_time.subsec rescue 0
@@ -388,6 +408,7 @@ module IceCube
388
408
  break if closing_time && res > closing_time
389
409
  if res >= opening_time
390
410
  block_given? ? block.call(res) : (answers << res)
411
+ answers.shift if tail_limit && answers.length > tail_limit
391
412
  break if limit && answers.length == limit
392
413
  end
393
414
  time = res + 1
@@ -433,7 +454,7 @@ module IceCube
433
454
  raise ArgumentError, "All recurrence rules must specify .until or .count to use #{method_name}"
434
455
  end
435
456
 
436
- def implicit_start_occurrence
457
+ def implicit_start_occurrence_rule
437
458
  SingleOccurrenceRule.new(start_time)
438
459
  end
439
460
 
@@ -442,8 +463,8 @@ module IceCube
442
463
  end
443
464
 
444
465
  def recurrence_times_with_start_time
445
- if (recurrence_rules).empty?
446
- [start_time] + recurrence_times_without_start_time
466
+ if recurrence_rules.empty?
467
+ [start_time].concat recurrence_times_without_start_time
447
468
  else
448
469
  recurrence_times
449
470
  end
@@ -451,7 +472,7 @@ module IceCube
451
472
 
452
473
  def recurrence_rules_with_implicit_start_occurrence
453
474
  if recurrence_rules.empty?
454
- [implicit_start_occurrence] + @all_recurrence_rules
475
+ [implicit_start_occurrence_rule].concat @all_recurrence_rules
455
476
  else
456
477
  @all_recurrence_rules
457
478
  end
@@ -1,5 +1,5 @@
1
1
  module IceCube
2
2
 
3
- VERSION = '0.10.1'
3
+ VERSION = '0.11.0'
4
4
 
5
5
  end
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.10.1
4
+ version: 0.11.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-17 00:00:00.000000000 Z
12
+ date: 2013-06-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -86,6 +86,7 @@ files:
86
86
  - lib/ice_cube/builders/ical_builder.rb
87
87
  - lib/ice_cube/builders/string_builder.rb
88
88
  - lib/ice_cube/deprecated.rb
89
+ - lib/ice_cube/enumerator.rb
89
90
  - lib/ice_cube/errors/count_exceeded.rb
90
91
  - lib/ice_cube/errors/until_exceeded.rb
91
92
  - lib/ice_cube/flexible_hash.rb
@@ -140,7 +141,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
140
141
  version: '0'
141
142
  segments:
142
143
  - 0
143
- hash: 2800901123420442900
144
+ hash: 3343770401458335569
144
145
  required_rubygems_version: !ruby/object:Gem::Requirement
145
146
  none: false
146
147
  requirements:
@@ -149,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
150
  version: '0'
150
151
  segments:
151
152
  - 0
152
- hash: 2800901123420442900
153
+ hash: 3343770401458335569
153
154
  requirements: []
154
155
  rubyforge_project: ice-cube
155
156
  rubygems_version: 1.8.25