livecal 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/livecal/parser.rb +3 -3
- data/lib/livecal/recurring_events.rb +4 -2
- data/lib/livecal.rb +2 -2
- metadata +5 -14
- data/.rspec +0 -3
- data/Gemfile +0 -5
- data/Rakefile +0 -8
- data/spec/integration/parsing_spec.rb +0 -308
- data/spec/spec_helper.rb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d2f96adba2d6e1568ea3d5fa26c1e3b22e14d6f5422d90896c0d231f8f67d9b
|
4
|
+
data.tar.gz: a79e0d5596ebe6f011c2a2a37c08890226fe56fddbb6ef5843c451872b123cee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b7e20785fbb7cea46ae843d731be24b665fa651f43561bdbf656e2b15db5038cd369f1af23cc74cc0c3b1489ccffdd1d39649cf71a2086766940537a2a3d0c4
|
7
|
+
data.tar.gz: 5eda9c1782dfa5dd5098d791ed8eac39e70cb39691313d58e2bcb6421d1dbfe280743f1cbaa74b12950788801cbc55c19c4b8f5da483bcb98083d26082ee27b6
|
data/lib/livecal/parser.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "
|
4
|
-
require_relative "
|
5
|
-
require_relative "
|
3
|
+
require_relative "calendar"
|
4
|
+
require_relative "event"
|
5
|
+
require_relative "recurring_events"
|
6
6
|
|
7
7
|
module Livecal
|
8
8
|
class Parser
|
@@ -29,11 +29,13 @@ module Livecal
|
|
29
29
|
attr_reader :source, :from, :to, :changes
|
30
30
|
|
31
31
|
def changed?(instance)
|
32
|
-
changes.any?
|
32
|
+
changes.any? do |change|
|
33
|
+
change.recurrence_id&.value_ical == instance.dtstart.value_ical
|
34
|
+
end
|
33
35
|
end
|
34
36
|
|
35
37
|
def duration
|
36
|
-
@duration ||= source.dtend - source.dtstart
|
38
|
+
@duration ||= source.dtend.to_i - source.dtstart.to_i
|
37
39
|
end
|
38
40
|
|
39
41
|
def instance_with_start(time)
|
data/lib/livecal.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: livecal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pat Allan
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: icalendar
|
@@ -87,25 +87,21 @@ executables: []
|
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
|
-
- ".rspec"
|
91
|
-
- Gemfile
|
92
90
|
- LICENSE.md
|
93
91
|
- README.md
|
94
|
-
- Rakefile
|
95
92
|
- lib/livecal.rb
|
96
93
|
- lib/livecal/calendar.rb
|
97
94
|
- lib/livecal/calendar_source.rb
|
98
95
|
- lib/livecal/event.rb
|
99
96
|
- lib/livecal/parser.rb
|
100
97
|
- lib/livecal/recurring_events.rb
|
101
|
-
- spec/integration/parsing_spec.rb
|
102
|
-
- spec/spec_helper.rb
|
103
98
|
homepage: https://github.com/pat/livecal
|
104
99
|
licenses:
|
105
100
|
- Hippocratic-2.1
|
106
101
|
metadata:
|
107
102
|
homepage_uri: https://github.com/pat/livecal
|
108
103
|
source_code_uri: https://github.com/pat/livecal
|
104
|
+
rubygems_mfa_required: 'true'
|
109
105
|
post_install_message:
|
110
106
|
rdoc_options: []
|
111
107
|
require_paths:
|
@@ -121,13 +117,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
121
117
|
- !ruby/object:Gem::Version
|
122
118
|
version: '0'
|
123
119
|
requirements: []
|
124
|
-
rubygems_version: 3.
|
120
|
+
rubygems_version: 3.5.16
|
125
121
|
signing_key:
|
126
122
|
specification_version: 4
|
127
123
|
summary: Parses ical/ics files into a live calendar
|
128
|
-
test_files:
|
129
|
-
- spec/integration/parsing_spec.rb
|
130
|
-
- spec/spec_helper.rb
|
131
|
-
- ".rspec"
|
132
|
-
- Gemfile
|
133
|
-
- Rakefile
|
124
|
+
test_files: []
|
data/.rspec
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
@@ -1,308 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe "Parsing ical files" do
|
4
|
-
let(:from) { Time.new 2021, 6, 6, 0, 0, 0, tz }
|
5
|
-
let(:to) { Time.new 2021, 6, 7, 0, 0, 0, tz }
|
6
|
-
let(:tz) { "+10:00" }
|
7
|
-
|
8
|
-
context "handles a single event" do
|
9
|
-
let(:source) do
|
10
|
-
<<~ICAL
|
11
|
-
BEGIN:VCALENDAR
|
12
|
-
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
13
|
-
VERSION:2.0
|
14
|
-
CALSCALE:GREGORIAN
|
15
|
-
METHOD:PUBLISH
|
16
|
-
X-WR-CALNAME:livecal
|
17
|
-
X-WR-TIMEZONE:Australia/Melbourne
|
18
|
-
BEGIN:VEVENT
|
19
|
-
DTSTART:20210606T020000Z
|
20
|
-
DTEND:20210606T030000Z
|
21
|
-
DTSTAMP:20210606T013959Z
|
22
|
-
UID:6vc8dul781vckb41vh5avkchi3@google.com
|
23
|
-
CREATED:20210606T013948Z
|
24
|
-
DESCRIPTION:
|
25
|
-
LAST-MODIFIED:20210606T013948Z
|
26
|
-
LOCATION:
|
27
|
-
SEQUENCE:0
|
28
|
-
STATUS:CONFIRMED
|
29
|
-
SUMMARY:Appointment
|
30
|
-
TRANSP:OPAQUE
|
31
|
-
END:VEVENT
|
32
|
-
END:VCALENDAR
|
33
|
-
ICAL
|
34
|
-
end
|
35
|
-
|
36
|
-
it "returns the event if in the requested window" do
|
37
|
-
calendars = Livecal.from_string source, from: from, to: to
|
38
|
-
|
39
|
-
expect(calendars.length).to eq(1)
|
40
|
-
expect(calendars.first.events.length).to eq(1)
|
41
|
-
|
42
|
-
event = calendars.first.events.first
|
43
|
-
|
44
|
-
expect(event.summary).to eq("Appointment")
|
45
|
-
end
|
46
|
-
|
47
|
-
it "returns no events if the event is outside the requested window" do
|
48
|
-
from = Time.new 2021, 6, 7, 0, 0, 0, tz
|
49
|
-
to = Time.new 2021, 6, 7, 23, 0, 0, tz
|
50
|
-
|
51
|
-
calendars = Livecal.from_string source, from: from, to: to
|
52
|
-
|
53
|
-
expect(calendars.length).to eq(1)
|
54
|
-
expect(calendars.first.events).to be_empty
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
context "with recurring events" do
|
59
|
-
let(:source) do
|
60
|
-
<<~ICAL
|
61
|
-
BEGIN:VCALENDAR
|
62
|
-
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
63
|
-
VERSION:2.0
|
64
|
-
CALSCALE:GREGORIAN
|
65
|
-
METHOD:PUBLISH
|
66
|
-
X-WR-CALNAME:livecal
|
67
|
-
X-WR-TIMEZONE:Australia/Melbourne
|
68
|
-
BEGIN:VTIMEZONE
|
69
|
-
TZID:Australia/Melbourne
|
70
|
-
X-LIC-LOCATION:Australia/Melbourne
|
71
|
-
BEGIN:STANDARD
|
72
|
-
TZOFFSETFROM:+1100
|
73
|
-
TZOFFSETTO:+1000
|
74
|
-
TZNAME:AEST
|
75
|
-
DTSTART:19700405T030000
|
76
|
-
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU
|
77
|
-
END:STANDARD
|
78
|
-
BEGIN:DAYLIGHT
|
79
|
-
TZOFFSETFROM:+1000
|
80
|
-
TZOFFSETTO:+1100
|
81
|
-
TZNAME:AEDT
|
82
|
-
DTSTART:19701004T020000
|
83
|
-
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=1SU
|
84
|
-
END:DAYLIGHT
|
85
|
-
END:VTIMEZONE
|
86
|
-
BEGIN:VEVENT
|
87
|
-
DTSTART;TZID=Australia/Melbourne:20210606T120000
|
88
|
-
DTEND;TZID=Australia/Melbourne:20210606T130000
|
89
|
-
RRULE:FREQ=WEEKLY;BYDAY=SU
|
90
|
-
DTSTAMP:20210606T015535Z
|
91
|
-
UID:6vc8dul781vckb41vh5avkchi3@google.com
|
92
|
-
CREATED:20210606T013948Z
|
93
|
-
DESCRIPTION:
|
94
|
-
LAST-MODIFIED:20210606T015524Z
|
95
|
-
LOCATION:
|
96
|
-
SEQUENCE:1
|
97
|
-
STATUS:CONFIRMED
|
98
|
-
SUMMARY:Appointment
|
99
|
-
TRANSP:OPAQUE
|
100
|
-
END:VEVENT
|
101
|
-
END:VCALENDAR
|
102
|
-
ICAL
|
103
|
-
end
|
104
|
-
|
105
|
-
it "returns the events in the requested window" do
|
106
|
-
from = Time.new 2021, 6, 6, 0, 0, 0, tz
|
107
|
-
to = Time.new 2021, 6, 14, 0, 0, 0, tz
|
108
|
-
calendars = Livecal.from_string source, from: from, to: to
|
109
|
-
|
110
|
-
expect(calendars.length).to eq(1)
|
111
|
-
expect(calendars.first.events.length).to eq(2)
|
112
|
-
|
113
|
-
first, second = calendars.first.events.to_a
|
114
|
-
|
115
|
-
expect(first.summary).to eq("Appointment")
|
116
|
-
expect(first.starts_at).to eq(Time.new(2021, 6, 6, 12, 0, 0, tz))
|
117
|
-
expect(first.ends_at).to eq(Time.new(2021, 6, 6, 13, 0, 0, tz))
|
118
|
-
|
119
|
-
expect(second.summary).to eq("Appointment")
|
120
|
-
expect(second.starts_at).to eq(Time.new(2021, 6, 13, 12, 0, 0, tz))
|
121
|
-
expect(second.ends_at).to eq(Time.new(2021, 6, 13, 13, 0, 0, tz))
|
122
|
-
end
|
123
|
-
|
124
|
-
it "includes events when the initial instance is outside the window" do
|
125
|
-
from = Time.new 2021, 6, 13, 0, 0, 0, tz
|
126
|
-
to = Time.new 2021, 6, 14, 0, 0, 0, tz
|
127
|
-
calendars = Livecal.from_string source, from: from, to: to
|
128
|
-
|
129
|
-
expect(calendars.length).to eq(1)
|
130
|
-
expect(calendars.first.events.length).to eq(1)
|
131
|
-
|
132
|
-
event = calendars.first.events.first
|
133
|
-
|
134
|
-
expect(event.summary).to eq("Appointment")
|
135
|
-
expect(event.starts_at).to eq(Time.new(2021, 6, 13, 12, 0, 0, tz))
|
136
|
-
expect(event.ends_at).to eq(Time.new(2021, 6, 13, 13, 0, 0, tz))
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
context "recurring events with exclusions" do
|
141
|
-
let(:source) do
|
142
|
-
<<~ICAL
|
143
|
-
BEGIN:VCALENDAR
|
144
|
-
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
145
|
-
VERSION:2.0
|
146
|
-
CALSCALE:GREGORIAN
|
147
|
-
METHOD:PUBLISH
|
148
|
-
X-WR-CALNAME:livecal
|
149
|
-
X-WR-TIMEZONE:Australia/Melbourne
|
150
|
-
BEGIN:VTIMEZONE
|
151
|
-
TZID:Australia/Melbourne
|
152
|
-
X-LIC-LOCATION:Australia/Melbourne
|
153
|
-
BEGIN:STANDARD
|
154
|
-
TZOFFSETFROM:+1100
|
155
|
-
TZOFFSETTO:+1000
|
156
|
-
TZNAME:AEST
|
157
|
-
DTSTART:19700405T030000
|
158
|
-
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU
|
159
|
-
END:STANDARD
|
160
|
-
BEGIN:DAYLIGHT
|
161
|
-
TZOFFSETFROM:+1000
|
162
|
-
TZOFFSETTO:+1100
|
163
|
-
TZNAME:AEDT
|
164
|
-
DTSTART:19701004T020000
|
165
|
-
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=1SU
|
166
|
-
END:DAYLIGHT
|
167
|
-
END:VTIMEZONE
|
168
|
-
BEGIN:VEVENT
|
169
|
-
DTSTART;TZID=Australia/Melbourne:20210606T120000
|
170
|
-
DTEND;TZID=Australia/Melbourne:20210606T130000
|
171
|
-
RRULE:FREQ=WEEKLY;BYDAY=SU
|
172
|
-
EXDATE;TZID=Australia/Melbourne:20210613T120000
|
173
|
-
DTSTAMP:20210606T031826Z
|
174
|
-
UID:6vc8dul781vckb41vh5avkchi3@google.com
|
175
|
-
CREATED:20210606T013948Z
|
176
|
-
DESCRIPTION:
|
177
|
-
LAST-MODIFIED:20210606T015524Z
|
178
|
-
LOCATION:
|
179
|
-
SEQUENCE:1
|
180
|
-
STATUS:CONFIRMED
|
181
|
-
SUMMARY:Appointment
|
182
|
-
TRANSP:OPAQUE
|
183
|
-
END:VEVENT
|
184
|
-
END:VCALENDAR
|
185
|
-
ICAL
|
186
|
-
end
|
187
|
-
|
188
|
-
it "returns the events in the requested window" do
|
189
|
-
from = Time.new 2021, 6, 6, 0, 0, 0, tz
|
190
|
-
to = Time.new 2021, 6, 21, 0, 0, 0, tz
|
191
|
-
calendars = Livecal.from_string source, from: from, to: to
|
192
|
-
|
193
|
-
expect(calendars.length).to eq(1)
|
194
|
-
expect(calendars.first.events.length).to eq(2)
|
195
|
-
|
196
|
-
first, second = calendars.first.events.to_a
|
197
|
-
|
198
|
-
expect(first.summary).to eq("Appointment")
|
199
|
-
expect(first.starts_at).to eq(Time.new(2021, 6, 6, 12, 0, 0, tz))
|
200
|
-
expect(first.ends_at).to eq(Time.new(2021, 6, 6, 13, 0, 0, tz))
|
201
|
-
|
202
|
-
expect(second.summary).to eq("Appointment")
|
203
|
-
expect(second.starts_at).to eq(Time.new(2021, 6, 20, 12, 0, 0, tz))
|
204
|
-
expect(second.ends_at).to eq(Time.new(2021, 6, 20, 13, 0, 0, tz))
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
context "recurring events with changes" do
|
209
|
-
let(:source) do
|
210
|
-
<<~ICAL
|
211
|
-
BEGIN:VCALENDAR
|
212
|
-
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
213
|
-
VERSION:2.0
|
214
|
-
CALSCALE:GREGORIAN
|
215
|
-
METHOD:PUBLISH
|
216
|
-
X-WR-CALNAME:livecal
|
217
|
-
X-WR-TIMEZONE:Australia/Melbourne
|
218
|
-
BEGIN:VTIMEZONE
|
219
|
-
TZID:Australia/Melbourne
|
220
|
-
X-LIC-LOCATION:Australia/Melbourne
|
221
|
-
BEGIN:STANDARD
|
222
|
-
TZOFFSETFROM:+1100
|
223
|
-
TZOFFSETTO:+1000
|
224
|
-
TZNAME:AEST
|
225
|
-
DTSTART:19700405T030000
|
226
|
-
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU
|
227
|
-
END:STANDARD
|
228
|
-
BEGIN:DAYLIGHT
|
229
|
-
TZOFFSETFROM:+1000
|
230
|
-
TZOFFSETTO:+1100
|
231
|
-
TZNAME:AEDT
|
232
|
-
DTSTART:19701004T020000
|
233
|
-
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=1SU
|
234
|
-
END:DAYLIGHT
|
235
|
-
END:VTIMEZONE
|
236
|
-
BEGIN:VEVENT
|
237
|
-
DTSTART;TZID=Australia/Melbourne:20210606T120000
|
238
|
-
DTEND;TZID=Australia/Melbourne:20210606T130000
|
239
|
-
RRULE:FREQ=WEEKLY;BYDAY=SU
|
240
|
-
DTSTAMP:20210606T032058Z
|
241
|
-
UID:60oght30b0avdekvlsg2bkfi7p@google.com
|
242
|
-
CREATED:20210606T032036Z
|
243
|
-
DESCRIPTION:
|
244
|
-
LAST-MODIFIED:20210606T032036Z
|
245
|
-
LOCATION:
|
246
|
-
SEQUENCE:0
|
247
|
-
STATUS:CONFIRMED
|
248
|
-
SUMMARY:Appointment
|
249
|
-
TRANSP:OPAQUE
|
250
|
-
END:VEVENT
|
251
|
-
BEGIN:VEVENT
|
252
|
-
DTSTART;TZID=Australia/Melbourne:20210614T130000
|
253
|
-
DTEND;TZID=Australia/Melbourne:20210614T140000
|
254
|
-
DTSTAMP:20210606T032058Z
|
255
|
-
UID:60oght30b0avdekvlsg2bkfi7p@google.com
|
256
|
-
RECURRENCE-ID;TZID=Australia/Melbourne:20210613T120000
|
257
|
-
CREATED:20210606T032036Z
|
258
|
-
DESCRIPTION:
|
259
|
-
LAST-MODIFIED:20210606T032050Z
|
260
|
-
LOCATION:
|
261
|
-
SEQUENCE:1
|
262
|
-
STATUS:CONFIRMED
|
263
|
-
SUMMARY:Appointment
|
264
|
-
TRANSP:OPAQUE
|
265
|
-
END:VEVENT
|
266
|
-
END:VCALENDAR
|
267
|
-
ICAL
|
268
|
-
end
|
269
|
-
|
270
|
-
it "returns the events in the requested window" do
|
271
|
-
from = Time.new 2021, 6, 6, 0, 0, 0, tz
|
272
|
-
to = Time.new 2021, 6, 21, 0, 0, 0, tz
|
273
|
-
calendars = Livecal.from_string source, from: from, to: to
|
274
|
-
|
275
|
-
expect(calendars.length).to eq(1)
|
276
|
-
expect(calendars.first.events.length).to eq(3)
|
277
|
-
|
278
|
-
first, second, third = calendars.first.events.to_a
|
279
|
-
|
280
|
-
expect(first.summary).to eq("Appointment")
|
281
|
-
expect(first.starts_at).to eq(Time.new(2021, 6, 6, 12, 0, 0, tz))
|
282
|
-
expect(first.ends_at).to eq(Time.new(2021, 6, 6, 13, 0, 0, tz))
|
283
|
-
|
284
|
-
expect(second.summary).to eq("Appointment")
|
285
|
-
expect(second.starts_at).to eq(Time.new(2021, 6, 14, 13, 0, 0, tz))
|
286
|
-
expect(second.ends_at).to eq(Time.new(2021, 6, 14, 14, 0, 0, tz))
|
287
|
-
|
288
|
-
expect(third.summary).to eq("Appointment")
|
289
|
-
expect(third.starts_at).to eq(Time.new(2021, 6, 20, 12, 0, 0, tz))
|
290
|
-
expect(third.ends_at).to eq(Time.new(2021, 6, 20, 13, 0, 0, tz))
|
291
|
-
end
|
292
|
-
|
293
|
-
it "factors in changes outside the requested window" do
|
294
|
-
from = Time.new 2021, 6, 6, 0, 0, 0, tz
|
295
|
-
to = Time.new 2021, 6, 13, 0, 0, 0, tz
|
296
|
-
calendars = Livecal.from_string source, from: from, to: to
|
297
|
-
|
298
|
-
expect(calendars.length).to eq(1)
|
299
|
-
expect(calendars.first.events.length).to eq(1)
|
300
|
-
|
301
|
-
event = calendars.first.events.first
|
302
|
-
|
303
|
-
expect(event.summary).to eq("Appointment")
|
304
|
-
expect(event.starts_at).to eq(Time.new(2021, 6, 6, 12, 0, 0, tz))
|
305
|
-
expect(event.ends_at).to eq(Time.new(2021, 6, 6, 13, 0, 0, tz))
|
306
|
-
end
|
307
|
-
end
|
308
|
-
end
|