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

Constructor Details

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

Create a new schedule



23
24
25
26
27
28
29
# File 'lib/ice_cube/schedule.rb', line 23

def initialize(start_time = nil, options = {})
  @start_time = start_time || Time.now
  @end_time = options[:end_time]
  @duration = options[:duration]
  @all_recurrence_rules = []
  @all_exception_rules = []
end

Instance Attribute Details

#durationObject

Get the duration



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

def duration
  @duration
end

#end_timeObject

Get the end time



18
19
20
# File 'lib/ice_cube/schedule.rb', line 18

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



323
324
325
# File 'lib/ice_cube/schedule.rb', line 323

def self.dump(schedule)
  schedule.to_yaml
end

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

Load the schedule from a hash



293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'lib/ice_cube/schedule.rb', line 293

def self.from_hash(data, options = {})
  data[:start_date] = options[:start_date_override] if options[:start_date_override]
  # And then deserialize
  schedule = IceCube::Schedule.new TimeUtil.deserialize_time(data[:start_date])
  schedule.duration = data[:duration] if data[:duration]
  schedule.end_time = TimeUtil.deserialize_time(data[:end_time]) if data[:end_time]
  data[:rrules] && data[:rrules].each { |h| schedule.rrule(IceCube::Rule.from_hash(h)) }  
  data[:exrules] && data[:exrules].each { |h| schedule.exrule(IceCube::Rule.from_hash(h)) }
  data[:rtimes] && data[:rtimes].each do |t|
    schedule.add_recurrence_time TimeUtil.deserialize_time(t)
  end
  data[:extimes] && data[:extimes].each do |t|
    schedule.add_exception_time TimeUtil.deserialize_time(t)
  end
  # Also serialize old format for backward compat
  data[:rdates] && data[:rdates].each do |t|
    schedule.add_recurrence_time TimeUtil.deserialize_time(t)
  end
  data[:exdates] && data[:exdates].each do |t|
    schedule.add_exception_time TimeUtil.deserialize_time(t)
  end
  schedule
end

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

Load the schedule from yaml



271
272
273
# File 'lib/ice_cube/schedule.rb', line 271

def self.from_yaml(yaml, options = {})
  from_hash IceCube::use_psych? ? Psych::load(yaml) : YAML::load(yaml), options
end

.load(yaml) ⇒ Object



327
328
329
# File 'lib/ice_cube/schedule.rb', line 327

def self.load(yaml)
  from_yaml(yaml) unless yaml.nil? || yaml.empty?
end

Instance Method Details

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

Add an exception rule to the schedule



66
67
68
# File 'lib/ice_cube/schedule.rb', line 66

def add_exception_rule(rule)
  @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



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

def add_exception_time(time)
  return nil 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



54
55
56
# File 'lib/ice_cube/schedule.rb', line 54

def add_recurrence_rule(rule)
  @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



32
33
34
35
36
37
# File 'lib/ice_cube/schedule.rb', line 32

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

#all_occurrencesObject

All of the occurrences

Raises:

  • (ArgumentError)


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

def all_occurrences
  raise ArgumentError.new('Rule must specify either an until date or a count to use #all_occurrences') unless terminating?
  find_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



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/ice_cube/schedule.rb', line 195

def conflicts_with?(other_schedule, closing_time = nil)
  unless terminating? || other_schedule.terminating? || closing_time
    raise ArgumentError.new 'At least one schedule 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 ? last_time + terminating_schedule.duration : last_time
    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

#each_occurrence(&block) ⇒ Object

Iterate forever



142
143
144
145
# File 'lib/ice_cube/schedule.rb', line 142

def each_occurrence(&block)
  find_occurrences(start_time, &block)
  self
end

#exception_rulesObject Also known as: exrules

Get the exception rules



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

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



110
111
112
# File 'lib/ice_cube/schedule.rb', line 110

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



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

def first(n = nil)
  occurrences = find_occurrences start_time, nil, n || 1
  n.nil? ? occurrences.first : occurrences
end

#next_occurrence(from = Time.now) ⇒ Object

The next occurrence after now (overridable)



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

def next_occurrence(from = Time.now)
  find_occurrences(from + 1, nil, 1).first
end

#next_occurrences(num, from = Time.now) ⇒ Object

The next n occurrences after now



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

