Class: IceCube::Schedule

Inherits:
Object
  • Object
show all
Extended by:
Deprecated
Defined in:
lib/ice_cube/schedule.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Deprecated

deprecated, deprecated_alias, schedule_options

Constructor Details

#initialize(start_time = nil, options = {}) {|_self| ... } ⇒ Schedule

Create a new schedule

Yields:

  • (_self)

Yield Parameters:



18
19
20
21
22
23
24
25
# File 'lib/ice_cube/schedule.rb', line 18

def initialize(start_time = nil, options = {})
  self.start_time = start_time || TimeUtil.now
  self.end_time = self.start_time + options[:duration] if options[:duration]
  self.end_time = options[:end_time] if options[:end_time]
  @all_recurrence_rules = []
  @all_exception_rules = []
  yield self if block_given?
end

Instance Attribute Details

#end_timeObject

Get the end time



14
15
16
# File 'lib/ice_cube/schedule.rb', line 14

def end_time
  @end_time
end

#start_timeObject

Get the start time



10
11
12
# File 'lib/ice_cube/schedule.rb', line 10

def start_time
  @start_time
end

Class Method Details

.dump(schedule) ⇒ Object



403
404
405
406
# File 'lib/ice_cube/schedule.rb', line 403

def self.dump(schedule)
  return schedule if schedule.nil? || schedule == ""
  schedule.to_yaml
end

.from_hash(original_hash, options = {}) ⇒ Object

Load the schedule from a hash



377
378
379
380
381
382
# File 'lib/ice_cube/schedule.rb', line 377

def self.from_hash(original_hash, options = {})
  HashParser.new(original_hash).to_schedule do |schedule|
    Deprecated.schedule_options(schedule, options)
    yield schedule if block_given?
  end
end

.from_ical(ical, options = {}) ⇒ Object

Load the schedule from ical



339
340
341
# File 'lib/ice_cube/schedule.rb', line 339

def self.from_ical(ical, options = {})
  IcalParser.schedule_from_ical(ical, options)
end

.from_yaml(yaml, options = {}) ⇒ Object

Load the schedule from yaml



349
350
351
352
353
354
# File 'lib/ice_cube/schedule.rb', line 349

def self.from_yaml(yaml, options = {})
  YamlParser.new(yaml).to_schedule do |schedule|
    Deprecated.schedule_options(schedule, options)
    yield schedule if block_given?
  end
end

.load(yaml) ⇒ Object



408
409
410
411
# File 'lib/ice_cube/schedule.rb', line 408

def self.load(yaml)
  return yaml if yaml.nil? || yaml == ""
  from_yaml(yaml)
end

Instance Method Details

#add_exception_rule(rule) ⇒ Object Also known as: exrule

Add an exception rule to the schedule



83
84
85
86
# File 'lib/ice_cube/schedule.rb', line 83

def add_exception_rule(rule)
  return if rule.nil?
  @all_exception_rules << rule unless @all_exception_rules.include?(rule)
end

#add_exception_time(time) ⇒ Object Also known as: extime

Add an exception time to the schedule



59
60
61
62
63
64
# File 'lib/ice_cube/schedule.rb', line 59

def add_exception_time(time)
  return if time.nil?
  rule = SingleOccurrenceRule.new(time)
  add_exception_rule rule
  time
end

#add_recurrence_rule(rule) ⇒ Object Also known as: rrule

Add a recurrence rule to the schedule



70
71
72
73
# File 'lib/ice_cube/schedule.rb', line 70

def add_recurrence_rule(rule)
  return if rule.nil?
  @all_recurrence_rules << rule unless @all_recurrence_rules.include?(rule)
end

#add_recurrence_time(time) ⇒ Object Also known as: rtime

Add a recurrence time to the schedule



48
49
50
51
52
53
# File 'lib/ice_cube/schedule.rb', line 48

def add_recurrence_time(time)
  return if time.nil?
  rule = SingleOccurrenceRule.new(time)
  add_recurrence_rule rule
  time
end

#all_occurrencesObject

All of the occurrences



154
155
156
157
# File 'lib/ice_cube/schedule.rb', line 154

def all_occurrences
  require_terminating_rules
  enumerate_occurrences(start_time).to_a
end

#all_occurrences_enumeratorObject

Emit an enumerator based on the start time



160
161
162
# File 'lib/ice_cube/schedule.rb', line 160

def all_occurrences_enumerator
  enumerate_occurrences(start_time)
end

#conflicts_with?(other_schedule, closing_time = nil) ⇒ Boolean

Determine if this schedule conflicts with another schedule

Parameters:

  • other_schedule (IceCube::Schedule)
    • The schedule to compare to

  • closing_time (Time) (defaults to: nil)
    • the last time to consider

