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,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
|
+
def to_overlap_range_start
|
26
|
+
self
|
27
|
+
end
|
28
|
+
alias_method :to_overlap_range_end, :to_overlap_range_start
|
29
|
+
|
30
|
+
# Return a copy of this object which will be interpreted as a floating time.
|
31
|
+
def with_floating_timezone
|
32
|
+
dup.set_tzid(:floating)
|
33
|
+
end
|
34
|
+
|
35
|
+
unless DateTime.instance_methods.map {|selector| selector.to_sym}.include?(:to_date)
|
36
|
+
# Converts self to a Ruby Date object; time portion is discarded
|
37
|
+
def to_date
|
38
|
+
::Date.new(year, month, day)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
unless DateTime.instance_methods.map {|selector| selector.to_sym}.include?(:to_datetime)
|
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,15 @@
|
|
1
|
+
require "ri_cal/core_extensions/date_time/conversions.rb"
|
2
|
+
require "ri_cal/core_extensions/time/tzid_access.rb"
|
3
|
+
require "ri_cal/core_extensions/time/week_day_predicates.rb"
|
4
|
+
require "ri_cal/core_extensions/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,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,57 @@
|
|
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
|
+
def to_ri_cal_text_property
|
9
|
+
PropertyValue::Text.new(nil, :value => self)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Parse the receiver as an RiCal::PropertyValue::DateTime
|
13
|
+
def to_ri_cal_date_time_value(timezone_finder = nil)
|
14
|
+
params, value = *Parser.params_and_value(self, :no_leading_semicolon)
|
15
|
+
if PropertyValue::DateTime.valid_string?(value)
|
16
|
+
PropertyValue::DateTime.new(timezone_finder, :params => params, :value => value)
|
17
|
+
else
|
18
|
+
raise InvalidPropertyValue.new("#{self.inspect} is not a valid rfc 2445 date-time")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def to_ri_cal_date_or_date_time_value(timezone_finder = nil)
|
24
|
+
params, value = *Parser.params_and_value(self, :no_leading_semicolon)
|
25
|
+
if PropertyValue::DateTime.valid_string?(value) || PropertyValue::Date.valid_string?(value)
|
26
|
+
PropertyValue.date_or_date_time(timezone_finder, :params => params, :value => value)
|
27
|
+
else
|
28
|
+
raise InvalidPropertyValue.new("#{self.inspect} is not a valid rfc 2445 date or date-time")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Parse the receiver as an RiCal::PropertyValue::DurationValue
|
33
|
+
def to_ri_cal_duration_value(timezone_finder = nil)
|
34
|
+
params, value = *Parser.params_and_value(self)
|
35
|
+
if PropertyValue::Duration.valid_string?(value)
|
36
|
+
PropertyValue::Duration.new(timezone_finder, :params => params, :value => value)
|
37
|
+
else
|
38
|
+
raise InvalidPropertyValue.new("#{self.inspect} is not a valid rfc 2445 duration")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_ri_cal_occurrence_list_value(timezone_finder = nil)
|
43
|
+
params, value = *Parser.params_and_value(self, :no_leading_semicolon)
|
44
|
+
if PropertyValue::DateTime.valid_string?(value)
|
45
|
+
PropertyValue::DateTime.new(timezone_finder, :params => params, :value => value)
|
46
|
+
elsif PropertyValue::Date.valid_string?(value)
|
47
|
+
PropertyValue::Date.new(timezone_finder, :params => params, :value => value)
|
48
|
+
elsif PropertyValue::Period.valid_string?(value)
|
49
|
+
PropertyValue::Period.new(timezone_finder, :params => params, :value => value)
|
50
|
+
else
|
51
|
+
raise "Invalid value for occurrence list #{self.inspect}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
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
|
@@ -0,0 +1,42 @@
|
|
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
|
+
module Conversions
|
8
|
+
# Return an RiCal::PropertyValue::DateTime representing the receiver
|
9
|
+
def to_ri_cal_date_time_value(timezone_finder = nil) #:nodoc:
|
10
|
+
RiCal::PropertyValue::DateTime.new(
|
11
|
+
timezone_finder,
|
12
|
+
:value => strftime("%Y%m%dT%H%M%S"),
|
13
|
+
:params => {"TZID" => self.tzid || :default})
|
14
|
+
end
|
15
|
+
|
16
|
+
alias_method :to_ri_cal_date_or_date_time_value, :to_ri_cal_date_time_value #:nodoc:
|
17
|
+
alias_method :to_ri_cal_occurrence_list_value, :to_ri_cal_date_time_value #:nodoc:
|
18
|
+
|
19
|
+
# Return the natural ri_cal_property for this object
|
20
|
+
def to_ri_cal_property_value(timezone_finder = nil) #:nodoc:
|
21
|
+
to_ri_cal_date_time_value(timezone_finder)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_overlap_range_start
|
25
|
+
to_datetime
|
26
|
+
end
|
27
|
+
|
28
|
+
alias_method :to_overlap_range_end, :to_overlap_range_start
|
29
|
+
|
30
|
+
# Return a copy of this object which will be interpreted as a floating time.
|
31
|
+
def with_floating_timezone
|
32
|
+
dup.set_tzid(:floating)
|
33
|
+
end
|
34
|
+
|
35
|
+
unless Time.instance_methods.map {|selector| selector.to_sym}.include?(:to_datetime)
|
36
|
+
require 'date'
|
37
|
+
::Time.send(:public, :to_datetime)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,50 @@
|
|
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
|
+
# Provides a tzid attribute for ::Time and ::DateTime
|
8
|
+
module TzidAccess
|
9
|
+
# The tzid attribute is used by RiCal, it should be a valid timezone identifier within a calendar,
|
10
|
+
# :floating to indicate a floating time, or nil to use the default timezone in effect
|
11
|
+
#
|
12
|
+
# See PropertyValue::DateTime#default_tzid= and Component::Calendar#tzid=
|
13
|
+
attr_accessor :tzid
|
14
|
+
|
15
|
+
# Convenience method, sets the tzid and returns the receiver
|
16
|
+
def set_tzid(time_zone_identifier)
|
17
|
+
self.tzid = time_zone_identifier
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
# Predicate indicating whether or not the instance represents a floating time
|
22
|
+
def has_floating_timezone?
|
23
|
+
tzid == :floating
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module TimeWithZoneExtension #:nodoc:
|
31
|
+
def tzid
|
32
|
+
utc? ? "UTC" : time_zone.tzinfo.identifier
|
33
|
+
end
|
34
|
+
|
35
|
+
# Predicate indicating whether or not the instance represents a floating time
|
36
|
+
def has_floating_timezone?
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_ri_cal_date_time_value(timezone_finder=nil)
|
41
|
+
::RiCal::PropertyValue::DateTime.new(timezone_finder, :params => {"TZID" => tzid}, :value => strftime("%Y%m%dT%H%M%S"))
|
42
|
+
end
|
43
|
+
alias_method :to_ri_cal_date_or_date_time_value, :to_ri_cal_date_time_value
|
44
|
+
alias_method :to_ri_cal_occurrence_list_value, :to_ri_cal_date_time_value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
if RiCal::TimeWithZone
|
49
|
+
RiCal::TimeWithZone.class_eval {include RiCal::TimeWithZoneExtension}
|
50
|
+
end
|
@@ -0,0 +1,55 @@
|
|
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 predicate and related methods for use by the RiCal gem
|
8
|
+
# This module is included by Time, Date, and DateTime
|
9
|
+
module WeekDayPredicates
|
10
|
+
|
11
|
+
# Determine the day which falls on a particular weekday of the same month as the receiver
|
12
|
+
#
|
13
|
+
# == Parameters
|
14
|
+
# n:: the ordinal number being requested
|
15
|
+
# which_wday:: the weekday using Ruby time conventions, i.e. 0 => Sunday, 1 => Monday, ...
|
16
|
+
|
17
|
+
# e.g. to obtain the 3nd Tuesday of the receivers month use
|
18
|
+
#
|
19
|
+
# time.nth_wday_in_month(2, 2)
|
20
|
+
def nth_wday_in_month(n, which_wday, for_time = self)
|
21
|
+
first_of_month = for_time.to_ri_cal_property_value.change(:day => 1)
|
22
|
+
first_in_month = first_of_month.advance(:days => (which_wday - first_of_month.wday))
|
23
|
+
first_in_month = first_in_month.advance(:days => 7) if first_in_month.month != first_of_month.month
|
24
|
+
if n > 0
|
25
|
+
first_in_month.advance(:days => (7*(n - 1)))
|
26
|
+
else
|
27
|
+
possible = first_in_month.advance(:days => 21)
|
28
|
+
possible = possible.advance(:days => 7) while possible.month == first_in_month.month
|
29
|
+
last_in_month = possible.advance(:days => - 7)
|
30
|
+
(last_in_month.advance(:days => - (7*(n.abs - 1))))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# A predicate to determine whether or not the receiver falls on a particular weekday of its month.
|
35
|
+
#
|
36
|
+
# == Parameters
|
37
|
+
# n:: the ordinal number being requested
|
38
|
+
# which_wday:: the weekday using Ruby time conventions, i.e. 0 => Sunday, 1 => Monday, ...
|
39
|
+
def nth_wday_in_month?(n, which_wday)
|
40
|
+
target = nth_wday_in_month(n, which_wday)
|
41
|
+
[self.year, self.month, self.day] == [target.year, target.month, target.day]
|
42
|
+
end
|
43
|
+
|
44
|
+
# Return a DateTime which is the beginning of the first day on or before the receiver
|
45
|
+
# with the specified wday
|
46
|
+
def start_of_week_with_wkst(wkst)
|
47
|
+
wkst ||= 1
|
48
|
+
date = ::Date.civil(self.year, self.month, self.day)
|
49
|
+
date -= 1 while date.wday != wkst
|
50
|
+
date
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#- ©2009 Rick DeNatale
|
2
|
+
#- All rights reserved. Refer to the file README.txt for the license
|
3
|
+
#
|
4
|
+
require "ri_cal/core_extensions/time/conversions.rb"
|
5
|
+
require "ri_cal/core_extensions/time/tzid_access.rb"
|
6
|
+
require "ri_cal/core_extensions/time/week_day_predicates.rb"
|
7
|
+
require "ri_cal/core_extensions/time/calculations.rb"
|
8
|
+
|
9
|
+
class Time #:nodoc:
|
10
|
+
include RiCal::CoreExtensions::Time::WeekDayPredicates
|
11
|
+
include RiCal::CoreExtensions::Time::Calculations
|
12
|
+
include RiCal::CoreExtensions::Time::Conversions
|
13
|
+
include RiCal::CoreExtensions::Time::TzidAccess
|
14
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
#- ©2009 Rick DeNatale
|
2
|
+
#- All rights reserved. Refer to the file README.txt for the license
|
3
|
+
#
|
4
|
+
|
5
|
+
require "ri_cal/core_extensions/array.rb"
|
6
|
+
require "ri_cal/core_extensions/date.rb"
|
7
|
+
require "ri_cal/core_extensions/date_time.rb"
|
8
|
+
require "ri_cal/core_extensions/object.rb"
|
9
|
+
require "ri_cal/core_extensions/string.rb"
|
10
|
+
require "ri_cal/core_extensions/time.rb"
|
11
|
+
|