rubyredrick-ri_cal 0.0.2

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.
Files changed (123) hide show
  1. data/History.txt +3 -0
  2. data/Manifest.txt +122 -0
  3. data/README.txt +271 -0
  4. data/Rakefile +31 -0
  5. data/bin/ri_cal +8 -0
  6. data/component_attributes/alarm.yml +10 -0
  7. data/component_attributes/calendar.yml +4 -0
  8. data/component_attributes/component_property_defs.yml +180 -0
  9. data/component_attributes/event.yml +45 -0
  10. data/component_attributes/freebusy.yml +16 -0
  11. data/component_attributes/journal.yml +35 -0
  12. data/component_attributes/timezone.yml +3 -0
  13. data/component_attributes/timezone_period.yml +11 -0
  14. data/component_attributes/todo.yml +46 -0
  15. data/copyrights.txt +2 -0
  16. data/docs/draft-ietf-calsify-2446bis-08.txt +7280 -0
  17. data/docs/draft-ietf-calsify-rfc2445bis-09.txt +10416 -0
  18. data/docs/incrementers.txt +7 -0
  19. data/docs/rfc2445.pdf +0 -0
  20. data/lib/ri_cal/component/alarm.rb +22 -0
  21. data/lib/ri_cal/component/calendar.rb +199 -0
  22. data/lib/ri_cal/component/event.rb +30 -0
  23. data/lib/ri_cal/component/freebusy.rb +19 -0
  24. data/lib/ri_cal/component/journal.rb +22 -0
  25. data/lib/ri_cal/component/t_z_info_timezone.rb +124 -0
  26. data/lib/ri_cal/component/timezone/daylight_period.rb +26 -0
  27. data/lib/ri_cal/component/timezone/standard_period.rb +24 -0
  28. data/lib/ri_cal/component/timezone/timezone_period.rb +54 -0
  29. data/lib/ri_cal/component/timezone.rb +193 -0
  30. data/lib/ri_cal/component/todo.rb +26 -0
  31. data/lib/ri_cal/component.rb +224 -0
  32. data/lib/ri_cal/core_extensions/array/conversions.rb +15 -0
  33. data/lib/ri_cal/core_extensions/array.rb +7 -0
  34. data/lib/ri_cal/core_extensions/date/conversions.rb +27 -0
  35. data/lib/ri_cal/core_extensions/date.rb +13 -0
  36. data/lib/ri_cal/core_extensions/date_time/conversions.rb +27 -0
  37. data/lib/ri_cal/core_extensions/date_time.rb +13 -0
  38. data/lib/ri_cal/core_extensions/object/conversions.rb +20 -0
  39. data/lib/ri_cal/core_extensions/object.rb +8 -0
  40. data/lib/ri_cal/core_extensions/string/conversions.rb +32 -0
  41. data/lib/ri_cal/core_extensions/string.rb +8 -0
  42. data/lib/ri_cal/core_extensions/time/calculations.rb +153 -0
  43. data/lib/ri_cal/core_extensions/time/conversions.rb +27 -0
  44. data/lib/ri_cal/core_extensions/time/week_day_predicates.rb +88 -0
  45. data/lib/ri_cal/core_extensions/time.rb +11 -0
  46. data/lib/ri_cal/core_extensions.rb +6 -0
  47. data/lib/ri_cal/invalid_timezone_identifer.rb +20 -0
  48. data/lib/ri_cal/occurrence_enumerator.rb +172 -0
  49. data/lib/ri_cal/parser.rb +138 -0
  50. data/lib/ri_cal/properties/alarm.rb +390 -0
  51. data/lib/ri_cal/properties/calendar.rb +164 -0
  52. data/lib/ri_cal/properties/event.rb +1526 -0
  53. data/lib/ri_cal/properties/freebusy.rb +594 -0
  54. data/lib/ri_cal/properties/journal.rb +1240 -0
  55. data/lib/ri_cal/properties/timezone.rb +151 -0
  56. data/lib/ri_cal/properties/timezone_period.rb +416 -0
  57. data/lib/ri_cal/properties/todo.rb +1562 -0
  58. data/lib/ri_cal/property_value/array.rb +19 -0
  59. data/lib/ri_cal/property_value/cal_address.rb +12 -0
  60. data/lib/ri_cal/property_value/date.rb +119 -0
  61. data/lib/ri_cal/property_value/date_time/additive_methods.rb +43 -0
  62. data/lib/ri_cal/property_value/date_time/time_machine.rb +180 -0
  63. data/lib/ri_cal/property_value/date_time/timezone_support.rb +65 -0
  64. data/lib/ri_cal/property_value/date_time.rb +324 -0
  65. data/lib/ri_cal/property_value/duration.rb +106 -0
  66. data/lib/ri_cal/property_value/geo.rb +12 -0
  67. data/lib/ri_cal/property_value/integer.rb +13 -0
  68. data/lib/ri_cal/property_value/occurrence_list.rb +82 -0
  69. data/lib/ri_cal/property_value/period.rb +63 -0
  70. data/lib/ri_cal/property_value/recurrence_rule/enumeration_support_methods.rb +98 -0
  71. data/lib/ri_cal/property_value/recurrence_rule/enumerator.rb +77 -0
  72. data/lib/ri_cal/property_value/recurrence_rule/initialization_methods.rb +149 -0
  73. data/lib/ri_cal/property_value/recurrence_rule/negative_setpos_enumerator.rb +54 -0
  74. data/lib/ri_cal/property_value/recurrence_rule/numbered_span.rb +32 -0
  75. data/lib/ri_cal/property_value/recurrence_rule/occurence_incrementer.rb +794 -0
  76. data/lib/ri_cal/property_value/recurrence_rule/recurring_day.rb +132 -0
  77. data/lib/ri_cal/property_value/recurrence_rule/recurring_month_day.rb +61 -0
  78. data/lib/ri_cal/property_value/recurrence_rule/recurring_numbered_week.rb +34 -0
  79. data/lib/ri_cal/property_value/recurrence_rule/recurring_year_day.rb +50 -0
  80. data/lib/ri_cal/property_value/recurrence_rule/validations.rb +126 -0
  81. data/lib/ri_cal/property_value/recurrence_rule.rb +146 -0
  82. data/lib/ri_cal/property_value/text.rb +41 -0
  83. data/lib/ri_cal/property_value/uri.rb +12 -0
  84. data/lib/ri_cal/property_value/utc_offset.rb +34 -0
  85. data/lib/ri_cal/property_value.rb +110 -0
  86. data/lib/ri_cal/required_timezones.rb +56 -0
  87. data/lib/ri_cal/time_with_floating_timezone.rb +59 -0
  88. data/lib/ri_cal.rb +134 -0
  89. data/ri_cal.gemspec +47 -0
  90. data/sample_ical_files/from_ical_dot_app/test1.ics +38 -0
  91. data/script/console +10 -0
  92. data/script/destroy +14 -0
  93. data/script/generate +14 -0
  94. data/script/txt2html +71 -0
  95. data/spec/ri_cal/component/alarm_spec.rb +13 -0
  96. data/spec/ri_cal/component/calendar_spec.rb +55 -0
  97. data/spec/ri_cal/component/event_spec.rb +157 -0
  98. data/spec/ri_cal/component/freebusy_spec.rb +13 -0
  99. data/spec/ri_cal/component/journal_spec.rb +13 -0
  100. data/spec/ri_cal/component/t_z_info_timezone_spec.rb +37 -0
  101. data/spec/ri_cal/component/timezone_spec.rb +155 -0
  102. data/spec/ri_cal/component/todo_spec.rb +61 -0
  103. data/spec/ri_cal/component_spec.rb +212 -0
  104. data/spec/ri_cal/core_extensions/time/calculations_spec.rb +189 -0
  105. data/spec/ri_cal/core_extensions/time/week_day_predicates_spec.rb +46 -0
  106. data/spec/ri_cal/occurrence_enumerator_spec.rb +218 -0
  107. data/spec/ri_cal/parser_spec.rb +304 -0
  108. data/spec/ri_cal/property_value/date_spec.rb +22 -0
  109. data/spec/ri_cal/property_value/date_time_spec.rb +448 -0
  110. data/spec/ri_cal/property_value/duration_spec.rb +80 -0
  111. data/spec/ri_cal/property_value/period_spec.rb +50 -0
  112. data/spec/ri_cal/property_value/recurrence_rule/recurring_year_day_spec.rb +22 -0
  113. data/spec/ri_cal/property_value/recurrence_rule_spec.rb +1815 -0
  114. data/spec/ri_cal/property_value/text_spec.rb +14 -0
  115. data/spec/ri_cal/property_value/utc_offset_spec.rb +49 -0
  116. data/spec/ri_cal/property_value_spec.rb +111 -0
  117. data/spec/ri_cal/required_timezones_spec.rb +68 -0
  118. data/spec/ri_cal_spec.rb +54 -0
  119. data/spec/spec.opts +4 -0
  120. data/spec/spec_helper.rb +24 -0
  121. data/tasks/ri_cal.rake +403 -0
  122. data/tasks/spec.rake +35 -0
  123. metadata +201 -0
