demingfactor-ri_cal 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/History.txt +402 -0
- data/Manifest.txt +161 -0
- data/README.txt +410 -0
- data/Rakefile +69 -0
- data/VERSION +1 -0
- data/bin/ri_cal +8 -0
- data/component_attributes/alarm.yml +10 -0
- data/component_attributes/calendar.yml +4 -0
- data/component_attributes/component_property_defs.yml +180 -0
- data/component_attributes/event.yml +45 -0
- data/component_attributes/freebusy.yml +16 -0
- data/component_attributes/journal.yml +35 -0
- data/component_attributes/timezone.yml +3 -0
- data/component_attributes/timezone_period.yml +11 -0
- data/component_attributes/todo.yml +46 -0
- data/copyrights.txt +1 -0
- data/docs/draft-ietf-calsify-2446bis-08.txt +7280 -0
- data/docs/draft-ietf-calsify-rfc2445bis-09.txt +10416 -0
- data/docs/incrementers.txt +7 -0
- data/docs/rfc2445.pdf +0 -0
- data/lib/ri_cal/component/alarm.rb +19 -0
- data/lib/ri_cal/component/calendar.rb +257 -0
- data/lib/ri_cal/component/event.rb +58 -0
- data/lib/ri_cal/component/freebusy.rb +16 -0
- data/lib/ri_cal/component/journal.rb +27 -0
- data/lib/ri_cal/component/non_standard.rb +33 -0
- data/lib/ri_cal/component/t_z_info_timezone.rb +153 -0
- data/lib/ri_cal/component/timezone/daylight_period.rb +25 -0
- data/lib/ri_cal/component/timezone/standard_period.rb +23 -0
- data/lib/ri_cal/component/timezone/timezone_period.rb +76 -0
- data/lib/ri_cal/component/timezone.rb +197 -0
- data/lib/ri_cal/component/todo.rb +42 -0
- data/lib/ri_cal/component.rb +256 -0
- data/lib/ri_cal/core_extensions/array/conversions.rb +15 -0
- data/lib/ri_cal/core_extensions/array.rb +7 -0
- data/lib/ri_cal/core_extensions/date/conversions.rb +56 -0
- data/lib/ri_cal/core_extensions/date.rb +13 -0
- data/lib/ri_cal/core_extensions/date_time/conversions.rb +50 -0
- data/lib/ri_cal/core_extensions/date_time.rb +15 -0
- data/lib/ri_cal/core_extensions/object/conversions.rb +20 -0
- data/lib/ri_cal/core_extensions/object.rb +8 -0
- data/lib/ri_cal/core_extensions/string/conversions.rb +57 -0
- data/lib/ri_cal/core_extensions/string.rb +8 -0
- data/lib/ri_cal/core_extensions/time/calculations.rb +153 -0
- data/lib/ri_cal/core_extensions/time/conversions.rb +42 -0
- data/lib/ri_cal/core_extensions/time/tzid_access.rb +50 -0
- data/lib/ri_cal/core_extensions/time/week_day_predicates.rb +55 -0
- data/lib/ri_cal/core_extensions/time.rb +14 -0
- data/lib/ri_cal/core_extensions.rb +11 -0
- data/lib/ri_cal/fast_date_time.rb +234 -0
- data/lib/ri_cal/floating_timezone.rb +32 -0
- data/lib/ri_cal/invalid_property_value.rb +8 -0
- data/lib/ri_cal/invalid_timezone_identifier.rb +20 -0
- data/lib/ri_cal/occurrence_enumerator.rb +265 -0
- data/lib/ri_cal/occurrence_period.rb +17 -0
- data/lib/ri_cal/parser.rb +148 -0
- data/lib/ri_cal/properties/alarm.rb +390 -0
- data/lib/ri_cal/properties/calendar.rb +164 -0
- data/lib/ri_cal/properties/event.rb +1523 -0
- data/lib/ri_cal/properties/freebusy.rb +593 -0
- data/lib/ri_cal/properties/journal.rb +1237 -0
- data/lib/ri_cal/properties/timezone.rb +150 -0
- data/lib/ri_cal/properties/timezone_period.rb +416 -0
- data/lib/ri_cal/properties/todo.rb +1559 -0
- data/lib/ri_cal/properties.rb +12 -0
- data/lib/ri_cal/property_value/array.rb +27 -0
- data/lib/ri_cal/property_value/cal_address.rb +11 -0
- data/lib/ri_cal/property_value/date.rb +184 -0
- data/lib/ri_cal/property_value/date_time/additive_methods.rb +44 -0
- data/lib/ri_cal/property_value/date_time/time_machine.rb +159 -0
- data/lib/ri_cal/property_value/date_time/timezone_support.rb +100 -0
- data/lib/ri_cal/property_value/date_time.rb +359 -0
- data/lib/ri_cal/property_value/duration.rb +110 -0
- data/lib/ri_cal/property_value/geo.rb +11 -0
- data/lib/ri_cal/property_value/integer.rb +12 -0
- data/lib/ri_cal/property_value/occurrence_list.rb +144 -0
- data/lib/ri_cal/property_value/period.rb +86 -0
- data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +100 -0
- data/lib/ri_cal/property_value/recurrence_rule/enumerator.rb +79 -0
- data/lib/ri_cal/property_value/recurrence_rule/initialization_methods.rb +148 -0
- data/lib/ri_cal/property_value/recurrence_rule/negative_setpos_enumerator.rb +53 -0
- data/lib/ri_cal/property_value/recurrence_rule/numbered_span.rb +31 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_day_incrementer.rb +86 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_hour_incrementer.rb +31 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_minute_incrementer.rb +32 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_month_incrementer.rb +52 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_monthday_incrementer.rb +31 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_numbered_day_incrementer.rb +38 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_second_incrementer.rb +32 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_weekno_incrementer.rb +69 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_yearday_incrementer.rb +31 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/daily_incrementer.rb +28 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/frequency_incrementer.rb +80 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/hourly_incrementer.rb +23 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/list_incrementer.rb +106 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/minutely_incrementer.rb +23 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/monthly_incrementer.rb +33 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/null_sub_cycle_incrementer.rb +43 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/secondly_incrementer.rb +28 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/weekly_incrementer.rb +37 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/yearly_incrementer.rb +57 -0
- data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer.rb +135 -0
- data/lib/ri_cal/property_value/recurrence_rule/recurring_day.rb +131 -0
- data/lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb +64 -0
- data/lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb +33 -0
- data/lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb +53 -0
- data/lib/ri_cal/property_value/recurrence_rule/time_manipulation.rb +42 -0
- data/lib/ri_cal/property_value/recurrence_rule/validations.rb +125 -0
- data/lib/ri_cal/property_value/recurrence_rule.rb +154 -0
- data/lib/ri_cal/property_value/text.rb +44 -0
- data/lib/ri_cal/property_value/uri.rb +11 -0
- data/lib/ri_cal/property_value/utc_offset.rb +33 -0
- data/lib/ri_cal/property_value/zulu_date_time.rb +34 -0
- data/lib/ri_cal/property_value.rb +159 -0
- data/lib/ri_cal/required_timezones.rb +55 -0
- data/lib/ri_cal.rb +187 -0
- data/parked_specs/ri_cal/claudio_a_bug_spec.rb +100 -0
- data/performance/empty_propval/subject.rb +43 -0
- data/performance/paris_eastern/subject.rb +90 -0
- data/performance/penultimate_weekday/subject.rb +15 -0
- data/performance/psm_big_enum/ical.ics +3171 -0
- data/performance/psm_big_enum/subject.rb +16 -0
- data/performance/utah_cycling/subject.rb +55 -0
- data/ri_cal.gemspec +244 -0
- data/script/benchmark_subject +23 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/profile_subject +29 -0
- data/script/txt2html +71 -0
- data/spec/ri_cal/bugreports_spec.rb +276 -0
- data/spec/ri_cal/component/alarm_spec.rb +12 -0
- data/spec/ri_cal/component/calendar_spec.rb +88 -0
- data/spec/ri_cal/component/event_spec.rb +735 -0
- data/spec/ri_cal/component/freebusy_spec.rb +12 -0
- data/spec/ri_cal/component/journal_spec.rb +37 -0
- data/spec/ri_cal/component/t_z_info_timezone_spec.rb +60 -0
- data/spec/ri_cal/component/timezone_spec.rb +236 -0
- data/spec/ri_cal/component/todo_spec.rb +112 -0
- data/spec/ri_cal/component_spec.rb +224 -0
- data/spec/ri_cal/core_extensions/string/conversions_spec.rb +78 -0
- data/spec/ri_cal/core_extensions/time/calculations_spec.rb +188 -0
- data/spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb +45 -0
- data/spec/ri_cal/fast_date_time_spec.rb +77 -0
- data/spec/ri_cal/inf_loop_spec.rb +78 -0
- data/spec/ri_cal/occurrence_enumerator_spec.rb +611 -0
- data/spec/ri_cal/parser_spec.rb +337 -0
- data/spec/ri_cal/property_value/date_spec.rb +53 -0
- data/spec/ri_cal/property_value/date_time_spec.rb +383 -0
- data/spec/ri_cal/property_value/duration_spec.rb +126 -0
- data/spec/ri_cal/property_value/occurrence_list_spec.rb +72 -0
- data/spec/ri_cal/property_value/period_spec.rb +63 -0
- data/spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb +21 -0
- data/spec/ri_cal/property_value/recurrence_rule_spec.rb +1814 -0
- data/spec/ri_cal/property_value/text_spec.rb +25 -0
- data/spec/ri_cal/property_value/utc_offset_spec.rb +48 -0
- data/spec/ri_cal/property_value_spec.rb +125 -0
- data/spec/ri_cal/required_timezones_spec.rb +67 -0
- data/spec/ri_cal_spec.rb +53 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +50 -0
- data/tasks/gem_loader/load_active_support.rb +3 -0
- data/tasks/gem_loader/load_tzinfo_gem.rb +2 -0
- data/tasks/ri_cal.rake +412 -0
- data/tasks/spec.rake +102 -0
- metadata +246 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
module RiCal
|
2
|
+
class PropertyValue
|
3
|
+
class RecurrenceRule < PropertyValue
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
5
|
+
#
|
6
|
+
class OccurrenceIncrementer # :nodoc:
|
7
|
+
class ByMonthIncrementer < ListIncrementer #:nodoc:
|
8
|
+
|
9
|
+
def self.for_rrule(rrule)
|
10
|
+
conditional_incrementer(rrule, :bymonth, MonthlyIncrementer)
|
11
|
+
end
|
12
|
+
|
13
|
+
def occurrences_for(date_time)
|
14
|
+
if contains_daily_incrementer?
|
15
|
+
list.map {|value| date_time.change(:month => value, :day => 1)}
|
16
|
+
else
|
17
|
+
list.map {|value| date_time.in_month(value)}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def range_advance(date_time)
|
22
|
+
advance_year(date_time)
|
23
|
+
end
|
24
|
+
|
25
|
+
def start_of_cycle(date_time)
|
26
|
+
if contains_daily_incrementer?
|
27
|
+
date_time.change(:month => 1, :day => 1)
|
28
|
+
else
|
29
|
+
date_time.change(:month => 1)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def varying_time_attribute
|
34
|
+
:month
|
35
|
+
end
|
36
|
+
|
37
|
+
def advance_cycle(date_time)
|
38
|
+
if contains_daily_incrementer?
|
39
|
+
first_day_of_year(advance_year(date_time))
|
40
|
+
else
|
41
|
+
advance_year(date_time).change(:month => 1)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def end_of_occurrence(date_time)
|
46
|
+
date_time.end_of_month
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_monthday_incrementer.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module RiCal
|
2
|
+
class PropertyValue
|
3
|
+
class RecurrenceRule < PropertyValue
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
5
|
+
#
|
6
|
+
class OccurrenceIncrementer # :nodoc:
|
7
|
+
class ByMonthdayIncrementer < ByNumberedDayIncrementer #:nodoc:
|
8
|
+
def self.for_rrule(rrule)
|
9
|
+
conditional_incrementer(rrule, :bymonthday, DailyIncrementer)
|
10
|
+
end
|
11
|
+
|
12
|
+
def scope_of(date_time)
|
13
|
+
date_time.month
|
14
|
+
end
|
15
|
+
|
16
|
+
def start_of_cycle(date_time)
|
17
|
+
date_time.change(:day => 1)
|
18
|
+
end
|
19
|
+
|
20
|
+
def advance_cycle(date_time)
|
21
|
+
first_day_of_month(advance_month(date_time))
|
22
|
+
end
|
23
|
+
|
24
|
+
def end_of_occurrence(date_time)
|
25
|
+
date_time.end_of_day
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_numbered_day_incrementer.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module RiCal
|
2
|
+
class PropertyValue
|
3
|
+
class RecurrenceRule < PropertyValue
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
5
|
+
#
|
6
|
+
class OccurrenceIncrementer # :nodoc:
|
7
|
+
class ByNumberedDayIncrementer < ListIncrementer #:nodoc:
|
8
|
+
|
9
|
+
def daily_incrementer?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def unneeded?(candidate)
|
14
|
+
list.length == 1 && list.first.fixed_day?
|
15
|
+
end
|
16
|
+
|
17
|
+
def occurrences_for(date_time)
|
18
|
+
if occurrences && @scoping_value == scope_of(date_time)
|
19
|
+
occurrences
|
20
|
+
else
|
21
|
+
@scoping_value = scope_of(date_time)
|
22
|
+
self.occurrences = list.map {|numbered_day| numbered_day.target_date_time_for(date_time)}.uniq.sort
|
23
|
+
occurrences
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def end_of_occurrence(date_time)
|
28
|
+
date_time.end_of_day
|
29
|
+
end
|
30
|
+
|
31
|
+
def candidate_acceptable?(candidate)
|
32
|
+
list.any? {|by_part| by_part.include?(candidate)}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_second_incrementer.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module RiCal
|
2
|
+
class PropertyValue
|
3
|
+
class RecurrenceRule < PropertyValue
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
5
|
+
#
|
6
|
+
class OccurrenceIncrementer # :nodoc:
|
7
|
+
class BySecondIncrementer < ListIncrementer #:nodoc:
|
8
|
+
|
9
|
+
def self.for_rrule(rrule)
|
10
|
+
conditional_incrementer(rrule, :bysecond, SecondlyIncrementer)
|
11
|
+
end
|
12
|
+
|
13
|
+
def varying_time_attribute
|
14
|
+
:sec
|
15
|
+
end
|
16
|
+
|
17
|
+
def start_of_cycle(date_time)
|
18
|
+
date_time.start_of_minute
|
19
|
+
end
|
20
|
+
|
21
|
+
def advance_cycle(date_time)
|
22
|
+
date_time.advance(:minutes => 1).start_of_minute
|
23
|
+
end
|
24
|
+
|
25
|
+
def end_of_occurrence(date_time)
|
26
|
+
date_time
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_weekno_incrementer.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
module RiCal
|
2
|
+
class PropertyValue
|
3
|
+
class RecurrenceRule < PropertyValue
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
5
|
+
#
|
6
|
+
class OccurrenceIncrementer # :nodoc:
|
7
|
+
class ByWeekNoIncrementer < ListIncrementer #:nodoc:
|
8
|
+
attr_reader :wkst
|
9
|
+
# include WeeklyBydayMethods
|
10
|
+
|
11
|
+
def initialize(rrule, list, sub_cycle_incrementer)
|
12
|
+
@wkst = rrule.wkst_day
|
13
|
+
super(rrule, list, sub_cycle_incrementer)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.for_rrule(rrule)
|
17
|
+
conditional_incrementer(rrule, :byweekno, WeeklyIncrementer)
|
18
|
+
end
|
19
|
+
|
20
|
+
def weeknum_incrementer?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
def unneeded?(candidate)
|
25
|
+
false
|
26
|
+
end
|
27
|
+
|
28
|
+
def first_within_outer_cycle(previous_occurrence, outer_range)
|
29
|
+
new_range_start = outer_range.first
|
30
|
+
new_range_end = new_range_start.end_of_iso_year(wkst)
|
31
|
+
super(previous_occurrence, outer_range.first..new_range_end)
|
32
|
+
end
|
33
|
+
|
34
|
+
def start_of_cycle(date_time)
|
35
|
+
result = date_time.at_start_of_iso_year(wkst)
|
36
|
+
result
|
37
|
+
end
|
38
|
+
|
39
|
+
def occurrences_for(date_time)
|
40
|
+
iso_year, year_start = *date_time.iso_year_and_week_one_start(wkst)
|
41
|
+
week_one_occurrence = date_time.change(
|
42
|
+
:year => year_start.year,
|
43
|
+
:month => year_start.month,
|
44
|
+
:day => year_start.day
|
45
|
+
)
|
46
|
+
weeks_in_year_plus_one = week_one_occurrence.iso_weeks_in_year(wkst)
|
47
|
+
weeks = list.map {|recurring_weeknum|
|
48
|
+
wk_num = recurring_weeknum.ordinal
|
49
|
+
(wk_num > 0) ? wk_num : weeks_in_year_plus_one + wk_num
|
50
|
+
}.uniq.sort
|
51
|
+
weeks.map {|wk_num| week_one_occurrence.advance(:days => (wk_num - 1) * 7)}
|
52
|
+
end
|
53
|
+
|
54
|
+
def candidate_acceptable?(candidate)
|
55
|
+
list.include?(candidate.iso_week_num(wkst))
|
56
|
+
end
|
57
|
+
|
58
|
+
def advance_cycle(date_time)
|
59
|
+
date_time.at_start_of_next_iso_year(wkst)
|
60
|
+
end
|
61
|
+
|
62
|
+
def end_of_occurrence(date_time)
|
63
|
+
date_time.end_of_week_with_wkst(wkst)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/by_yearday_incrementer.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module RiCal
|
2
|
+
class PropertyValue
|
3
|
+
class RecurrenceRule < PropertyValue
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
5
|
+
#
|
6
|
+
class OccurrenceIncrementer # :nodoc:
|
7
|
+
class ByYeardayIncrementer < ByNumberedDayIncrementer #:nodoc:
|
8
|
+
def self.for_rrule(rrule)
|
9
|
+
conditional_incrementer(rrule, :byyearday, ByMonthdayIncrementer)
|
10
|
+
end
|
11
|
+
|
12
|
+
def start_of_cycle(date_time)
|
13
|
+
date_time.change(:month => 1, :day => 1)
|
14
|
+
end
|
15
|
+
|
16
|
+
def scope_of(date_time)
|
17
|
+
date_time.year
|
18
|
+
end
|
19
|
+
|
20
|
+
def advance_cycle(date_time)
|
21
|
+
first_day_of_year(advance_year(date_time))
|
22
|
+
end
|
23
|
+
|
24
|
+
def end_of_occurrence(date_time)
|
25
|
+
date_time.end_of_day
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module RiCal
|
2
|
+
class PropertyValue
|
3
|
+
class RecurrenceRule < PropertyValue
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
5
|
+
#
|
6
|
+
class OccurrenceIncrementer # :nodoc:
|
7
|
+
class DailyIncrementer < FrequencyIncrementer #:nodoc:
|
8
|
+
|
9
|
+
def self.for_rrule(rrule)
|
10
|
+
conditional_incrementer(rrule, "DAILY", OccurrenceIncrementer::ByHourIncrementer)
|
11
|
+
end
|
12
|
+
|
13
|
+
def daily_incrementer?
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
def advance_what
|
18
|
+
:days
|
19
|
+
end
|
20
|
+
|
21
|
+
def end_of_occurrence(date_time)
|
22
|
+
date_time.end_of_day
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/frequency_incrementer.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
module RiCal
|
2
|
+
class PropertyValue
|
3
|
+
class RecurrenceRule < PropertyValue
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
5
|
+
#
|
6
|
+
class OccurrenceIncrementer # :nodoc:
|
7
|
+
|
8
|
+
# A FrequenceIncrementer represents the xxxLY and FREQ parts of a recurrence rule
|
9
|
+
# A FrequenceIncrementer has a single occurrence within each cycle.
|
10
|
+
class FrequencyIncrementer < OccurrenceIncrementer #:nodoc:
|
11
|
+
attr_accessor :interval, :outer_occurrence, :skip_increment
|
12
|
+
|
13
|
+
alias_method :cycle_start, :current_occurrence
|
14
|
+
|
15
|
+
def initialize(rrule, sub_cycle_incrementer)
|
16
|
+
super(rrule, sub_cycle_incrementer)
|
17
|
+
self.interval = rrule.interval
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.conditional_incrementer(rrule, freq_str, sub_cycle_class)
|
21
|
+
sub_cycle_incrementer = sub_cycle_class.for_rrule(rrule)
|
22
|
+
if rrule.freq == freq_str
|
23
|
+
new(rrule, sub_cycle_incrementer)
|
24
|
+
else
|
25
|
+
sub_cycle_incrementer
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def multiplier
|
30
|
+
1
|
31
|
+
end
|
32
|
+
|
33
|
+
def step(occurrence)
|
34
|
+
occurrence.advance(advance_what => (interval * multiplier))
|
35
|
+
end
|
36
|
+
|
37
|
+
def sub_cycle_incrementer
|
38
|
+
if @sub_cycle_incrementer.unneeded?(current_occurrence || @previous_occurrence)
|
39
|
+
NullSubCycleIncrementer
|
40
|
+
else
|
41
|
+
super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def first_within_outer_cycle(previous_occurrence, outer_cycle_range)
|
46
|
+
if outer_range
|
47
|
+
first_occurrence = outer_cycle_range.first
|
48
|
+
else
|
49
|
+
first_occurrence = step(previous_occurrence)
|
50
|
+
end
|
51
|
+
self.outer_range = outer_cycle_range
|
52
|
+
sub_cycle_incrementer.first_within_outer_cycle(previous_occurrence, update_cycle_range(first_occurrence))
|
53
|
+
end
|
54
|
+
|
55
|
+
# Advance to the next occurrence, if the result is within the current cycles of all outer incrementers
|
56
|
+
def next_cycle(previous_occurrence)
|
57
|
+
@sub_cycle_dtstart = previous_occurrence
|
58
|
+
if current_occurrence
|
59
|
+
candidate = sub_cycle_incrementer.cycle_adjust(step(current_occurrence))
|
60
|
+
else
|
61
|
+
candidate = step(previous_occurrence)
|
62
|
+
end
|
63
|
+
if outermost?
|
64
|
+
sub_occurrence = sub_cycle_incrementer.first_within_outer_cycle(previous_occurrence, update_cycle_range(candidate))
|
65
|
+
until sub_occurrence
|
66
|
+
candidate = sub_cycle_incrementer.cycle_adjust(step(candidate))
|
67
|
+
sub_occurrence = sub_cycle_incrementer.first_within_outer_cycle(previous_occurrence, update_cycle_range(candidate))
|
68
|
+
end
|
69
|
+
sub_occurrence
|
70
|
+
elsif in_outer_cycle?(candidate)
|
71
|
+
sub_cycle_incrementer.first_within_outer_cycle(previous_occurrence, update_cycle_range(candidate))
|
72
|
+
else
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RiCal
|
2
|
+
class PropertyValue
|
3
|
+
class RecurrenceRule < PropertyValue
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
5
|
+
#
|
6
|
+
class OccurrenceIncrementer # :nodoc:
|
7
|
+
class HourlyIncrementer < FrequencyIncrementer #:nodoc:
|
8
|
+
def self.for_rrule(rrule)
|
9
|
+
conditional_incrementer(rrule, "HOURLY", ByMinuteIncrementer)
|
10
|
+
end
|
11
|
+
|
12
|
+
def advance_what
|
13
|
+
:hours
|
14
|
+
end
|
15
|
+
|
16
|
+
def end_of_occurrence(date_time)
|
17
|
+
date_time.end_of_hour
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module RiCal
|
2
|
+
class PropertyValue
|
3
|
+
class RecurrenceRule < PropertyValue
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
5
|
+
#
|
6
|
+
class OccurrenceIncrementer # :nodoc:
|
7
|
+
|
8
|
+
# A ListIncrementer represents a byxxx part of a recurrence rule
|
9
|
+
# It contains a list of simple values or recurring values
|
10
|
+
# It keeps a collection of occurrences within a given range called a cycle
|
11
|
+
# When the collection of occurrences is exhausted it is refreshed if there is no
|
12
|
+
# outer incrementer, or if a new cycle would start in the current cycle of the outer incrementers.
|
13
|
+
class ListIncrementer < OccurrenceIncrementer #:nodoc:
|
14
|
+
attr_accessor :occurrences, :list, :outer_occurrence, :cycle_start
|
15
|
+
|
16
|
+
def initialize(rrule, list, sub_cycle_incrementer)
|
17
|
+
super(rrule, sub_cycle_incrementer)
|
18
|
+
self.list = list
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.conditional_incrementer(rrule, by_part, sub_cycle_class)
|
22
|
+
sub_cycle_incrementer = sub_cycle_class.for_rrule(rrule)
|
23
|
+
list = rrule.by_rule_list(by_part)
|
24
|
+
if list
|
25
|
+
new(rrule, list, sub_cycle_incrementer)
|
26
|
+
else
|
27
|
+
sub_cycle_incrementer
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Advance to the next occurrence, if the result is within the current cycles of all outer incrementers
|
32
|
+
def next_cycle(previous_occurrence)
|
33
|
+
unless occurrences
|
34
|
+
self.occurrences = occurrences_for(previous_occurrence)
|
35
|
+
end
|
36
|
+
candidate = next_candidate(previous_occurrence)
|
37
|
+
if candidate
|
38
|
+
sub_cycle_incrementer.first_within_outer_cycle(previous_occurrence, update_cycle_range(candidate))
|
39
|
+
else
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def unneeded?(candidate)
|
45
|
+
sub_cycle_incrementer.unneeded?(candidate) &&
|
46
|
+
list.length == 1 &&
|
47
|
+
candidate_acceptable?(candidate)
|
48
|
+
end
|
49
|
+
|
50
|
+
def candidate_acceptable?(candidate)
|
51
|
+
list.any? {|value| candidate.send(varying_time_attribute) == value}
|
52
|
+
end
|
53
|
+
|
54
|
+
def first_within_outer_cycle(previous_occurrence, outer_range)
|
55
|
+
self.outer_range = outer_range
|
56
|
+
self.occurrences = occurrences_within(outer_range)
|
57
|
+
occurrences.each { |occurrence|
|
58
|
+
sub = sub_cycle_incrementer.first_within_outer_cycle(previous_occurrence, update_cycle_range(occurrence))
|
59
|
+
return sub if sub && sub > previous_occurrence
|
60
|
+
}
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
|
64
|
+
def next_candidate(date_time)
|
65
|
+
candidate = next_in_list(date_time)
|
66
|
+
if outermost?
|
67
|
+
while candidate.nil?
|
68
|
+
get_next_occurrences
|
69
|
+
candidate = next_in_list(date_time)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
candidate
|
73
|
+
end
|
74
|
+
|
75
|
+
def next_in_list(date_time)
|
76
|
+
occurrences.find {|occurrence| occurrence > date_time}
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_next_occurrences
|
80
|
+
adv_cycle = advance_cycle(start_of_cycle(occurrences.first))
|
81
|
+
self.occurrences = occurrences_for(adv_cycle)
|
82
|
+
end
|
83
|
+
|
84
|
+
def cycle_adjust(date_time)
|
85
|
+
sub_cycle_incrementer.cycle_adjust(start_of_cycle(date_time))
|
86
|
+
end
|
87
|
+
|
88
|
+
def occurrences_for(date_time)
|
89
|
+
list.map {|value| date_time.change(varying_time_attribute => value)}
|
90
|
+
end
|
91
|
+
|
92
|
+
def occurrences_within(date_time_range)
|
93
|
+
result = []
|
94
|
+
date_time = date_time_range.first
|
95
|
+
while date_time <= date_time_range.last
|
96
|
+
result << occurrences_for(date_time)
|
97
|
+
date_time = advance_cycle(date_time)
|
98
|
+
end
|
99
|
+
result.flatten
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RiCal
|
2
|
+
class PropertyValue
|
3
|
+
class RecurrenceRule < PropertyValue
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
5
|
+
#
|
6
|
+
class OccurrenceIncrementer # :nodoc:
|
7
|
+
class MinutelyIncrementer < FrequencyIncrementer #:nodoc:
|
8
|
+
def self.for_rrule(rrule)
|
9
|
+
conditional_incrementer(rrule, "MINUTELY", BySecondIncrementer)
|
10
|
+
end
|
11
|
+
|
12
|
+
def advance_what
|
13
|
+
:minutes
|
14
|
+
end
|
15
|
+
|
16
|
+
def end_of_occurrence(date_time)
|
17
|
+
date_time.end_of_minute
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module RiCal
|
2
|
+
class PropertyValue
|
3
|
+
class RecurrenceRule < PropertyValue
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
5
|
+
#
|
6
|
+
class OccurrenceIncrementer # :nodoc:
|
7
|
+
class MonthlyIncrementer < FrequencyIncrementer #:nodoc:
|
8
|
+
|
9
|
+
def self.for_rrule(rrule)
|
10
|
+
conditional_incrementer(rrule, "MONTHLY", ByWeekNoIncrementer)
|
11
|
+
end
|
12
|
+
|
13
|
+
def advance_what
|
14
|
+
:months
|
15
|
+
end
|
16
|
+
|
17
|
+
def step(date_time)
|
18
|
+
if contains_daily_incrementer?
|
19
|
+
result = super(date_time).change(:day => 1)
|
20
|
+
result
|
21
|
+
else
|
22
|
+
super(date_time)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def end_of_occurrence(date_time)
|
27
|
+
date_time.end_of_month
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/ri_cal/property_value/recurrence_rule/occurrence_incrementer/null_sub_cycle_incrementer.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module RiCal
|
2
|
+
class PropertyValue
|
3
|
+
class RecurrenceRule < PropertyValue
|
4
|
+
class OccurrenceIncrementer # :nodoc:
|
5
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
6
|
+
#
|
7
|
+
class NullSubCycleIncrementer #:nodoc:
|
8
|
+
def self.next_time(previous)
|
9
|
+
nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.add_outer_incrementer(incrementer)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.unneeded?(candidate)
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.first_within_outer_cycle(previous_occurrence, outer_cycle_range)
|
20
|
+
outer_cycle_range.first
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.first_sub_occurrence(previous_occurrence, outer_cycle_range)
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.cycle_adjust(date_time)
|
28
|
+
date_time
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.to_s
|
32
|
+
"NULL-INCR"
|
33
|
+
end
|
34
|
+
|
35
|
+
def inspect
|
36
|
+
to_s
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module RiCal
|
2
|
+
class PropertyValue
|
3
|
+
class RecurrenceRule < PropertyValue
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
5
|
+
#
|
6
|
+
class OccurrenceIncrementer # :nodoc:
|
7
|
+
class SecondlyIncrementer < FrequencyIncrementer #:nodoc:
|
8
|
+
|
9
|
+
def self.for_rrule(rrule)
|
10
|
+
if rrule.freq == "SECONDLY"
|
11
|
+
new(rrule, nil)
|
12
|
+
else
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def advance_what
|
18
|
+
:seconds
|
19
|
+
end
|
20
|
+
|
21
|
+
def end_of_occurrence(date_time)
|
22
|
+
date_time
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module RiCal
|
2
|
+
class PropertyValue
|
3
|
+
class RecurrenceRule < PropertyValue
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
5
|
+
#
|
6
|
+
class OccurrenceIncrementer # :nodoc:
|
7
|
+
class WeeklyIncrementer < FrequencyIncrementer #:nodoc:
|
8
|
+
|
9
|
+
attr_reader :wkst
|
10
|
+
|
11
|
+
# include WeeklyBydayMethods
|
12
|
+
|
13
|
+
def initialize(rrule, parent)
|
14
|
+
@wkst = rrule.wkst_day
|
15
|
+
super(rrule, parent)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.for_rrule(rrule)
|
19
|
+
conditional_incrementer(rrule, "WEEKLY", ByDayIncrementer)
|
20
|
+
end
|
21
|
+
|
22
|
+
def multiplier
|
23
|
+
7
|
24
|
+
end
|
25
|
+
|
26
|
+
def advance_what
|
27
|
+
:days
|
28
|
+
end
|
29
|
+
|
30
|
+
def end_of_occurrence(date_time)
|
31
|
+
date_time.end_of_week_with_wkst(wkst)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|