Class: Icalendar::Recurrence::Schedule

Inherits:
Object
  • Object
show all
Defined in:
lib/icalendar/recurrence/schedule.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(event) ⇒ Schedule

Returns a new instance of Schedule.



11
12
13
# File 'lib/icalendar/recurrence/schedule.rb', line 11

def initialize(event)
  @event = event
end

Instance Attribute Details

#eventObject (readonly)

Returns the value of attribute event.



9
10
11
# File 'lib/icalendar/recurrence/schedule.rb', line 9

def event
  @event
end

Instance Method Details

#base_ice_cube_recurrence_rule(frequency, interval) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/icalendar/recurrence/schedule.rb', line 109

def base_ice_cube_recurrence_rule(frequency, interval)
  interval ||= 1
  if frequency == "DAILY"
    IceCube::DailyRule.new(interval)
  elsif frequency == "WEEKLY"
    IceCube::WeeklyRule.new(interval)
  elsif frequency == "MONTHLY"
    IceCube::MonthlyRule.new(interval)
  elsif frequency == "YEARLY"
    IceCube::YearlyRule.new(interval)
  else
    raise "Unknown frequency: #{rrule.frequency}"
  end
end

#convert_byday_to_ice_cube_day_of_week_hash(ical_byday) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/icalendar/recurrence/schedule.rb', line 124

def convert_byday_to_ice_cube_day_of_week_hash(ical_byday)
  data = parse_ical_byday(ical_byday)
  day_code = data.fetch(:day_code)
  position = data.fetch(:position)

  day_symbol = case day_code.to_s
  when "SU" then :sunday
  when "MO" then :monday
  when "TU" then :tuesday
  when "WE" then :wednesday
  when "TH" then :thursday
  when "FR" then :friday
  when "SA" then :saturday
  else
    raise ArgumentError.new "Unexpected ical_day: #{ical_day.inspect}"
  end

  [day_symbol, Array(position)]
end

#convert_duration_to_seconds(ical_duration) ⇒ Object



152
153
154
155
156
157
158
# File 'lib/icalendar/recurrence/schedule.rb', line 152

def convert_duration_to_seconds(ical_duration)
  return 0 unless ical_duration

  conversion_rates = { seconds: 1, minutes: 60, hours: 3600, days: 86400, weeks: 604800 }
  seconds = conversion_rates.inject(0) { |sum, (unit, multiplier)| sum + ical_duration[unit] * multiplier }
  seconds * (ical_duration.past ? -1 : 1)
end

#convert_ice_cube_occurrence(ice_cube_occurrence) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/icalendar/recurrence/schedule.rb', line 43

def convert_ice_cube_occurrence(ice_cube_occurrence)
  if timezone
    begin
      tz = TZInfo::Timezone.get(timezone)
      start_time = tz.local_to_utc(ice_cube_occurrence.start_time)
      end_time = tz.local_to_utc(ice_cube_occurrence.end_time)
    rescue TZInfo::InvalidTimezoneIdentifier => e
      warn "Unknown TZID specified in ical event (#{timezone.inspect}), ignoring (will likely cause event to be at wrong time!)"
    end
  end

  start_time ||= ice_cube_occurrence.start_time
  end_time ||= ice_cube_occurrence.end_time
  
  Icalendar::Recurrence::Occurrence.new(start_time, end_time)
end

#convert_rrule_to_ice_cube_recurrence_rule(rrule) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/icalendar/recurrence/schedule.rb', line 92

def convert_rrule_to_ice_cube_recurrence_rule(rrule)
  ice_cube_recurrence_rule = base_ice_cube_recurrence_rule(rrule.frequency, rrule.interval)

  ice_cube_recurrence_rule.tap do |r|
    days = transform_byday_to_hash(rrule.by_day)

    r.month_of_year(rrule.by_month) unless rrule.by_month.nil?
    r.day_of_month(rrule.by_month_day.map(&:to_i)) unless rrule.by_month_day.nil?
    r.day_of_week(days) if days.is_a?(Hash) and !days.empty?
    r.day(days) if days.is_a?(Array) and !days.empty?
    r.until(TimeUtil.to_time(rrule.until)) if rrule.until
    r.count(rrule.count)
  end

  ice_cube_recurrence_rule
end

#end_timeObject



27
28
29
30
31
32
33
# File 'lib/icalendar/recurrence/schedule.rb', line 27

def end_time
  if event.end
    TimeUtil.to_time(event.end)
  else
    start_time + convert_duration_to_seconds(event.duration)
  end
end

#ice_cube_scheduleObject



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/icalendar/recurrence/schedule.rb', line 60

def ice_cube_schedule
  schedule = IceCube::Schedule.new
  schedule.start_time = start_time
  schedule.end_time = end_time

  rrules.each do |rrule|
    ice_cube_recurrence_rule = convert_rrule_to_ice_cube_recurrence_rule(rrule)
    schedule.add_recurrence_rule(ice_cube_recurrence_rule)
  end

  event.exdate.each do |exception_date|
    exception_date = Time.parse(exception_date) if exception_date.is_a?(String)
    schedule.add_exception_time(TimeUtil.to_time(exception_date))
  end

  schedule
end

#occurrences_between(begin_time, closing_time) ⇒ Object



35
36
37
38
39
40
41
# File 'lib/icalendar/recurrence/schedule.rb', line 35

def occurrences_between(begin_time, closing_time)
  ice_cube_occurrences = ice_cube_schedule.occurrences_between(TimeUtil.to_time(begin_time), TimeUtil.to_time(closing_time))

  ice_cube_occurrences.map do |occurrence|
    convert_ice_cube_occurrence(occurrence)
  end
end

#parse_ical_byday(ical_byday) ⇒ Object

Parses ICAL BYDAY value to day and position array 1SA => “SA”, position: 1 MO => {day_code: “MO”, position: nil



147
148
149
150
# File 'lib/icalendar/recurrence/schedule.rb', line 147

def parse_ical_byday(ical_byday)
  match = ical_byday.match(/(\d*)([A-Z]{2})/)
  {day_code: match[2], position: match[1].to_i}
end

#rrulesObject



19
20
21
# File 'lib/icalendar/recurrence/schedule.rb', line 19

def rrules
  event.rrule
end

#start_timeObject



23
24
25
# File 'lib/icalendar/recurrence/schedule.rb', line 23

def start_time
  TimeUtil.to_time(event.start)
end

#timezoneObject



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

def timezone
  event.tzid
end

#transform_byday_to_hash(byday_entries) ⇒ Object



78
79
80
81
82
83
84
85
86
87
# File 'lib/icalendar/recurrence/schedule.rb', line 78

def transform_byday_to_hash(byday_entries)
  hashable_array = Array(byday_entries).map {|byday| convert_byday_to_ice_cube_day_of_week_hash(byday) }.flatten(1)
  hash = Hash[*hashable_array]

  if hash.values.include?([0]) # byday interval not specified (e.g., BYDAY=SA not BYDAY=1SA)
    hash.keys
  else
    hash
  end
end