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,23 @@
|
|
|
1
|
+
module RiCal
|
|
2
|
+
class Component
|
|
3
|
+
class Timezone
|
|
4
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
|
5
|
+
#
|
|
6
|
+
# A StandardPeriod is a TimezonePeriod during which daylight saving time is *not* in effect
|
|
7
|
+
class StandardPeriod < TimezonePeriod #:nodoc: all
|
|
8
|
+
|
|
9
|
+
def self.entity_name #:nodoc:
|
|
10
|
+
"STANDARD"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def dst?
|
|
14
|
+
false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def ambiguous_local?(time)
|
|
18
|
+
[time.year, time.month, time.day] == [dtstart.year, dtstart.month, dtstart.day]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. .. properties timezone_period.rb])
|
|
2
|
+
|
|
3
|
+
module RiCal
|
|
4
|
+
class Component
|
|
5
|
+
class Timezone
|
|
6
|
+
#- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
|
|
7
|
+
#
|
|
8
|
+
# A TimezonePeriod is a component of a timezone representing a period during which a particular offset from UTC is
|
|
9
|
+
# in effect.
|
|
10
|
+
#
|
|
11
|
+
# to see the property accessing methods for this class see the RiCal::Properties::TimezonePeriod module
|
|
12
|
+
class TimezonePeriod < Component
|
|
13
|
+
include Properties::TimezonePeriod
|
|
14
|
+
|
|
15
|
+
include OccurrenceEnumerator
|
|
16
|
+
|
|
17
|
+
def zone_identifier #:nodoc:
|
|
18
|
+
tzname.first
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def dtend #:nodoc:
|
|
22
|
+
nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def exdate_property #:nodoc:
|
|
26
|
+
nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def utc_total_offset #:nodoc:
|
|
30
|
+
tzoffsetto_property.to_seconds
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def exrule_property #:nodoc:
|
|
34
|
+
nil
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def last_before_utc(utc_time) #:nodoc:
|
|
38
|
+
last_before_local(utc_time + tzoffsetfrom_property)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def last_before_local(local_time) #:nodoc:
|
|
42
|
+
cand_occurrence = nil
|
|
43
|
+
each do |occurrence|
|
|
44
|
+
return cand_occurrence if occurrence.dtstart_property > local_time
|
|
45
|
+
cand_occurrence = occurrence
|
|
46
|
+
end
|
|
47
|
+
return cand_occurrence
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. properties todo.rb])
|
|
2
|
+
|
|
3
|
+
module RiCal
|
|
4
|
+
class Component
|
|
5
|
+
#- ©2009 Rick DeNatale
|
|
6
|
+
#- All rights reserved. Refer to the file README.txt for the license
|
|
7
|
+
#
|
|
8
|
+
# A Todo (VTODO) calendar component groups properties describing a to-do
|
|
9
|
+
# Todos may have multiple occurrences
|
|
10
|
+
#
|
|
11
|
+
# Todos may also contain one or more ALARM subcomponents
|
|
12
|
+
# to see the property accessing methods for this class see the RiCal::Properties::Todo module
|
|
13
|
+
# to see the methods for enumerating occurrences of recurring to-dos see the RiCal::OccurrenceEnumerator module
|
|
14
|
+
class Todo < Component
|
|
15
|
+
include Properties::Todo
|
|
16
|
+
|
|
17
|
+
def self.entity_name #:nodoc:
|
|
18
|
+
"VTODO"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def subcomponent_class #:nodoc:
|
|
22
|
+
{:alarm => Alarm }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Return a date_time representing the time at which the todo should start
|
|
26
|
+
def start_time
|
|
27
|
+
dtstart_property ? dtstart.to_datetime : nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Return a date_time representing the time at which the todo is due
|
|
31
|
+
def finish_time
|
|
32
|
+
if due
|
|
33
|
+
due_property.to_finish_time
|
|
34
|
+
elsif duration_property && dtstart_property
|
|
35
|
+
(dtstart_property + duration_property).to_finish_time
|
|
36
|
+
else
|
|
37
|
+
nil
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module RiCal
|
|
2
|
+
module CoreExtensions #:nodoc:
|
|
3
|
+
module Array #:nodoc:
|
|
4
|
+
#- ©2009 Rick DeNatale
|
|
5
|
+
#- All rights reserved. Refer to the file README.txt for the license
|
|
6
|
+
#
|
|
7
|
+
module Conversions
|
|
8
|
+
# return the concatenation of the elements representation in rfc 2445 format
|
|
9
|
+
def to_rfc2445_string # :doc:
|
|
10
|
+
join(",")
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require "#{File.dirname(__FILE__)}/date/conversions.rb"
|
|
2
|
+
require "#{File.dirname(__FILE__)}/time/week_day_predicates.rb"
|
|
3
|
+
require "#{File.dirname(__FILE__)}/time/calculations.rb"
|
|
4
|
+
require 'date'
|
|
5
|
+
|
|
6
|
+
class Date #:nodoc:
|
|
7
|
+
#- ©2009 Rick DeNatale
|
|
8
|
+
#- All rights reserved. Refer to the file README.txt for the license
|
|
9
|
+
#
|
|
10
|
+
include RiCal::CoreExtensions::Time::WeekDayPredicates
|
|
11
|
+
include RiCal::CoreExtensions::Time::Calculations
|
|
12
|
+
include RiCal::CoreExtensions::Date::Conversions
|
|
13
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module RiCal
|
|
2
|
+
module CoreExtensions #:nodoc:
|
|
3
|
+
module Date #:nodoc:
|
|
4
|
+
#- ©2009 Rick DeNatale
|
|
5
|
+
#- All rights reserved. Refer to the file README.txt for the license
|
|
6
|
+
#
|
|
7
|
+
module Conversions #:nodoc:
|
|
8
|
+
# Return an RiCal::PropertyValue::DateTime representing the receiver
|
|
9
|
+
def to_ri_cal_date_time_value(timezone_finder = nil)
|
|
10
|
+
RiCal::PropertyValue::DateTime.new(timezone_finder, :value => self)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Return an RiCal::PropertyValue::Date representing the receiver
|
|
14
|
+
def to_ri_cal_date_value(timezone_finder = nil)
|
|
15
|
+
RiCal::PropertyValue::Date.new(timezone_finder, :value => self)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
alias_method :to_ri_cal_date_or_date_time_value, :to_ri_cal_date_value
|
|
19
|
+
alias_method :to_ri_cal_occurrence_list_value, :to_ri_cal_date_value
|
|
20
|
+
|
|
21
|
+
# Return the natural ri_cal_property for this object
|
|
22
|
+
def to_ri_cal_property_value(timezone_finder = nil)
|
|
23
|
+
to_ri_cal_date_value(timezone_finder)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
unless defined? ActiveSupport
|
|
27
|
+
# A method to keep Time, Date and DateTime instances interchangeable on conversions.
|
|
28
|
+
# In this case, it simply returns +self+.
|
|
29
|
+
def to_date
|
|
30
|
+
self
|
|
31
|
+
end if RUBY_VERSION < '1.9'
|
|
32
|
+
|
|
33
|
+
# Converts a Date instance to a Time, where the time is set to the beginning of the day.
|
|
34
|
+
# The timezone can be either :local or :utc (default :local).
|
|
35
|
+
#
|
|
36
|
+
# ==== Examples
|
|
37
|
+
# date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
|
|
38
|
+
#
|
|
39
|
+
# date.to_time # => Sat Nov 10 00:00:00 0800 2007
|
|
40
|
+
# date.to_time(:local) # => Sat Nov 10 00:00:00 0800 2007
|
|
41
|
+
#
|
|
42
|
+
# date.to_time(:utc) # => Sat Nov 10 00:00:00 UTC 2007
|
|
43
|
+
def to_time(form = :local)
|
|
44
|
+
::Time.send("#{form}_time", year, month, day)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Converts a Date instance to a DateTime, where the time is set to the beginning of the day
|
|
48
|
+
# and UTC offset is set to 0.
|
|
49
|
+
#
|
|
50
|
+
# ==== Examples
|
|
51
|
+
# date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
|
|
52
|
+
#
|
|
53
|
+
# date.to_datetime # => Sat, 10 Nov 2007 00:00:00 0000
|
|
54
|
+
def to_datetime
|
|
55
|
+
::DateTime.civil(year, month, day, 0, 0, 0, 0)
|
|
56
|
+
end if RUBY_VERSION < '1.9'
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require "#{File.dirname(__FILE__)}/date_time/conversions.rb"
|
|
2
|
+
require "#{File.dirname(__FILE__)}/time/tzid_access.rb"
|
|
3
|
+
require "#{File.dirname(__FILE__)}/time/week_day_predicates.rb"
|
|
4
|
+
require "#{File.dirname(__FILE__)}/time/calculations.rb"
|
|
5
|
+
require 'date'
|
|
6
|
+
|
|
7
|
+
class DateTime #:nodoc:
|
|
8
|
+
#- ©2009 Rick DeNatale
|
|
9
|
+
#- All rights reserved. Refer to the file README.txt for the license
|
|
10
|
+
#
|
|
11
|
+
include RiCal::CoreExtensions::Time::WeekDayPredicates
|
|
12
|
+
include RiCal::CoreExtensions::Time::Calculations
|
|
13
|
+
include RiCal::CoreExtensions::Time::TzidAccess
|
|
14
|
+
include RiCal::CoreExtensions::DateTime::Conversions
|
|
15
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'date'
|
|
2
|
+
module RiCal
|
|
3
|
+
module CoreExtensions #:nodoc:
|
|
4
|
+
module DateTime #:nodoc:
|
|
5
|
+
#- ©2009 Rick DeNatale
|
|
6
|
+
#- All rights reserved. Refer to the file README.txt for the license
|
|
7
|
+
#
|
|
8
|
+
module Conversions #:nodoc:
|
|
9
|
+
# Return an RiCal::PropertyValue::DateTime representing the receiver
|
|
10
|
+
def to_ri_cal_date_time_value(timezone_finder = nil) #:nodoc:
|
|
11
|
+
RiCal::PropertyValue::DateTime.new(
|
|
12
|
+
timezone_finder,
|
|
13
|
+
:value => strftime("%Y%m%dT%H%M%S"),
|
|
14
|
+
:params => {"TZID" => self.tzid || :default})
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
alias_method :to_ri_cal_date_or_date_time_value, :to_ri_cal_date_time_value #:nodoc:
|
|
18
|
+
alias_method :to_ri_cal_occurrence_list_value, :to_ri_cal_date_time_value #:nodoc:
|
|
19
|
+
|
|
20
|
+
# Return the natural ri_cal_property for this object
|
|
21
|
+
def to_ri_cal_property_value(timezone_finder = nil) #:nodoc:
|
|
22
|
+
to_ri_cal_date_time_value(timezone_finder)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Return a copy of this object which will be interpreted as a floating time.
|
|
26
|
+
def with_floating_timezone
|
|
27
|
+
dup.set_tzid(:floating)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
unless defined? ActiveSupport
|
|
31
|
+
# Converts self to a Ruby Date object; time portion is discarded
|
|
32
|
+
def to_date
|
|
33
|
+
::Date.new(year, month, day)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Attempts to convert self to a Ruby Time object; returns self if out of range of Ruby Time class
|
|
37
|
+
# If self has an offset other than 0, self will just be returned unaltered, since there's no clean way to map it to a Time
|
|
38
|
+
def to_time
|
|
39
|
+
self.offset == 0 ? ::Time.utc_time(year, month, day, hour, min, sec) : self
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# To be able to keep Times, Dates and DateTimes interchangeable on conversions
|
|
43
|
+
def to_datetime
|
|
44
|
+
self
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module RiCal
|
|
2
|
+
module CoreExtensions #:nodoc:
|
|
3
|
+
module Object #:nodoc:
|
|
4
|
+
#- ©2009 Rick DeNatale
|
|
5
|
+
#- All rights reserved. Refer to the file README.txt for the license
|
|
6
|
+
#
|
|
7
|
+
module Conversions #:nodoc:
|
|
8
|
+
# Used to format rfc2445 output for RiCal
|
|
9
|
+
def to_rfc2445_string
|
|
10
|
+
to_s
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Used by RiCal specs returns the receiver
|
|
14
|
+
def to_ri_cal_ruby_value
|
|
15
|
+
self
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module RiCal
|
|
2
|
+
module CoreExtensions #:nodoc:
|
|
3
|
+
module String #:nodoc:
|
|
4
|
+
#- ©2009 Rick DeNatale
|
|
5
|
+
#- All rights reserved. Refer to the file README.txt for the license
|
|
6
|
+
#
|
|
7
|
+
module Conversions #:nodoc:
|
|
8
|
+
# Parse the receiver as an RiCal::PropertyValue::DateTime
|
|
9
|
+
def to_ri_cal_date_time_value(timezone_finder = nil)
|
|
10
|
+
params, value = *Parser.params_and_value(self, :no_leading_semicolon)
|
|
11
|
+
if PropertyValue::DateTime.valid_string?(value)
|
|
12
|
+
PropertyValue::DateTime.new(timezone_finder, :params => params, :value => value)
|
|
13
|
+
else
|
|
14
|
+
raise InvalidPropertyValue.new("#{self.inspect} is not a valid rfc 2445 date-time")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def to_ri_cal_date_or_date_time_value(timezone_finder = nil)
|
|
20
|
+
params, value = *Parser.params_and_value(self, :no_leading_semicolon)
|
|
21
|
+
if PropertyValue::DateTime.valid_string?(value) || PropertyValue::Date.valid_string?(value)
|
|
22
|
+
PropertyValue.date_or_date_time(timezone_finder, :params => params, :value => value)
|
|
23
|
+
else
|
|
24
|
+
raise InvalidPropertyValue.new("#{self.inspect} is not a valid rfc 2445 date or date-time")
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Parse the receiver as an RiCal::PropertyValue::DurationValue
|
|
29
|
+
def to_ri_cal_duration_value(timezone_finder = nil)
|
|
30
|
+
params, value = *Parser.params_and_value(self)
|
|
31
|
+
if PropertyValue::Duration.valid_string?(value)
|
|
32
|
+
PropertyValue::Duration.new(timezone_finder, :params => params, :value => value)
|
|
33
|
+
else
|
|
34
|
+
raise InvalidPropertyValue.new("#{self.inspect} is not a valid rfc 2445 duration")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def to_ri_cal_occurrence_list_value(timezone_finder = nil)
|
|
39
|
+
params, value = *Parser.params_and_value(self, :no_leading_semicolon)
|
|
40
|
+
if PropertyValue::DateTime.valid_string?(value)
|
|
41
|
+
PropertyValue::DateTime.new(timezone_finder, :params => params, :value => value)
|
|
42
|
+
elsif PropertyValue::Date.valid_string?(value)
|
|
43
|
+
PropertyValue::Date.new(timezone_finder, :params => params, :value => value)
|
|
44
|
+
elsif PropertyValue::Period.valid_string?(value)
|
|
45
|
+
PropertyValue::Period.new(timezone_finder, :params => params, :value => value)
|
|
46
|
+
else
|
|
47
|
+
raise "Invalid value for occurrence list #{self.inspect}"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# code stolen from ActiveSupport Gem
|
|
52
|
+
unless ::String.instance_methods.include?("camelize")
|
|
53
|
+
# Convert the receiver to camelized form
|
|
54
|
+
# This method duplicates the method provided by ActiveSupport, and will only be defined
|
|
55
|
+
# by the RiCal gem if it is not already defined.
|
|
56
|
+
def camelize
|
|
57
|
+
self.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require "#{File.dirname(__FILE__)}/time/conversions.rb"
|
|
2
|
+
require "#{File.dirname(__FILE__)}/time/tzid_access.rb"
|
|
3
|
+
require "#{File.dirname(__FILE__)}/time/week_day_predicates.rb"
|
|
4
|
+
require "#{File.dirname(__FILE__)}/time/calculations.rb"
|
|
5
|
+
#- ©2009 Rick DeNatale
|
|
6
|
+
#- All rights reserved. Refer to the file README.txt for the license
|
|
7
|
+
#
|
|
8
|
+
class Time #:nodoc:
|
|
9
|
+
include RiCal::CoreExtensions::Time::WeekDayPredicates
|
|
10
|
+
include RiCal::CoreExtensions::Time::Calculations
|
|
11
|
+
include RiCal::CoreExtensions::Time::Conversions
|
|
12
|
+
include RiCal::CoreExtensions::Time::TzidAccess
|
|
13
|
+
end
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
module RiCal
|
|
2
|
+
module CoreExtensions #:nodoc:
|
|
3
|
+
module Time #:nodoc:
|
|
4
|
+
#- ©2009 Rick DeNatale
|
|
5
|
+
#- All rights reserved. Refer to the file README.txt for the license
|
|
6
|
+
#
|
|
7
|
+
# Provide calculation methods for use by the RiCal gem
|
|
8
|
+
# This module is included by Time, Date, and DateTime
|
|
9
|
+
module Calculations
|
|
10
|
+
# A predicate method used to determine if the receiver is within a leap year
|
|
11
|
+
def leap_year?
|
|
12
|
+
year % 4 == 0 && (year % 400 == 0 || year % 100 != 0)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Return the number of days in the month which includes the receiver
|
|
16
|
+
def days_in_month
|
|
17
|
+
raw = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][self.month]
|
|
18
|
+
self.month == 2 && leap_year? ? raw + 1 : raw
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Return the date on which the first iso week with a given starting week day occurs
|
|
22
|
+
# for a given iso year
|
|
23
|
+
#
|
|
24
|
+
#
|
|
25
|
+
# From RFC 2445 page 43:
|
|
26
|
+
# A week is defined as a seven day period, starting on the day of the week defined to be the
|
|
27
|
+
# week start (see WKST). Week number one of the calendar year is the first week which contains
|
|
28
|
+
# at least four (4) days in that calendar
|
|
29
|
+
# year.
|
|
30
|
+
#
|
|
31
|
+
# == parameters
|
|
32
|
+
# year:: the iso year
|
|
33
|
+
# wkst:: an integer representing the day of the week on which weeks are deemed to start. This uses
|
|
34
|
+
# the ruby convention where 0 represents Sunday.
|
|
35
|
+
def self.iso_week_one(year, wkst)
|
|
36
|
+
#
|
|
37
|
+
# Note that wkst uses the ruby definition, with Sunday = 0
|
|
38
|
+
#
|
|
39
|
+
# A good article about calculating ISO week number is at
|
|
40
|
+
# http://www.boyet.com/Articles/PublishedArticles/CalculatingtheISOweeknumb.html
|
|
41
|
+
#
|
|
42
|
+
# RFC 2445 generalizes the notion of ISO week by allowing the start of the week to vary.
|
|
43
|
+
# In order to adopt the algorithm in the referenced article, we must determine, for each
|
|
44
|
+
# wkst value, the day in January which must be contained in week 1 of the year.
|
|
45
|
+
#
|
|
46
|
+
# For a given wkst week 1 for a year is the first week which
|
|
47
|
+
# 1) Starts with a day with a wday of wkst
|
|
48
|
+
# 2) Contains a majority (4 or more) of days in that year
|
|
49
|
+
#
|
|
50
|
+
# If end of prior Dec, start of Jan Week 1 starts on For WKST =
|
|
51
|
+
|
|
52
|
+
# MO TU WE TH FR SA SU MO TU WE TH FR SA SU MO TU WE TH FR SA SU
|
|
53
|
+
# 01 02 03 04 05 06 07 08 09 10 11 12 13 14 01-07 02-08 03-09 04-10 05-11 06-12 07-13
|
|
54
|
+
# 31 01 02 03 04 05 06 07 08 09 10 11 12 13 31-06 01-07 02-08 03-09 04-10 05-11 06-12
|
|
55
|
+
# 30 31 01 02 03 04 05 06 07 08 09 10 11 12 30-05 31-06 01-07 02-08 03-09 04-10 05-11
|
|
56
|
+
# 29 30 31 01 02 03 04 05 06 07 08 09 10 11 29-04 30-05 31-06 01-07 02-08 03-09 04-10
|
|
57
|
+
# 28 29 30 31 01 02 03 04 05 06 07 08 09 10 04-10 29-04 30-05 31-06 01-07 02-08 03-09
|
|
58
|
+
# 27 28 29 30 31 01 02 03 04 05 06 07 08 09 03-09 04-10 29-04 30-05 31-06 01-07 02-08
|
|
59
|
+
# 26 27 28 29 30 31 01 02 03 04 05 06 07 08 02-08 03-09 04-10 29-04 30-05 31-06 01-07
|
|
60
|
+
# 25 26 27 28 29 30 31 01 02 03 04 05 06 07 01-07 02-08 03-09 04-10 29-04 30-05 31-06
|
|
61
|
+
# Week 1 must contain 4 4 4 4 ? ? ?
|
|
62
|
+
#
|
|
63
|
+
# So for a wkst of FR, SA, or SU, there is no date which MUST be contained in the 1st week
|
|
64
|
+
# We'll have to brute force that
|
|
65
|
+
if (1..4).include?(wkst)
|
|
66
|
+
# return the date of the wkst day which is less than or equal to jan4th
|
|
67
|
+
jan4th = ::Date.new(year, 1, 4)
|
|
68
|
+
result = jan4th - (convert_wday(jan4th.wday) - convert_wday(wkst))
|
|
69
|
+
else
|
|
70
|
+
# return the date of the wkst day which is greater than or equal to Dec 31 of the prior year
|
|
71
|
+
dec29th = ::Date.new(year-1, 12, 29)
|
|
72
|
+
result = dec29th + convert_wday(wkst) - convert_wday(dec29th.wday)
|
|
73
|
+
end
|
|
74
|
+
result
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Convert the receivers wday to RFC 2445 format. Whereas the Ruby time/date classes use
|
|
78
|
+
# 0 to represent Sunday, RFC 2445 uses 7.
|
|
79
|
+
def self.convert_wday(wday)
|
|
80
|
+
wday == 0 ? 7 : wday
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Return an array containing the iso year and iso week number for the receiver.
|
|
84
|
+
# Note that the iso year may be the year before or after the calendar year containing the receiver.
|
|
85
|
+
# == parameter
|
|
86
|
+
# wkst:: an integer representing the day of the week on which weeks are deemed to start. This uses
|
|
87
|
+
# the ruby convention where 0 represents Sunday.
|
|
88
|
+
def iso_year_and_week_one_start(wkst)
|
|
89
|
+
iso_year = self.year
|
|
90
|
+
date = ::Date.new(self.year, self.month, self.mday)
|
|
91
|
+
if (date >= ::Date.new(iso_year, 12, 29))
|
|
92
|
+
week_one_start = Calculations.iso_week_one(iso_year + 1, wkst)
|
|
93
|
+
if date < week_one_start
|
|
94
|
+
week_one_start = Calculations.iso_week_one(iso_year, wkst)
|
|
95
|
+
else
|
|
96
|
+
iso_year += 1
|
|
97
|
+
end
|
|
98
|
+
else
|
|
99
|
+
week_one_start = Calculations.iso_week_one(iso_year, wkst)
|
|
100
|
+
if (date < week_one_start)
|
|
101
|
+
iso_year -= 1
|
|
102
|
+
week_one_start = Calculations.iso_week_one(iso_year, wkst)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
[iso_year, week_one_start]
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def iso_year_and_week_num(wkst) #:nodoc:
|
|
109
|
+
iso_year, week_one_start = *iso_year_and_week_one_start(wkst)
|
|
110
|
+
[iso_year, (::Date.new(self.year, self.month, self.mday) - week_one_start).to_i / 7 + 1]
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# return the number of weeks in the the iso year containing the receiver
|
|
114
|
+
# == parameter
|
|
115
|
+
# wkst:: an integer representing the day of the week on which weeks are deemed to start. This uses
|
|
116
|
+
# the ruby convention where 0 represents Sunday.
|
|
117
|
+
def iso_weeks_in_year(wkst)
|
|
118
|
+
iso_year, week_one_start = *iso_year_and_week_one_start(wkst)
|
|
119
|
+
probe_date = week_one_start + (7*52)
|
|
120
|
+
if probe_date.iso_year(wkst) == iso_year
|
|
121
|
+
53
|
|
122
|
+
else
|
|
123
|
+
52
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# return the iso week number of the receiver
|
|
128
|
+
# == parameter
|
|
129
|
+
# wkst:: an integer representing the day of the week on which weeks are deemed to start. This uses
|
|
130
|
+
# the ruby convention where 0 represents Sunday.
|
|
131
|
+
def iso_week_num(wkst)
|
|
132
|
+
iso_year_and_week_num(wkst)[1]
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# return the iso year of the receiver
|
|
136
|
+
# == parameter
|
|
137
|
+
# wkst:: an integer representing the day of the week on which weeks are deemed to start. This uses
|
|
138
|
+
# the ruby convention where 0 represents Sunday.
|
|
139
|
+
def iso_year(wkst)
|
|
140
|
+
iso_year_and_week_num(wkst)[0]
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# return the first day of the iso year of the receiver
|
|
144
|
+
# == parameter
|
|
145
|
+
# wkst:: an integer representing the day of the week on which weeks are deemed to start. This uses
|
|
146
|
+
# the ruby convention where 0 represents Sunday.
|
|
147
|
+
def iso_year_start(wkst)
|
|
148
|
+
iso_year_and_week_one_start(wkst)[1]
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|