@@ -0,0 +1,19 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ #- ©2009 Rick DeNatale
4
+ #- All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ class Array < PropertyValue # :nodoc:
7
+
8
+ def value=(val)
9
+ case val
10
+ when String
11
+ @value = val.split(",")
12
+ else
13
+ @value = val
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,12 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ #- ©2009 Rick DeNatale
4
+ #- All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ # RiCal::PropertyValue::CalAddress represents an icalendar CalAddress property value
7
+ # which is defined in
8
+ # RFC 2445 section 4.3.3 p 34
9
+ class CalAddress < PropertyValue
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,119 @@
1
+ require 'date'
2
+ module RiCal
3
+ class PropertyValue
4
+ #- ©2009 Rick DeNatale
5
+ #- All rights reserved. Refer to the file README.txt for the license
6
+ #
7
+ # RiCal::PropertyValue::CalAddress represents an icalendar Date property value
8
+ # which is defined in
9
+ # RFC 2445 section 4.3.4 p 34
10
+ class Date < PropertyValue
11
+ # Returns the value of the reciever as an RFC 2445 iCalendar string
12
+ def value
13
+ if @date_time_value
14
+ @date_time_value.strftime("%Y%m%d")
15
+ else
16
+ nil
17
+ end
18
+ end
19
+
20
+ # Set the value of the property to val
21
+ #
22
+ # val may be either:
23
+ #
24
+ # * A string which can be parsed as a DateTime
25
+ # * A Time instance
26
+ # * A Date instance
27
+ # * A DateTime instance
28
+ def value=(val)
29
+ case val
30
+ when nil
31
+ @date_time_value = nil
32
+ when String
33
+ @date_time_value = ::DateTime.parse(::DateTime.parse(val).strftime("%Y%m%d"))
34
+ when ::Time, ::Date, ::DateTime
35
+ @date_time_value = ::DateTime.parse(val.strftime("%Y%m%d"))
36
+ end
37
+ end
38
+
39
+ def visible_params #:nodoc:
40
+ {"VALUE" => "DATE"}.merge(params)
41
+ end
42
+
43
+ # Returns the year (including the century)
44
+ def year
45
+ @date_time_value.year
46
+ end
47
+
48
+ # Returns the month of the year (1..12)
49
+ def month
50
+ @date_time_value.month
51
+ end
52
+
53
+ # Returns the day of the month
54
+ def day
55
+ @date_time_value.day
56
+ end
57
+
58
+ # Returns the ruby representation a ::Date
59
+ def ruby_value
60
+ ::Date.parse(@date_time_value.strftime("%Y%m%d"))
61
+ end
62
+
63
+ alias_method :to_ri_cal_ruby_value, :ruby_value
64
+
65
+ # Return an instance of RiCal::PropertyValue::DateTime representing the start of this date
66
+ def to_ri_cal_date_time_value
67
+ PropertyValue::DateTime.new(:value => @date_time_value)
68
+ end
69
+
70
+ # Return this date property
71
+ def to_ri_cal_date_value
72
+ self
73
+ end
74
+
75
+ # Return the "Natural' property value for the date_property, in this case the date property itself."
76
+ def to_ri_cal_date_or_date_time_value
77
+ self
78
+ end
79
+
80
+ def compute_change(d, options) #:nodoc:
81
+ ::Date.civil((options[:year] || d.year), (options[:month] || d.month), (options[:day] || d.day))
82
+ end
83
+
84
+ def compute_advance(d, options) #:nodoc:
85
+ d = d >> options[:years] * 12 if options[:years]
86
+ d = d >> options[:months] if options[:months]
87
+ d = d + options[:weeks] * 7 if options[:weeks]
88
+ d = d + options[:days] if options[:days]
89
+ compute_change(@date_time_value, :year => d.year, :month => d.month, :day => d.day)
90
+ end
91
+
92
+ def advance(options) #:nodoc:
93
+ PropertyValue::Date.new(timezone_finder, :value => compute_advance(@date_time_value, options), :params =>(params ? params.dup : nil) )
94
+ end
95
+
96
+ def change(options) #:nodoc:
97
+ PropertyValue::Date.new(timezone_finder,:value => compute_change(@date_time_value, options), :params => (params ? params.dup : nil) )
98
+ end
99
+
100
+ def add_date_times_to(required_timezones) #:nodoc:
101
+ # Do nothing since dates don't have a timezone
102
+ end
103
+
104
+
105
+ # Delegate unknown messages to the wrappered Date instance.
106
+ # TODO: Is this really necessary?
107
+ def method_missing(selector, *args) #:nodoc:
108
+ @date_time_value.send(selector, *args)
109
+ end
110
+
111
+ # TODO: consider if this should be a period rather than a hash
112
+ def occurrence_hash(default_duration) #:nodoc:
113
+ date_time = self.to_ri_cal_date_time_value
114
+ {:start => date_time,
115
+ :end => date_time.advance(:hours => 24, :seconds => -1)}
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,43 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ #- ©2009 Rick DeNatale
4
+ #- 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
@@ -0,0 +1,180 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ #- ©2009 Rick DeNatale
4
+ #- 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
@@ -0,0 +1,65 @@
1
+ module RiCal
2
+ class PropertyValue
3
+ #- ©2009 Rick DeNatale
4
+ #- All rights reserved. Refer to the file README.txt for the license
5
+ #
6
+ # Time zone related ethods 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
11
+ end
12
+
13
+ def tzid=(string) #:nodoc:
14
+ @tzid = string
15
+ @timezone = nil
16
+ end
17
+
18
+ def timezone #:nodoc:
19
+ @timezone ||= timezone_finder.find_timezone(@tzid)
20
+ end
21
+
22
+ # Determine if the receiver has a local time zone, i.e. it is not a floating time or a UTC time
23
+ def has_local_timezone?
24
+ tzid && tzid != "UTC"
25
+ end
26
+
27
+ # Return the receiver if it has a floating time zone already,
28
+ # otherwise return a DATETIME property with the same time as the receiver but with a floating time zone
29
+ def with_floating_timezone
30
+ if @tzid == nil
31
+ self
32
+ else
33
+ @date_time_value.with_floating_timezone.to_ri_cal_date_time_value
34
+ end
35
+ end
36
+
37
+ # Returns a instance that represents the time in UTC.
38
+ def utc
39
+ if has_local_timezone?
40
+ timezone.local_to_utc(self)
41
+ else # Already local or a floating time
42
+ self
43
+ end
44
+ end
45
+
46
+ # Predicate indicating whether or not the instance represents a ZULU time
47
+ def utc?
48
+ tzid == "UTC"
49
+ end
50
+
51
+ # Returns the simultaneous time in the specified zone.
52
+ def in_time_zone(new_zone)
53
+ new_zone = timezone_finder.find_timezone(new_zone)
54
+ return self if tzid == new_zone.identifier
55
+ if has_local_timezone?
56
+ new_zone.utc_to_local(utc)
57
+ elsif utc?
58
+ new_zone.utc_to_local(self)
59
+ else # Floating time
60
+ DateTime.new(timezone_finder, :value => @date_time_value, :tzid => new_zone.identifier)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end