Returns:

  • (Boolean)

    whether or not the schedules conflict at all



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/ice_cube/schedule.rb', line 257

def conflicts_with?(other_schedule, closing_time = nil)
  closing_time = TimeUtil.ensure_time(closing_time)
  unless terminating? || other_schedule.terminating? || closing_time
    raise ArgumentError, "One or both schedules must be terminating to use #conflicts_with?"
  end
  # Pick the terminating schedule, and other schedule
  # No need to reverse if terminating? or there is a closing time
  terminating_schedule = self
  unless terminating? || closing_time
    terminating_schedule, other_schedule = other_schedule, terminating_schedule
  end
  # Go through each occurrence of the terminating schedule and determine
  # if the other occurs at that time
  #
  last_time = nil
  terminating_schedule.each_occurrence do |time|
    if closing_time && time > closing_time
      last_time = closing_time
      break
    end
    last_time = time
    return true if other_schedule.occurring_at?(time)
  end
  # Due to durations, we need to walk up to the end time, and verify in the
  # other direction
  if last_time
    last_time += terminating_schedule.duration
    other_schedule.each_occurrence do |time|
      break if time > last_time
      return true if terminating_schedule.occurring_at?(time)
    end
  end
  # No conflict, return false
  false
end

#durationObject



39
40
41
# File 'lib/ice_cube/schedule.rb', line 39

def duration
  end_time ? end_time - start_time : 0
end

#duration=(seconds) ⇒ Object



43
44
45
# File 'lib/ice_cube/schedule.rb', line 43

def duration=(seconds)
  @end_time = start_time + seconds
end

#each_occurrence(&block) ⇒ Object

Iterate forever



165
166
167
168
# File 'lib/ice_cube/schedule.rb', line 165

def each_occurrence(&block)
  enumerate_occurrences(start_time, &block).to_a
  self
end

#encode_with(coder) ⇒ Object

Hook for YAML.dump, enables to_yaml



344
345
346
# File 'lib/ice_cube/schedule.rb', line 344

def encode_with(coder)
  coder.represent_object nil, to_hash
end

#eql?(other) ⇒ Boolean Also known as: ==

Returns:

  • (Boolean)


398
399
400
# File 'lib/ice_cube/schedule.rb', line 398

def eql?(other)
  self.hash == other.hash
end

#exception_rulesObject Also known as: exrules

Get the exception rules



102
103
104
# File 'lib/ice_cube/schedule.rb', line 102

def exception_rules
  @all_exception_rules.reject { |r| r.is_a?(SingleOccurrenceRule) }
end

#exception_timesObject Also known as: extimes

Get the exception times that are on the schedule



128
129
130
# File 'lib/ice_cube/schedule.rb', line 128

def exception_times
  @all_exception_rules.select { |r| r.is_a?(SingleOccurrenceRule) }.map(&:time)
end

#first(n = nil) ⇒ Object

Get the first n occurrences, or the first occurrence if n is skipped



299
300
301
302
# File 'lib/ice_cube/schedule.rb', line 299

def first(n = nil)
  occurrences = enumerate_occurrences(start_time).take(n || 1)
  n.nil? ? occurrences.first : occurrences
end

#hashObject



390
391
392
393
394
395
396
# File 'lib/ice_cube/schedule.rb', line 390

def hash
  [
    TimeUtil.hash(start_time), duration,
    *@all_recurrence_rules.map(&:hash).sort!,
    *@all_exception_rules.map(&:hash).sort!
  ].hash
end

#last(n = nil) ⇒ Object

Get the final n occurrences of a terminating schedule or the final one if no n is given



306
307
308
309
310
# File 'lib/ice_cube/schedule.rb', line 306

def last(n = nil)
  require_terminating_rules
  occurrences = enumerate_occurrences(start_time).to_a
  n.nil? ? occurrences.last : occurrences[-n..-1]
end

#next_occurrence(from = nil, options = {}) ⇒ Object

The next occurrence after now (overridable)



177
178
179
180
181
182
# File 'lib/ice_cube/schedule.rb', line 177

def next_occurrence(from = nil, options = {})
  from = TimeUtil.match_zone(from, start_time) || TimeUtil.now(start_time)
  enumerate_occurrences(from + 1, nil, options).next
rescue StopIteration
  nil
end

#next_occurrences(num, from = nil, options = {}) ⇒ Object

The next n occurrences after now



171
172
173
174
# File 'lib/ice_cube/schedule.rb', line 171

def next_occurrences(num, from = nil, options = {})
  from = TimeUtil.match_zone(from, start_time) || TimeUtil.now(start_time)
  enumerate_occurrences(from + 1, nil, options).take(num)