def next_occurrences(num, from = Time.now)
  find_occurrences(from + 1, nil, num)
end

#occurrences(closing_time) ⇒ Object

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



131
132
133
# File 'lib/ice_cube/schedule.rb', line 131

def occurrences(closing_time)
  find_occurrences(start_time, closing_time)
end

#occurrences_between(begin_time, closing_time) ⇒ Object

Occurrences between two times



163
164
165
# File 'lib/ice_cube/schedule.rb', line 163

def occurrences_between(begin_time, closing_time)
  find_occurrences(begin_time, closing_time)
end

#occurring_at?(time) ⇒ Boolean

Determine if the schedule is occurring at a given time

Returns:

  • (Boolean)


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

def occurring_at?(time)
  time = time.to_time
  if duration
    return false if exception_time?(time)
    occurs_between?(time - duration + 1, time)
  else
    occurs_at?(time)
  end
end

#occurs_at?(time) ⇒ Boolean

Determine if the schedule occurs at a specific time

Returns:

  • (Boolean)


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

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

#occurs_between?(begin_time, closing_time) ⇒ Boolean

Return a boolean indicating if an occurrence falls between two times

Returns:

  • (Boolean)


169
170
171
# File 'lib/ice_cube/schedule.rb', line 169

def occurs_between?(begin_time, closing_time)
  !find_occurrences(begin_time, closing_time, 1).empty?
end

#occurs_on?(date) ⇒ Boolean

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

Returns:

  • (Boolean)


174
175
176
177
178
# File 'lib/ice_cube/schedule.rb', line 174

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

#recurrence_rulesObject Also known as: rrules

Get the recurrence rules



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

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



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

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

#remaining_occurrences(from = Time.now) ⇒ Object

The remaining occurrences (same requirements as all_occurrences)



158
159
160
# File 'lib/ice_cube/schedule.rb', line 158

def remaining_occurrences(from = Time.now)
  find_occurrences(from)
end

#remove_exception_rule(rule) ⇒ Object

Remove an exception rule



72
73
74
75
# File 'lib/ice_cube/schedule.rb', line 72

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



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

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



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

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



98
99
100
101
102
103
104
# File 'lib/ice_cube/schedule.rb', line 98

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



319
320
321
# File 'lib/ice_cube/schedule.rb', line 319

def terminating?
  end_time || recurrence_rules.all?(&:terminating?)
end

#to_hashObject

Convert the schedule to a hash



276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/ice_cube/schedule.rb', line 276

def to_hash
  data = {}
  data[:start_date] = TimeUtil.serialize_time(start_time)
  data[:end_time] = TimeUtil.serialize_time(end_time) if end_time
  data[:duration] = duration if duration
  data[:rrules] = recurrence_rules.map(&:to_hash)
  data[:exrules] = exception_rules.map(&:to_hash)
  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



253
254
255
256
257
258
259
260
261
262
263
# File 'lib/ice_cube/schedule.rb', line 253

def to_ical(force_utc = false)
  pieces = []
  pieces << "DTSTART#{IcalBuilder.ical_format(start_time, force_utc)}"
  pieces << "DURATION:#{IcalBuilder.ical_duration(duration)}" if duration
  pieces.concat recurrence_rules.map { |r| "RRULE:#{r.to_ical}" }
  pieces.concat exception_rules.map { |r| "EXRULE:#{r.to_ical}" }
  pieces.concat recurrence_times.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



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

def to_s
  pieces = []
  ed = extimes; rd = rtimes - ed
  pieces.concat rd.sort.map { |t| t.strftime(TO_S_TIME_FORMAT) }
  pieces.concat rrules.map { |t| t.to_s }
  pieces.concat exrules.map { |t| "not #{t.to_s}" }
  pieces.concat ed.sort.map { |t| "not on #{t.strftime(TO_S_TIME_FORMAT)}" }
  pieces << "until #{end_time.strftime(TO_S_TIME_FORMAT)}" if end_time
  pieces.join(' / ')
end

#to_yaml(*args) ⇒ Object

Convert the schedule to yaml



266
267
268
# File 'lib/ice_cube/schedule.rb', line 266

def to_yaml(*args)
  IceCube::use_psych? ? Psych::dump(to_hash, *args) : YAML::dump(to_hash, *args)
end