ri_cal 0.5.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.
- data/History.txt +45 -0
- data/Manifest.txt +129 -0
- data/README.txt +394 -0
- data/Rakefile +31 -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.rb +144 -0
- data/lib/ri_cal/component.rb +247 -0
- data/lib/ri_cal/component/alarm.rb +21 -0
- data/lib/ri_cal/component/calendar.rb +219 -0
- data/lib/ri_cal/component/event.rb +60 -0
- data/lib/ri_cal/component/freebusy.rb +18 -0
- data/lib/ri_cal/component/journal.rb +30 -0
- data/lib/ri_cal/component/t_z_info_timezone.rb +123 -0
- data/lib/ri_cal/component/timezone.rb +196 -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 +53 -0
- data/lib/ri_cal/component/todo.rb +43 -0
- data/lib/ri_cal/core_extensions.rb +6 -0
- data/lib/ri_cal/core_extensions/array.rb +7 -0
- data/lib/ri_cal/core_extensions/array/conversions.rb +15 -0
- data/lib/ri_cal/core_extensions/date.rb +13 -0
- data/lib/ri_cal/core_extensions/date/conversions.rb +61 -0
- data/lib/ri_cal/core_extensions/date_time.rb +15 -0
- data/lib/ri_cal/core_extensions/date_time/conversions.rb +50 -0
- data/lib/ri_cal/core_extensions/object.rb +8 -0
- data/lib/ri_cal/core_extensions/object/conversions.rb +20 -0
- data/lib/ri_cal/core_extensions/string.rb +8 -0
- data/lib/ri_cal/core_extensions/string/conversions.rb +63 -0
- data/lib/ri_cal/core_extensions/time.rb +13 -0
- data/lib/ri_cal/core_extensions/time/calculations.rb +153 -0
- data/lib/ri_cal/core_extensions/time/conversions.rb +61 -0
- data/lib/ri_cal/core_extensions/time/tzid_access.rb +50 -0
- data/lib/ri_cal/core_extensions/time/week_day_predicates.rb +88 -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_identifer.rb +20 -0
- data/lib/ri_cal/occurrence_enumerator.rb +206 -0
- data/lib/ri_cal/occurrence_period.rb +17 -0
- data/lib/ri_cal/parser.rb +138 -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 +1526 -0
- data/lib/ri_cal/properties/freebusy.rb +594 -0
- data/lib/ri_cal/properties/journal.rb +1240 -0
- data/lib/ri_cal/properties/timezone.rb +151 -0
- data/lib/ri_cal/properties/timezone_period.rb +416 -0
- data/lib/ri_cal/properties/todo.rb +1562 -0
- data/lib/ri_cal/property_value.rb +149 -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 +175 -0
- data/lib/ri_cal/property_value/date_time.rb +335 -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 +181 -0
- data/lib/ri_cal/property_value/date_time/timezone_support.rb +96 -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 +82 -0
- data/lib/ri_cal/property_value/recurrence_rule.rb +145 -0
- data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +97 -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/occurence_incrementer.rb +793 -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 +60 -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 +49 -0
- data/lib/ri_cal/property_value/recurrence_rule/validations.rb +125 -0
- data/lib/ri_cal/property_value/text.rb +40 -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/required_timezones.rb +55 -0
- data/ri_cal.gemspec +49 -0
- data/sample_ical_files/from_ical_dot_app/test1.ics +38 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +71 -0
- data/spec/ri_cal/component/alarm_spec.rb +12 -0
- data/spec/ri_cal/component/calendar_spec.rb +54 -0
- data/spec/ri_cal/component/event_spec.rb +601 -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 +36 -0
- data/spec/ri_cal/component/timezone_spec.rb +218 -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/occurrence_enumerator_spec.rb +573 -0
- data/spec/ri_cal/parser_spec.rb +303 -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 +49 -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 +46 -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 +410 -0
- data/tasks/spec.rake +50 -0
- metadata +221 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module RiCal
|
|
2
|
+
class PropertyValue
|
|
3
|
+
class DateTime
|
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
|
5
|
+
#
|
|
6
|
+
# Methods for DateTime which support adding or subtracting another DateTime or Duration
|
|
7
|
+
module AdditiveMethods
|
|
8
|
+
# if end_time is nil => nil
|
|
9
|
+
# otherwise convert end_time to a DateTime and compute the difference
|
|
10
|
+
def duration_until(end_time) # :nodoc:
|
|
11
|
+
end_time && RiCal::PropertyValue::Duration.from_datetimes(timezone_finder, to_datetime, end_time.to_datetime)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Double-dispatch method for subtraction.
|
|
15
|
+
def subtract_from_date_time_value(dtvalue) #:nodoc:
|
|
16
|
+
RiCal::PropertyValue::Duration.from_datetimes(timezone_finder, to_datetime,dtvalue.to_datetime)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Double-dispatch method for addition.
|
|
20
|
+
def add_to_date_time_value(date_time_value) #:nodoc:
|
|
21
|
+
raise ArgumentError.new("Cannot add #{date_time_value} to #{self}")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Return the difference between the receiver and other
|
|
25
|
+
#
|
|
26
|
+
# The parameter other should be either a RiCal::PropertyValue::Duration or a RiCal::PropertyValue::DateTime
|
|
27
|
+
#
|
|
28
|
+
# If other is a Duration, the result will be a DateTime, if it is a DateTime the result will be a Duration
|
|
29
|
+
def -(other)
|
|
30
|
+
other.subtract_from_date_time_value(self)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Return the sum of the receiver and duration
|
|
34
|
+
#
|
|
35
|
+
# The parameter other duration should be a RiCal::PropertyValue::Duration
|
|
36
|
+
#
|
|
37
|
+
# The result will be an RiCal::PropertyValue::DateTime
|
|
38
|
+
def +(duration)
|
|
39
|
+
duration.add_to_date_time_value(self)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
module RiCal
|
|
2
|
+
class PropertyValue
|
|
3
|
+
class DateTime
|
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
|
5
|
+
#
|
|
6
|
+
# Methods for DateTime which support getting values at different point in time.
|
|
7
|
+
module TimeMachine
|
|
8
|
+
def compute_change(d, options) # :nodoc:
|
|
9
|
+
::DateTime.civil(
|
|
10
|
+
options[:year] || d.year,
|
|
11
|
+
options[:month] || d.month,
|
|
12
|
+
options[:day] || d.day,
|
|
13
|
+
options[:hour] || d.hour,
|
|
14
|
+
options[:min] || (options[:hour] ? 0 : d.min),
|
|
15
|
+
options[:sec] || ((options[:hour] || options[:min]) ? 0 : d.sec),
|
|
16
|
+
options[:offset] || d.offset,
|
|
17
|
+
options[:start] || d.start
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def compute_advance(d, options) # :nodoc:
|
|
22
|
+
d = d >> options[:years] * 12 if options[:years]
|
|
23
|
+
d = d >> options[:months] if options[:months]
|
|
24
|
+
d = d + options[:weeks] * 7 if options[:weeks]
|
|
25
|
+
d = d + options[:days] if options[:days]
|
|
26
|
+
datetime_advanced_by_date = compute_change(@date_time_value, :year => d.year, :month => d.month, :day => d.day)
|
|
27
|
+
seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
|
|
28
|
+
seconds_to_advance == 0 ? datetime_advanced_by_date : datetime_advanced_by_date + Rational(seconds_to_advance.round, 86400)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def advance(options) # :nodoc:
|
|
32
|
+
PropertyValue::DateTime.new(timezone_finder,
|
|
33
|
+
:value => compute_advance(@date_time_value, options),
|
|
34
|
+
:tzid => @tzid,
|
|
35
|
+
:params =>(params ? params.dup : nil)
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def change(options) # :nodoc:
|
|
40
|
+
PropertyValue::DateTime.new(timezone_finder,
|
|
41
|
+
:value => compute_change(@date_time_value, options),
|
|
42
|
+
:tzid => @tzid,
|
|
43
|
+
:params => (params ? params.dup : nil)
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def change_sec(new_sec) #:nodoc:
|
|
48
|
+
PropertyValue::DateTime.civil(self.year, self.month, self.day, self.hour, self.min, sec, self.offset, self.start, params)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def change_min(new_min) #:nodoc:
|
|
52
|
+
PropertyValue::DateTime.civil(self.year, self.month, self.day, self.hour, new_min, self.sec, self.offset, self.start, params)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def change_hour(new_hour) #:nodoc:
|
|
56
|
+
PropertyValue::DateTime.civil(self.year, self.month, self.day, new_hour, self.min, self.sec, self.offset, self.start, params)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def change_day(new_day) #:nodoc:
|
|
60
|
+
PropertyValue::DateTime.civil(self.year, self.month, new_day, self.hour, self.min, self.sec, self.offset, self.start, params)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def change_month(new_month) #:nodoc:
|
|
64
|
+
PropertyValue::DateTime.civil(self.year, new_month, self.day, self.hour, self.min, self.sec, self.offset, self.start, params)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def change_year(new_year) #:nodoc:
|
|
68
|
+
PropertyValue::DateTime.civil(new_year, self.month, self.day, self.hour, self.min, self.sec, self.offset, self.start, params)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Return a DATE-TIME property representing the receiver on a different day (if necessary) so that
|
|
72
|
+
# the result is within the 7 days starting with date
|
|
73
|
+
def in_week_starting?(date)
|
|
74
|
+
wkst_jd = date.jd
|
|
75
|
+
@date_time_value.jd.between?(wkst_jd, wkst_jd + 6)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Return a DATE-TIME property representing the receiver on a different day (if necessary) so that
|
|
79
|
+
# the result is the first day of the ISO week starting on the wkst day containing the receiver.
|
|
80
|
+
def at_start_of_week_with_wkst(wkst)
|
|
81
|
+
date = @date_time_value.start_of_week_with_wkst(wkst)
|
|
82
|
+
change(:year => date.year, :month => date.month, :day => date.day)
|
|
83
|
+
end
|
|
84
|
+
# Return a DATE_TIME value representing the first second of the minute containing the receiver
|
|
85
|
+
def start_of_minute
|
|
86
|
+
change(:sec => 0)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Return a DATE_TIME value representing the last second of the minute containing the receiver
|
|
90
|
+
def end_of_minute
|
|
91
|
+
change(:sec => 59)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Return a DATE_TIME value representing the first second of the hour containing the receiver
|
|
95
|
+
def start_of_hour
|
|
96
|
+
change(:min => 0, :sec => 0)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Return a DATE_TIME value representing the last second of the hour containing the receiver
|
|
100
|
+
def end_of_hour
|
|
101
|
+
change(:min => 59, :sec => 59)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Return a DATE_TIME value representing the first second of the day containing the receiver
|
|
105
|
+
def start_of_day
|
|
106
|
+
change(:hour => 0, :min => 0, :sec => 0)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Return a DATE_TIME value representing the last second of the day containing the receiver
|
|
110
|
+
def end_of_day
|
|
111
|
+
change(:hour => 23, :min => 59, :sec => 59)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Return a Ruby Date representing the first day of the ISO week starting with wkst containing the receiver
|
|
115
|
+
def start_of_week_with_wkst(wkst)
|
|
116
|
+
@date_time_value.start_of_week_with_wkst(wkst)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Return a DATE_TIME value representing the last second of the ISO week starting with wkst containing the receiver
|
|
120
|
+
def end_of_week_with_wkst(wkst)
|
|
121
|
+
date = at_start_of_week_with_wkst(wkst).advance(:days => 6).end_of_day
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Return a DATE_TIME value representing the first second of the month containing the receiver
|
|
125
|
+
def start_of_month
|
|
126
|
+
change(:day => 1, :hour => 0, :min => 0, :sec => 0)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Return a DATE_TIME value representing the last second of the month containing the receiver
|
|
130
|
+
def end_of_month
|
|
131
|
+
change(:day => days_in_month, :hour => 23, :min => 59, :sec => 59)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Return a DATE_TIME value representing the first second of the month containing the receiver
|
|
135
|
+
def start_of_year
|
|
136
|
+
change(:month => 1, :day => 1, :hour => 0, :min => 0, :sec => 0)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Return a DATE_TIME value representing the last second of the month containing the receiver
|
|
140
|
+
def end_of_year
|
|
141
|
+
change(:month => 12, :day => 31, :hour => 23, :min => 59, :sec => 59)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Return a DATE_TIME value representing the same time on the first day of the ISO year with weeks
|
|
145
|
+
# starting on wkst containing the receiver
|
|
146
|
+
def at_start_of_iso_year(wkst)
|
|
147
|
+
start_of_year = @date_time_value.iso_year_start(wkst)
|
|
148
|
+
change(:year => start_of_year.year, :month => start_of_year.month, :day => start_of_year.day)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Return a DATE_TIME value representing the same time on the last day of the ISO year with weeks
|
|
152
|
+
# starting on wkst containing the receiver
|
|
153
|
+
def at_end_of_iso_year(wkst)
|
|
154
|
+
num_weeks = @date_time_value.iso_weeks_in_year(wkst)
|
|
155
|
+
at_start_of_iso_year(wkst).advance(:weeks => (num_weeks - 1), :days => 6)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Return a DATE_TIME value representing the same time on the first day of the ISO year with weeks
|
|
159
|
+
# starting on wkst after the ISO year containing the receiver
|
|
160
|
+
def at_start_of_next_iso_year(wkst)
|
|
161
|
+
num_weeks = @date_time_value.iso_weeks_in_year(wkst)
|
|
162
|
+
at_start_of_iso_year(wkst).advance(:weeks => num_weeks)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Return a DATE_TIME value representing the last second of the last day of the ISO year with weeks
|
|
166
|
+
# starting on wkst containing the receiver
|
|
167
|
+
def end_of_iso_year(wkst)
|
|
168
|
+
at_end_of_iso_year(wkst).end_of_day
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Return a DATE-TIME representing the same time, on the same day of the month in month.
|
|
172
|
+
# If the month of the receiver has more days than the target month the last day of the target month
|
|
173
|
+
# will be used.
|
|
174
|
+
def in_month(month)
|
|
175
|
+
first = change(:day => 1, :month => month)
|
|
176
|
+
first.change(:day => [first.days_in_month, day].min)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module RiCal
|
|
2
|
+
class PropertyValue
|
|
3
|
+
class DateTime
|
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
|
5
|
+
#
|
|
6
|
+
# Time zone related methods for DateTime
|
|
7
|
+
module TimezoneSupport
|
|
8
|
+
# Return the timezone id of the receiver, or nil if it is a floating time
|
|
9
|
+
def tzid
|
|
10
|
+
@tzid == :floating ? nil : @tzid
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def tzid=(timezone_id) #:nodoc:
|
|
14
|
+
timezone_id = default_tzid if timezone_id == :default
|
|
15
|
+
@tzid = timezone_id
|
|
16
|
+
@timezone = nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def find_timezone #:nodoc:
|
|
20
|
+
if @tzid == :floating
|
|
21
|
+
FloatingTimezone
|
|
22
|
+
else
|
|
23
|
+
timezone_finder.find_timezone(@tzid)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def timezone #:nodoc:
|
|
28
|
+
@timezone ||= find_timezone
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Determine if the receiver has a local time zone, i.e. it is not a floating time or a UTC time
|
|
32
|
+
def has_local_timezone?
|
|
33
|
+
tzid && tzid.upcase != "UTC"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Return the receiver if it has a floating time zone already,
|
|
37
|
+
# otherwise return a DATETIME property with the same time as the receiver but with a floating time zone
|
|
38
|
+
def with_floating_timezone
|
|
39
|
+
if @tzid == nil
|
|
40
|
+
self
|
|
41
|
+
else
|
|
42
|
+
@date_time_value.with_floating_timezone.to_ri_cal_date_time_value
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Returns a instance that represents the time in UTC.
|
|
47
|
+
def utc
|
|
48
|
+
if has_local_timezone?
|
|
49
|
+
timezone.local_to_utc(self)
|
|
50
|
+
else # Already local or a floating time
|
|
51
|
+
self
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def rational_tz_offset #:nodoc:
|
|
56
|
+
if has_local_timezone?
|
|
57
|
+
timezone.rational_utc_offset(@date_time_value)
|
|
58
|
+
else
|
|
59
|
+
Rational(0,24)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Predicate indicating whether or not the instance represents a ZULU time
|
|
64
|
+
def utc?
|
|
65
|
+
tzid == "UTC"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Predicate indicating whether or not the instance represents a floating time
|
|
69
|
+
def floating?
|
|
70
|
+
tzid.nil?
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def has_valid_tzinfo_tzid? #:nodoc:
|
|
74
|
+
if tzid && tzid != :floating
|
|
75
|
+
TZInfo::Timezone.get(tzid) rescue false
|
|
76
|
+
else
|
|
77
|
+
false
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Returns the simultaneous time in the specified zone.
|
|
82
|
+
def in_time_zone(new_zone)
|
|
83
|
+
new_zone = timezone_finder.find_timezone(new_zone)
|
|
84
|
+
return self if tzid == new_zone.identifier
|
|
85
|
+
if has_local_timezone?
|
|
86
|
+
new_zone.utc_to_local(utc)
|
|
87
|
+
elsif utc?
|
|
88
|
+
new_zone.utc_to_local(self)
|
|
89
|
+
else # Floating time
|
|
90
|
+
DateTime.new(timezone_finder, :value => @date_time_value, :tzid => new_zone.identifier)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
module RiCal
|
|
2
|
+
class PropertyValue
|
|
3
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
|
4
|
+
#
|
|
5
|
+
# RiCal::PropertyValue::CalAddress represents an icalendar Duration property value
|
|
6
|
+
# which is defined in
|
|
7
|
+
# rfc 2445 section 4.3.6 p 37
|
|
8
|
+
class Duration < PropertyValue
|
|
9
|
+
|
|
10
|
+
def self.value_part(unit, diff) # :nodoc:
|
|
11
|
+
(diff == 0) ? nil : "#{diff}#{unit}"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.from_datetimes(parent, start, finish, sign='+') # :nodoc:
|
|
15
|
+
if start > finish
|
|
16
|
+
from_datetimes(self, finish, start, '-')
|
|
17
|
+
else
|
|
18
|
+
diff = finish - start
|
|
19
|
+
days_diff = diff.to_i
|
|
20
|
+
hours = (diff - days_diff) * 24
|
|
21
|
+
hour_diff = hours.to_i
|
|
22
|
+
minutes = (hours - hour_diff) * 60
|
|
23
|
+
min_diff = minutes.to_i
|
|
24
|
+
seconds = (minutes - min_diff) * 60
|
|
25
|
+
sec_diff = seconds.to_i
|
|
26
|
+
|
|
27
|
+
day_part = value_part('D',days_diff)
|
|
28
|
+
hour_part = value_part('H', hour_diff)
|
|
29
|
+
min_part = value_part('M', min_diff)
|
|
30
|
+
sec_part = value_part('S', sec_diff)
|
|
31
|
+
t_part = (hour_diff.abs + min_diff.abs + sec_diff.abs) == 0 ? "" : "T"
|
|
32
|
+
new(parent, :value => "#{sign}P#{day_part}#{t_part}#{hour_part}#{min_part}#{sec_part}")
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.convert(parent, ruby_object) # :nodoc:
|
|
37
|
+
ruby_object.to_ri_cal_duration_value.for_parent(parent)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def value=(string) # :nodoc:
|
|
41
|
+
super
|
|
42
|
+
match = /([+-])?P(.*)$/.match(string)
|
|
43
|
+
@days = @hours = @minutes = @seconds = @weeks = 0
|
|
44
|
+
if match
|
|
45
|
+
@sign = match[1] == '-' ? -1 : 1
|
|
46
|
+
match[2].scan(/(\d+)([DHMSW])/) do |digits, unit|
|
|
47
|
+
number = digits.to_i
|
|
48
|
+
case unit
|
|
49
|
+
when 'D'
|
|
50
|
+
@days = number
|
|
51
|
+
when 'H'
|
|
52
|
+
@hours = number
|
|
53
|
+
when 'M'
|
|
54
|
+
@minutes = number
|
|
55
|
+
when 'S'
|
|
56
|
+
@seconds = number
|
|
57
|
+
when 'W'
|
|
58
|
+
@weeks = number
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def self.valid_string?(string) #:nodoc:
|
|
65
|
+
string =~ /^[+-]?P((\d+)[DHMSW])+$/
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def days # :nodoc:
|
|
69
|
+
@days * @sign
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def weeks # :nodoc:
|
|
73
|
+
@weeks * @sign
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def hours # :nodoc:
|
|
77
|
+
@hours * @sign
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def minutes # :nodoc:
|
|
81
|
+
@minutes * @sign
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def seconds # :nodoc:
|
|
85
|
+
@seconds * @sign
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Determine whether another object is an equivalent RiCal::PropertyValue::Duration
|
|
89
|
+
def ==(other)
|
|
90
|
+
other.kind_of?(PropertyValue::Duration) && value == other.value
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Returns the receiver
|
|
94
|
+
def to_ri_cal_duration_value
|
|
95
|
+
self
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Double-dispatch method to support RiCal::PropertyValue::DateTime.-
|
|
99
|
+
def subtract_from_date_time_value(date_time_value)
|
|
100
|
+
date_time_value.advance(:weeks => -weeks, :days => -days, :hours => -hours, :minutes => -minutes, :seconds => -seconds)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Double-dispatch method to support RiCal::PropertyValue::DateTime.+
|
|
104
|
+
def add_to_date_time_value(date_time_value)
|
|
105
|
+
date_time_value.advance(:weeks => weeks, :days => days, :hours => hours, :minutes => minutes, :seconds => seconds)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module RiCal
|
|
2
|
+
class PropertyValue
|
|
3
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
|
4
|
+
#
|
|
5
|
+
# RiCal::PropertyValue::CalAddress represents an icalendar Duration property value
|
|
6
|
+
# which is defined in
|
|
7
|
+
# rfc 2445 section 4.8.1.6 pp 82-83
|
|
8
|
+
class Geo < PropertyValue
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|