end

#occurrences(closing_time) ⇒ Object

Get all of the occurrences from the start_time up until a given Time



149
150
151
# File 'lib/ice_cube/schedule.rb', line 149

def occurrences(closing_time)
  enumerate_occurrences(start_time, closing_time).to_a
end

#occurrences_between(begin_time, closing_time, options = {}) ⇒ Object

Occurrences between two times



213
214
215
# File 'lib/ice_cube/schedule.rb', line 213

def occurrences_between(begin_time, closing_time, options = {})
  enumerate_occurrences(begin_time, closing_time, options).to_a
end

#occurring_at?(time) ⇒ Boolean

Determine if the schedule is occurring at a given time

Returns:

  • (Boolean)


243
244
245
246
247
248
249
250
251
# File 'lib/ice_cube/schedule.rb', line 243

def occurring_at?(time)
  time = TimeUtil.match_zone(time, start_time) or raise ArgumentError, "Time required, got #{time.inspect}"
  if duration > 0
    return false if exception_time?(time)
    occurs_between?(time - duration + 1, time)
  else
    occurs_at?(time)
  end
end

#occurring_between?(opening_time, closing_time) ⇒ Boolean

Return a boolean indicating if an occurrence is occurring between two times, inclusive of its duration. This counts zero-length occurrences that intersect the start of the range and within the range, but not occurrences at the end of the range since none of their duration intersects the range.

Returns:

  • (Boolean)


230
231
232
# File 'lib/ice_cube/schedule.rb', line 230

def occurring_between?(opening_time, closing_time)
  occurs_between?(opening_time, closing_time, :spans => true)
end

#occurs_at?(time) ⇒ Boolean

Determine if the schedule occurs at a specific time

Returns:

  • (Boolean)


294
295
296
# File 'lib/ice_cube/schedule.rb', line 294

def occurs_at?(time)
  occurs_between?(time, time)
end

#occurs_between?(begin_time, closing_time, options = {}) ⇒ Boolean

Return a boolean indicating if an occurrence falls between two times

Returns:

  • (Boolean)


218
219
220
221
222
223
# File 'lib/ice_cube/schedule.rb', line 218

def occurs_between?(begin_time, closing_time, options = {})
  enumerate_occurrences(begin_time, closing_time, options).next
  true
rescue StopIteration
  false
end

#occurs_on?(date) ⇒ Boolean

Return a boolean indicating if an occurrence falls on a certain date

Returns:

  • (Boolean)


235
236
237
238
239
240
# File 'lib/ice_cube/schedule.rb', line 235

def occurs_on?(date)
  date = TimeUtil.ensure_date(date)
  begin_time = TimeUtil.beginning_of_date(date, start_time)
  closing_time = TimeUtil.end_of_date(date, start_time)
  occurs_between?(begin_time, closing_time)
end

#previous_occurrence(from) ⇒ Object

The previous occurrence from a given time



185
186
187
188
189
# File 'lib/ice_cube/schedule.rb', line 185

def previous_occurrence(from)
  from = TimeUtil.match_zone(from, start_time) or raise ArgumentError, "Time required, got #{from.inspect}"
  return nil if from <= start_time
  enumerate_occurrences(start_time, from - 1).to_a.last
end

#previous_occurrences(num, from) ⇒ Object

The previous n occurrences before a given time



192
193
194
195
196
197
# File 'lib/ice_cube/schedule.rb', line 192

def previous_occurrences(num, from)
  from = TimeUtil.match_zone(from, start_time) or raise ArgumentError, "Time required, got #{from.inspect}"
  return [] if from <= start_time
  a = enumerate_occurrences(start_time, from - 1).to_a
  a.size > num ? a[-1*num,a.size] : a
end

#recurrence_rulesObject Also known as: rrules

Get the recurrence rules



96
97
98
# File 'lib/ice_cube/schedule.rb', line 96

def recurrence_rules
  @all_recurrence_rules.reject { |r| r.is_a?(SingleOccurrenceRule) }
end

#recurrence_timesObject Also known as: rtimes

Get the recurrence times that are on the schedule



108
109
110
# File 'lib/ice_cube/schedule.rb', line 108

def recurrence_times
  @all_recurrence_rules.select { |r| r.is_a?(SingleOccurrenceRule) }.map(&:time)
end

#remaining_occurrences(from = nil, options = {}) ⇒ Object

The remaining occurrences (same requirements as all_occurrences)



200
201
202
203
204
# File 'lib/ice_cube/schedule.rb', line 200

def remaining_occurrences(from = nil, options = {})
  require_terminating_rules
  from ||= TimeUtil.now(@start_time)
  enumerate_occurrences(from, nil, options).to_a
