icalendar-recurrence 1.1.3 → 1.2.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 +5 -5
- data/.github/workflows/main.yml +32 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +9 -0
- data/README.md +6 -2
- data/icalendar-recurrence.gemspec +6 -6
- data/lib/icalendar/recurrence/event_extensions.rb +4 -0
- data/lib/icalendar/recurrence/schedule.rb +15 -15
- data/lib/icalendar/recurrence/time_util.rb +23 -8
- data/lib/icalendar/recurrence/version.rb +1 -1
- data/spec/lib/recurrence_spec.rb +57 -2
- data/spec/lib/schedule_spec.rb +6 -0
- data/spec/spec_helper.rb +0 -1
- data/spec/support/fixtures/dst_exdate_event.ics +44 -0
- data/spec/support/fixtures/dst_rdate_event.ics +43 -0
- data/spec/support/fixtures/first_saturday_of_month_event.ics +2 -2
- metadata +38 -35
- data/.travis.yml +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0ae33082e4e2cfe166c0dfa58e2ff01b2833fd40dafa6272d4add3cc48d76381
|
4
|
+
data.tar.gz: e2052acd29e364ddad718774c56d17b43cb7e75e27fd09e73f26a16e0da50e8d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 82818e3411bff13fdb16786d99b875270ad3066ed993ac5cdd31f270c2bb743392dc828c0ec436f5fb0cdb17c1613717498743ed7984e17d4d7a6958c7ec7e4d
|
7
|
+
data.tar.gz: 10be0f14a28212d383643bf9b2ddd65e851079032426dfc5f7ae3f4c2081ec0e08211d1be58d5b57b3e604d7fcc7d98528792cf8b9321ea8f58c8c321ceb45c1
|
@@ -0,0 +1,32 @@
|
|
1
|
+
name: Ruby
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- main
|
7
|
+
- master
|
8
|
+
pull_request:
|
9
|
+
branches:
|
10
|
+
- main
|
11
|
+
- master
|
12
|
+
|
13
|
+
jobs:
|
14
|
+
build:
|
15
|
+
runs-on: ubuntu-latest
|
16
|
+
|
17
|
+
strategy:
|
18
|
+
matrix:
|
19
|
+
ruby:
|
20
|
+
- 3.0.6
|
21
|
+
- 3.1.4
|
22
|
+
- 3.2.2
|
23
|
+
|
24
|
+
steps:
|
25
|
+
- uses: actions/checkout@v4
|
26
|
+
- name: Set up Ruby
|
27
|
+
uses: ruby/setup-ruby@v1
|
28
|
+
with:
|
29
|
+
ruby-version: ${{ matrix.ruby }}
|
30
|
+
bundler-cache: true
|
31
|
+
- name: Run rspec tests
|
32
|
+
run: bundle exec rake spec
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# icalendar-recurrence CHANGELOG
|
2
2
|
|
3
|
+
## 1.2.0 (November 1, 2023)
|
4
|
+
|
5
|
+
- Fix exception date handling across DST boundaries (PR #25)
|
6
|
+
- Add `:parent` to the Occurrence class, to match constructor for Icalendar::Component (PR #23)
|
7
|
+
- Add `Event#all_occurrences` method (PR #28)
|
8
|
+
- Move TZInfo to a runtime dependency (PR #31)
|
9
|
+
- Handle `RDATE` recurrence rules (PR #33)
|
10
|
+
- Use built-in `.utc` method for occurrence time in all cases (PR #35 & #37)
|
11
|
+
|
3
12
|
## 1.1.2 (September 23, 2016)
|
4
13
|
|
5
14
|
- Loosen dependency on ice_cube gem to allow minor upgrades (issue #16)
|
data/README.md
CHANGED
@@ -20,11 +20,15 @@ and run `bundle install` from your shell.
|
|
20
20
|
require 'date' # for parse method
|
21
21
|
require 'icalendar/recurrence'
|
22
22
|
|
23
|
-
calendars = Icalendar.parse(File.read(path_to_ics)) # parse an ICS file
|
23
|
+
calendars = Icalendar::Calendar.parse(File.read(path_to_ics)) # parse an ICS file
|
24
24
|
event = Array(calendars).first.events.first # retrieve the first event
|
25
25
|
event.occurrences_between(Date.parse("2014-01-01"), Date.parse("2014-02-01")) # get all occurrence for one month
|
26
26
|
```
|
27
27
|
|
28
|
+
### Get all occurrences
|
29
|
+
|
30
|
+
To get all occurrences you can use `all_occurrences`. This only works when you have specified an ending using `until` or `count` in your RRULE.
|
31
|
+
|
28
32
|
### Working with occurrences
|
29
33
|
|
30
34
|
An event occurrence is a simple struct object with `start_time` and `end_time` methods.
|
@@ -67,7 +71,7 @@ EOF
|
|
67
71
|
|
68
72
|
# An event that occurs every day, starting January 1, 2014 with one excluded
|
69
73
|
# date. January 28, 2014 will not appear in the occurrences.
|
70
|
-
calendars = Icalendar.parse(ics_string)
|
74
|
+
calendars = Icalendar::Calendar.parse(ics_string)
|
71
75
|
every_day_except_jan_28 = Array(calendars).first.events.first
|
72
76
|
puts "Every day except January 28, 2014, occurrences from 2014-01-01 to 2014-02-01:"
|
73
77
|
puts every_day_except_jan_28.occurrences_between(Date.parse("2014-01-01"), Date.parse("2014-02-01"))
|
@@ -19,13 +19,13 @@ Gem::Specification.new do |spec|
|
|
19
19
|
|
20
20
|
spec.add_runtime_dependency 'icalendar', '~> 2.0'
|
21
21
|
spec.add_runtime_dependency 'ice_cube', '~> 0.16'
|
22
|
+
spec.add_runtime_dependency 'tzinfo', '~> 2.0'
|
22
23
|
|
23
|
-
spec.add_development_dependency 'activesupport', '~>
|
24
|
+
spec.add_development_dependency 'activesupport', '~> 7.1'
|
24
25
|
spec.add_development_dependency 'awesome_print'
|
25
26
|
spec.add_development_dependency 'pry'
|
26
|
-
spec.add_development_dependency 'bundler', '~>
|
27
|
-
spec.add_development_dependency 'rake', '
|
28
|
-
spec.add_development_dependency 'rspec', '~>
|
29
|
-
spec.add_development_dependency 'timecop', '~> 0.
|
30
|
-
spec.add_development_dependency 'tzinfo', '~> 0.3'
|
27
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
28
|
+
spec.add_development_dependency 'rake', '>= 12.3.3'
|
29
|
+
spec.add_development_dependency 'rspec', '~> 3.12'
|
30
|
+
spec.add_development_dependency 'timecop', '~> 0.9'
|
31
31
|
end
|
@@ -2,7 +2,7 @@ require 'ice_cube'
|
|
2
2
|
|
3
3
|
module Icalendar
|
4
4
|
module Recurrence
|
5
|
-
class Occurrence < Struct.new(:start_time, :end_time)
|
5
|
+
class Occurrence < Struct.new(:start_time, :end_time, :parent)
|
6
6
|
end
|
7
7
|
|
8
8
|
class Schedule
|
@@ -49,20 +49,10 @@ module Icalendar
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def convert_ice_cube_occurrence(ice_cube_occurrence)
|
52
|
-
|
53
|
-
|
54
|
-
tz = TZInfo::Timezone.get(timezone)
|
55
|
-
start_time = tz.local_to_utc(ice_cube_occurrence.start_time)
|
56
|
-
end_time = tz.local_to_utc(ice_cube_occurrence.end_time)
|
57
|
-
rescue TZInfo::InvalidTimezoneIdentifier => e
|
58
|
-
warn "Unknown TZID specified in ical event (#{timezone.inspect}), ignoring (will likely cause event to be at wrong time!)"
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
start_time ||= ice_cube_occurrence.start_time
|
63
|
-
end_time ||= ice_cube_occurrence.end_time
|
52
|
+
start_time = ice_cube_occurrence.start_time.utc
|
53
|
+
end_time = ice_cube_occurrence.end_time.utc
|
64
54
|
|
65
|
-
Icalendar::Recurrence::Occurrence.new(start_time, end_time)
|
55
|
+
Icalendar::Recurrence::Occurrence.new(start_time, end_time, @event)
|
66
56
|
end
|
67
57
|
|
68
58
|
def ice_cube_schedule
|
@@ -77,7 +67,17 @@ module Icalendar
|
|
77
67
|
|
78
68
|
event.exdate.each do |exception_date_or_dates|
|
79
69
|
Array(exception_date_or_dates).each do |exception_date|
|
80
|
-
|
70
|
+
# exception times should have the same tz offset as the event start or they'll be ignored as different times
|
71
|
+
# ignored if ActiveSupport::TimeWithZone is available
|
72
|
+
schedule.add_exception_time(TimeUtil.to_time(exception_date, moment: start_time))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
event.rdate.each do |extra_date_or_dates|
|
77
|
+
Array(extra_date_or_dates).each do |extra_date|
|
78
|
+
# exception times should have the same tz offset as the event start or they'll be ignored as different times
|
79
|
+
# ignored if ActiveSupport::TimeWithZone is available
|
80
|
+
schedule.add_recurrence_time(TimeUtil.to_time(extra_date, moment: start_time))
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
@@ -1,11 +1,17 @@
|
|
1
1
|
require 'tzinfo'
|
2
|
+
begin
|
3
|
+
require 'active_support/time'
|
4
|
+
rescue LoadError
|
5
|
+
# that's ok, will just fall back to Time
|
6
|
+
end
|
2
7
|
|
3
8
|
module Icalendar
|
4
9
|
module Recurrence
|
5
10
|
module TimeUtil
|
6
|
-
def datetime_to_time(datetime)
|
11
|
+
def datetime_to_time(datetime, options = {})
|
7
12
|
raise ArgumentError, "Unsupported DateTime object passed (must be Icalendar::Values::DateTime#{datetime.class} passed instead)" unless supported_datetime_object?(datetime)
|
8
|
-
|
13
|
+
options[:moment] ||= datetime.to_date
|
14
|
+
offset = timezone_offset(datetime.ical_params["tzid"], options)
|
9
15
|
offset ||= datetime.strftime("%:z")
|
10
16
|
|
11
17
|
Time.new(datetime.year, datetime.month, datetime.mday, datetime.hour, datetime.min, datetime.sec, offset)
|
@@ -16,11 +22,13 @@ module Icalendar
|
|
16
22
|
Time.new(date.year, date.month, date.mday)
|
17
23
|
end
|
18
24
|
|
19
|
-
def to_time(time_object)
|
25
|
+
def to_time(time_object, options = {})
|
20
26
|
if supported_time_object?(time_object)
|
21
27
|
time_object
|
28
|
+
elsif supported_icalendar_object?(time_object)
|
29
|
+
time_object.value
|
22
30
|
elsif supported_datetime_object?(time_object)
|
23
|
-
datetime_to_time(time_object)
|
31
|
+
datetime_to_time(time_object, options)
|
24
32
|
elsif supported_date_object?(time_object)
|
25
33
|
date_to_time(time_object)
|
26
34
|
elsif time_object.is_a?(String)
|
@@ -41,8 +49,7 @@ module Icalendar
|
|
41
49
|
#
|
42
50
|
def timezone_offset(tzid, options = {})
|
43
51
|
tzid = Array(tzid).first
|
44
|
-
|
45
|
-
moment = options.fetch(:moment)
|
52
|
+
moment = options.fetch(:moment, Time.now)
|
46
53
|
utc_moment = to_time(moment.clone).utc
|
47
54
|
tzid = tzid.to_s.gsub(/^(["'])|(["'])$/, "")
|
48
55
|
utc_offset = TZInfo::Timezone.get(tzid).period_for_utc(utc_moment).utc_total_offset # this seems to work, but I feel like there is a lurking bug
|
@@ -50,7 +57,7 @@ module Icalendar
|
|
50
57
|
hour_offset = "+#{hour_offset}" if hour_offset >= 0
|
51
58
|
match = hour_offset.to_s.match(/(\+|-)(\d+)/)
|
52
59
|
"#{match[1]}#{match[2].rjust(2, "0")}:00"
|
53
|
-
rescue TZInfo::InvalidTimezoneIdentifier
|
60
|
+
rescue TZInfo::InvalidTimezoneIdentifier
|
54
61
|
nil
|
55
62
|
end
|
56
63
|
|
@@ -67,8 +74,16 @@ module Icalendar
|
|
67
74
|
time_object.is_a?(Icalendar::Values::DateTime)
|
68
75
|
end
|
69
76
|
|
77
|
+
def supported_icalendar_object?(time_object)
|
78
|
+
time_object.is_a?(Icalendar::Values::DateTime) && supported_activesupport_object?(time_object.value)
|
79
|
+
end
|
80
|
+
|
70
81
|
def supported_time_object?(time_object)
|
71
|
-
time_object.is_a?(Time)
|
82
|
+
time_object.is_a?(Time) || supported_activesupport_object?(time_object)
|
83
|
+
end
|
84
|
+
|
85
|
+
def supported_activesupport_object?(time_object)
|
86
|
+
defined?(ActiveSupport::TimeWithZone) && time_object.is_a?(ActiveSupport::TimeWithZone)
|
72
87
|
end
|
73
88
|
|
74
89
|
# Replaces the existing offset with one associated with given TZID. Does
|
data/spec/lib/recurrence_spec.rb
CHANGED
@@ -86,6 +86,36 @@ describe "Event#occurrences_between" do
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
+
context "event repeating weekly with exdates" do
|
90
|
+
let(:event) { example_event :dst_exdate }
|
91
|
+
|
92
|
+
it "properly skips christmas and new years" do
|
93
|
+
occurrences = event.occurrences_between(start_time, start_time + 4.months)
|
94
|
+
|
95
|
+
expect(occurrences.length).to eq(14)
|
96
|
+
christmas_day = Date.new 2019, 12, 25
|
97
|
+
expect(occurrences.all? { |o| o.start_time.to_date != christmas_day }).to eq(true)
|
98
|
+
new_years_day = Date.new 2020, 1, 1
|
99
|
+
expect(occurrences.all? { |o| o.start_time.to_date != new_years_day }).to eq(true)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "event repeating weekly with rdates" do
|
104
|
+
let(:event) { example_event :dst_rdate }
|
105
|
+
|
106
|
+
it "properly includes specified rdates" do
|
107
|
+
occurrences = event.occurrences_between(start_time, start_time + 4.months)
|
108
|
+
extra_day_after_period = Date.new 2020, 02, 01
|
109
|
+
occurrence = occurrences.find { |o| o.start_time.to_date == extra_day_after_period }
|
110
|
+
|
111
|
+
expect(occurrences.length).to eq(17)
|
112
|
+
expect(occurrence).to_not be_nil
|
113
|
+
|
114
|
+
expect(occurrence.start_time).to eq(Time.new 2020, 02, 01, 19, 0, 0, "+00:00")
|
115
|
+
expect(occurrence.end_time).to eq(Time.new 2020, 02, 01, 21, 0, 0, "+00:00")
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
89
119
|
context "event repeating yearly" do
|
90
120
|
let(:event) { example_event :first_of_every_year }
|
91
121
|
|
@@ -145,8 +175,8 @@ describe "Event#occurrences_between" do
|
|
145
175
|
occurrences = event.occurrences_between(start_time, start_time + 55.days)
|
146
176
|
|
147
177
|
expected_start_times = [
|
148
|
-
Time.parse("2014-01-04 at
|
149
|
-
Time.parse("2014-02-01 at
|
178
|
+
Time.parse("2014-01-04 at 10am").force_zone("America/Los_Angeles"),
|
179
|
+
Time.parse("2014-02-01 at 10am").force_zone("America/Los_Angeles"),
|
150
180
|
]
|
151
181
|
|
152
182
|
expect(occurrences.length).to eq(2)
|
@@ -174,3 +204,28 @@ describe "Event#occurrences_between" do
|
|
174
204
|
end
|
175
205
|
end
|
176
206
|
end
|
207
|
+
|
208
|
+
describe "Event#all_occurrences" do
|
209
|
+
let(:start_time) { event.start_time }
|
210
|
+
|
211
|
+
context "event repeating once a month for three months" do
|
212
|
+
let(:event) { example_event :one_day_a_month_for_three_months }
|
213
|
+
|
214
|
+
it "get all 3 occurences" do
|
215
|
+
occurrences = event.all_occurrences
|
216
|
+
|
217
|
+
expect(occurrences.length).to eq(3)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
context "event repeating yearly" do
|
222
|
+
let(:event) { example_event :first_of_every_year }
|
223
|
+
|
224
|
+
it "can not get all occurences when not using count or until" do
|
225
|
+
expect {
|
226
|
+
event.all_occurrences
|
227
|
+
}.to raise_error(ArgumentError)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
data/spec/lib/schedule_spec.rb
CHANGED
@@ -21,6 +21,12 @@ describe Icalendar::Recurrence::Schedule do
|
|
21
21
|
expect(occurrences.count).to eq(7)
|
22
22
|
end
|
23
23
|
|
24
|
+
it 'returns object whose event method matches the origin event' do
|
25
|
+
# Simple test to make sure the event carried over; different __id__
|
26
|
+
expect(example_occurrence.parent.custom_properties).to eq example_event(:daily).custom_properties
|
27
|
+
expect(example_occurrence.parent.name).to eq example_event(:daily).name
|
28
|
+
end
|
29
|
+
|
24
30
|
context "timezoned event" do
|
25
31
|
let(:example_occurrence) do
|
26
32
|
timezoned_event = example_event :first_saturday_of_month
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,44 @@
|
|
1
|
+
BEGIN:VCALENDAR
|
2
|
+
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
3
|
+
VERSION:2.0
|
4
|
+
CALSCALE:GREGORIAN
|
5
|
+
METHOD:PUBLISH
|
6
|
+
X-WR-CALNAME:Minimal example
|
7
|
+
X-WR-TIMEZONE:Europe/Berlin
|
8
|
+
X-WR-CALDESC:Example for #221
|
9
|
+
BEGIN:VTIMEZONE
|
10
|
+
TZID:Europe/Berlin
|
11
|
+
X-LIC-LOCATION:Europe/Berlin
|
12
|
+
BEGIN:DAYLIGHT
|
13
|
+
TZOFFSETFROM:+0100
|
14
|
+
TZOFFSETTO:+0200
|
15
|
+
TZNAME:CEST
|
16
|
+
DTSTART:19700329T020000
|
17
|
+
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
|
18
|
+
END:DAYLIGHT
|
19
|
+
BEGIN:STANDARD
|
20
|
+
TZOFFSETFROM:+0200
|
21
|
+
TZOFFSETTO:+0100
|
22
|
+
TZNAME:CET
|
23
|
+
DTSTART:19701025T030000
|
24
|
+
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
|
25
|
+
END:STANDARD
|
26
|
+
END:VTIMEZONE
|
27
|
+
BEGIN:VEVENT
|
28
|
+
DTSTART;TZID=Europe/Berlin:20191016T100000
|
29
|
+
DTEND;TZID=Europe/Berlin:20191016T120000
|
30
|
+
RRULE:FREQ=WEEKLY;WKST=MO;UNTIL=20200129T225959Z;BYDAY=WE
|
31
|
+
EXDATE;TZID=Europe/Berlin:20200101T100000
|
32
|
+
EXDATE;TZID=Europe/Berlin:20191225T100000
|
33
|
+
DTSTAMP:20191121T083508Z
|
34
|
+
UID:01234567890123456789@google.com
|
35
|
+
CREATED:20191001T090000Z
|
36
|
+
DESCRIPTION:This repeating event should not occur on the specified EXDATEs
|
37
|
+
LAST-MODIFIED:20191001T090000Z
|
38
|
+
LOCATION:Room 1
|
39
|
+
SEQUENCE:1
|
40
|
+
STATUS:CONFIRMED
|
41
|
+
SUMMARY:A repeating event
|
42
|
+
TRANSP:OPAQUE
|
43
|
+
END:VEVENT
|
44
|
+
END:VCALENDAR
|
@@ -0,0 +1,43 @@
|
|
1
|
+
BEGIN:VCALENDAR
|
2
|
+
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
3
|
+
VERSION:2.0
|
4
|
+
CALSCALE:GREGORIAN
|
5
|
+
METHOD:PUBLISH
|
6
|
+
X-WR-CALNAME:Minimal example
|
7
|
+
X-WR-TIMEZONE:Europe/Berlin
|
8
|
+
X-WR-CALDESC:Example for #221
|
9
|
+
BEGIN:VTIMEZONE
|
10
|
+
TZID:Europe/Berlin
|
11
|
+
X-LIC-LOCATION:Europe/Berlin
|
12
|
+
BEGIN:DAYLIGHT
|
13
|
+
TZOFFSETFROM:+0100
|
14
|
+
TZOFFSETTO:+0200
|
15
|
+
TZNAME:CEST
|
16
|
+
DTSTART:19700329T020000
|
17
|
+
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
|
18
|
+
END:DAYLIGHT
|
19
|
+
BEGIN:STANDARD
|
20
|
+
TZOFFSETFROM:+0200
|
21
|
+
TZOFFSETTO:+0100
|
22
|
+
TZNAME:CET
|
23
|
+
DTSTART:19701025T030000
|
24
|
+
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
|
25
|
+
END:STANDARD
|
26
|
+
END:VTIMEZONE
|
27
|
+
BEGIN:VEVENT
|
28
|
+
DTSTART;TZID=Europe/Berlin:20191016T100000
|
29
|
+
DTEND;TZID=Europe/Berlin:20191016T120000
|
30
|
+
RRULE:FREQ=WEEKLY;WKST=MO;UNTIL=20200129T225959Z;BYDAY=WE
|
31
|
+
RDATE;TZID=Europe/Berlin:20200201T200000
|
32
|
+
DTSTAMP:20191121T083508Z
|
33
|
+
UID:01234567890123456789@google.com
|
34
|
+
CREATED:20191001T090000Z
|
35
|
+
DESCRIPTION:This repeating event should additionally occur on the specified RDATESs
|
36
|
+
LAST-MODIFIED:20191001T090000Z
|
37
|
+
LOCATION:Room 1
|
38
|
+
SEQUENCE:1
|
39
|
+
STATUS:CONFIRMED
|
40
|
+
SUMMARY:A repeating event
|
41
|
+
TRANSP:OPAQUE
|
42
|
+
END:VEVENT
|
43
|
+
END:VCALENDAR
|
@@ -29,8 +29,8 @@ DESCRIPTION:\nScheduled maintenance \n
|
|
29
29
|
X-MS-OLK-SENDER:mailto:foo@example.ca
|
30
30
|
ORGANIZER;SENT-BY="mailto:foo@example.ca":mailto:itadmin@example.ca
|
31
31
|
X-MS-OLK-SENDER:mailto:foo@example.ca
|
32
|
-
DTSTART;TZID="America/Los_Angeles":
|
33
|
-
DTEND;TZID="America/Los_Angeles":
|
32
|
+
DTSTART;TZID="America/Los_Angeles":20140104T100000
|
33
|
+
DTEND;TZID="America/Los_Angeles":20140104T110000
|
34
34
|
STATUS:CONFIRMED
|
35
35
|
CLASS:PUBLIC
|
36
36
|
X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: icalendar-recurrence
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jordan Raine
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-11-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: icalendar
|
@@ -38,20 +38,34 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.16'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: tzinfo
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: activesupport
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
61
|
+
version: '7.1'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
68
|
+
version: '7.1'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: awesome_print
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,80 +100,66 @@ dependencies:
|
|
86
100
|
requirements:
|
87
101
|
- - "~>"
|
88
102
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
103
|
+
version: '2.0'
|
90
104
|
type: :development
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
108
|
- - "~>"
|
95
109
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
110
|
+
version: '2.0'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: rake
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
|
-
- - "
|
115
|
+
- - ">="
|
102
116
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
117
|
+
version: 12.3.3
|
104
118
|
type: :development
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
107
121
|
requirements:
|
108
|
-
- - "
|
122
|
+
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
124
|
+
version: 12.3.3
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: rspec
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
129
|
- - "~>"
|
116
130
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
131
|
+
version: '3.12'
|
118
132
|
type: :development
|
119
133
|
prerelease: false
|
120
134
|
version_requirements: !ruby/object:Gem::Requirement
|
121
135
|
requirements:
|
122
136
|
- - "~>"
|
123
137
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
138
|
+
version: '3.12'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: timecop
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
143
|
- - "~>"
|
130
144
|
- !ruby/object:Gem::Version
|
131
|
-
version: 0.
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - "~>"
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: 0.6.3
|
139
|
-
- !ruby/object:Gem::Dependency
|
140
|
-
name: tzinfo
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
142
|
-
requirements:
|
143
|
-
- - "~>"
|
144
|
-
- !ruby/object:Gem::Version
|
145
|
-
version: '0.3'
|
145
|
+
version: '0.9'
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version: '0.
|
153
|
-
description:
|
152
|
+
version: '0.9'
|
153
|
+
description:
|
154
154
|
email:
|
155
155
|
- jnraine@gmail.com
|
156
156
|
executables: []
|
157
157
|
extensions: []
|
158
158
|
extra_rdoc_files: []
|
159
159
|
files:
|
160
|
+
- ".github/workflows/main.yml"
|
160
161
|
- ".gitignore"
|
161
162
|
- ".rspec"
|
162
|
-
- ".travis.yml"
|
163
163
|
- CHANGELOG.md
|
164
164
|
- Gemfile
|
165
165
|
- Guardfile
|
@@ -179,6 +179,8 @@ files:
|
|
179
179
|
- spec/lib/time_util_spec.rb
|
180
180
|
- spec/spec_helper.rb
|
181
181
|
- spec/support/fixtures/daily_event.ics
|
182
|
+
- spec/support/fixtures/dst_exdate_event.ics
|
183
|
+
- spec/support/fixtures/dst_rdate_event.ics
|
182
184
|
- spec/support/fixtures/embedded_timezone_event.ics
|
183
185
|
- spec/support/fixtures/every_monday_event.ics
|
184
186
|
- spec/support/fixtures/every_other_day_event.ics
|
@@ -201,7 +203,7 @@ homepage: https://github.com/icalendar/icalendar-recurrence
|
|
201
203
|
licenses:
|
202
204
|
- MIT
|
203
205
|
metadata: {}
|
204
|
-
post_install_message:
|
206
|
+
post_install_message:
|
205
207
|
rdoc_options: []
|
206
208
|
require_paths:
|
207
209
|
- lib
|
@@ -216,9 +218,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
216
218
|
- !ruby/object:Gem::Version
|
217
219
|
version: '0'
|
218
220
|
requirements: []
|
219
|
-
|
220
|
-
|
221
|
-
signing_key:
|
221
|
+
rubygems_version: 3.4.10
|
222
|
+
signing_key:
|
222
223
|
specification_version: 4
|
223
224
|
summary: Provides recurrence to icalendar gem.
|
224
225
|
test_files:
|
@@ -227,6 +228,8 @@ test_files:
|
|
227
228
|
- spec/lib/time_util_spec.rb
|
228
229
|
- spec/spec_helper.rb
|
229
230
|
- spec/support/fixtures/daily_event.ics
|
231
|
+
- spec/support/fixtures/dst_exdate_event.ics
|
232
|
+
- spec/support/fixtures/dst_rdate_event.ics
|
230
233
|
- spec/support/fixtures/embedded_timezone_event.ics
|
231
234
|
- spec/support/fixtures/every_monday_event.ics
|
232
235
|
- spec/support/fixtures/every_other_day_event.ics
|