end

#remaining_occurrences_enumerator(from = nil, options = {}) ⇒ Object

Returns an enumerator for all remaining occurrences



207
208
209
210
# File 'lib/ice_cube/schedule.rb', line 207

def remaining_occurrences_enumerator(from = nil, options = {})
  from ||= TimeUtil.now(@start_time)
  enumerate_occurrences(from, nil, options)
end

#remove_exception_rule(rule) ⇒ Object

Remove an exception rule



90
91
92
93
# File 'lib/ice_cube/schedule.rb', line 90

def remove_exception_rule(rule)
  res = @all_exception_rules.delete(rule)
  res.nil? ? [] : [res]
end

#remove_exception_time(time) ⇒ Object Also known as: remove_extime

Remove an exception time



136
137
138
139
140
141
142
# File 'lib/ice_cube/schedule.rb', line 136

def remove_exception_time(time)
  found = false
  @all_exception_rules.delete_if do |rule|
    found = true if rule.is_a?(SingleOccurrenceRule) && rule.time == time
  end
  time if found
end

#remove_recurrence_rule(rule) ⇒ Object

Remove a recurrence rule



77
78
79
80
# File 'lib/ice_cube/schedule.rb', line 77

def remove_recurrence_rule(rule)
  res = @all_recurrence_rules.delete(rule)
  res.nil? ? [] : [res]
end

#remove_recurrence_time(time) ⇒ Object Also known as: remove_rtime

Remove a recurrence time



116
117
118
119
120
121
122
# File 'lib/ice_cube/schedule.rb', line 116

def remove_recurrence_time(time)
  found = false
  @all_recurrence_rules.delete_if do |rule|
    found = true if rule.is_a?(SingleOccurrenceRule) && rule.time == time
  end
  time if found
end

#terminating?Boolean

Determine if the schedule will end

Returns:

  • (Boolean)

    true if ending, false if repeating forever



386
387
388
# File 'lib/ice_cube/schedule.rb', line 386

def terminating?
  @all_recurrence_rules.all?(&:terminating?)
end

#to_hashObject Also known as: to_h

Convert the schedule to a hash



357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
# File 'lib/ice_cube/schedule.rb', line 357

def to_hash
  data = {}
  data[:start_time] = TimeUtil.serialize_time(start_time)
  data[:start_date] = data[:start_time] if IceCube.compatibility <= 11
  data[:end_time] = TimeUtil.serialize_time(end_time) if end_time
  data[:rrules] = recurrence_rules.map(&:to_hash)
  if IceCube.compatibility <= 11 && exception_rules.any?
    data[:exrules] = exception_rules.map(&:to_hash)
  end
  data[:rtimes] = recurrence_times.map do |rt|
    TimeUtil.serialize_time(rt)
  end
  data[:extimes] = exception_times.map do |et|
    TimeUtil.serialize_time(et)
  end
  data
end

#to_ical(force_utc = false) ⇒ Object

Serialize this schedule to_ical



327
328
329
330
331
332
333
334
335
336
# File 'lib/ice_cube/schedule.rb', line 327

def to_ical(force_utc = false)
  pieces = []
  pieces << "DTSTART#{IcalBuilder.ical_format(start_time, force_utc)}"
  pieces.concat recurrence_rules.map { |r| "RRULE:#{r.to_ical}" }
  pieces.concat exception_rules.map  { |r| "EXRULE:#{r.to_ical}" }
  pieces.concat recurrence_times_without_start_time.map { |t| "RDATE#{IcalBuilder.ical_format(t, force_utc)}" }
  pieces.concat exception_times.map  { |t| "EXDATE#{IcalBuilder.ical_format(t, force_utc)}" }
  pieces << "DTEND#{IcalBuilder.ical_format(end_time, force_utc)}" if end_time
  pieces.join("\n")
end

#to_sObject

String serialization



313
314
315
316
317
318
319
320
321
322
323
324
# File 'lib/ice_cube/schedule.rb', line 313

def to_s
  pieces = []
  rd = recurrence_times_with_start_time - extimes
  pieces.concat rd.sort.map { |t| IceCube::I18n.l(t, format: IceCube.to_s_time_format) }
  pieces.concat rrules.map  { |t| t.to_s }
  pieces.concat exrules.map { |t| IceCube::I18n.t('ice_cube.not', target: t.to_s) }
  pieces.concat extimes.sort.map { |t|
    target = IceCube::I18n.l(t, format: IceCube.to_s_time_format)
    IceCube::I18n.t('ice_cube.not_on', target: target)
  }
  pieces.join(IceCube::I18n.t('ice_cube.pieces_connector'))
end