vpim2 0.0.1
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/CHANGES +504 -0
- data/COPYING +58 -0
- data/README +182 -0
- data/lib/atom.rb +728 -0
- data/lib/plist.rb +22 -0
- data/lib/vpim.rb +13 -0
- data/lib/vpim/address.rb +219 -0
- data/lib/vpim/attachment.rb +102 -0
- data/lib/vpim/date.rb +222 -0
- data/lib/vpim/dirinfo.rb +277 -0
- data/lib/vpim/duration.rb +119 -0
- data/lib/vpim/enumerator.rb +32 -0
- data/lib/vpim/field.rb +614 -0
- data/lib/vpim/icalendar.rb +381 -0
- data/lib/vpim/maker/vcard.rb +16 -0
- data/lib/vpim/property/base.rb +193 -0
- data/lib/vpim/property/common.rb +315 -0
- data/lib/vpim/property/location.rb +38 -0
- data/lib/vpim/property/priority.rb +43 -0
- data/lib/vpim/property/recurrence.rb +69 -0
- data/lib/vpim/property/resources.rb +24 -0
- data/lib/vpim/repo.rb +181 -0
- data/lib/vpim/rfc2425.rb +367 -0
- data/lib/vpim/rrule.rb +591 -0
- data/lib/vpim/vcard.rb +1430 -0
- data/lib/vpim/version.rb +18 -0
- data/lib/vpim/vevent.rb +187 -0
- data/lib/vpim/view.rb +90 -0
- data/lib/vpim/vjournal.rb +58 -0
- data/lib/vpim/vpim.rb +65 -0
- data/lib/vpim/vtodo.rb +103 -0
- data/samples/README.mutt +93 -0
- data/samples/ab-query.rb +57 -0
- data/samples/cmd-itip.rb +156 -0
- data/samples/ex_cpvcard.rb +55 -0
- data/samples/ex_get_vcard_photo.rb +22 -0
- data/samples/ex_mkv21vcard.rb +34 -0
- data/samples/ex_mkvcard.rb +64 -0
- data/samples/ex_mkyourown.rb +29 -0
- data/samples/ics-dump.rb +210 -0
- data/samples/ics-to-rss.rb +84 -0
- data/samples/mutt-aliases-to-vcf.rb +45 -0
- data/samples/osx-wrappers.rb +86 -0
- data/samples/reminder.rb +203 -0
- data/samples/rrule.rb +71 -0
- data/samples/tabbed-file-to-vcf.rb +390 -0
- data/samples/vcf-dump.rb +86 -0
- data/samples/vcf-lines.rb +61 -0
- data/samples/vcf-to-ics.rb +22 -0
- data/samples/vcf-to-mutt.rb +121 -0
- data/test/test_all.rb +17 -0
- data/test/test_date.rb +120 -0
- data/test/test_dur.rb +41 -0
- data/test/test_field.rb +156 -0
- data/test/test_ical.rb +415 -0
- data/test/test_repo.rb +158 -0
- data/test/test_rrule.rb +1030 -0
- data/test/test_vcard.rb +973 -0
- data/test/test_view.rb +79 -0
- metadata +117 -0
data/test/test_repo.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'vpim/repo'
|
4
|
+
require 'vpim/agent/calendars'
|
5
|
+
require 'test/unit'
|
6
|
+
|
7
|
+
require 'pp'
|
8
|
+
|
9
|
+
module Enumerable
|
10
|
+
def count
|
11
|
+
self.inject(0){|i,_| i + 1}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class TestRepo < Test::Unit::TestCase
|
16
|
+
Apple3 = Vpim::Repo::Apple3
|
17
|
+
Directory = Vpim::Repo::Directory
|
18
|
+
Agent = Vpim::Agent
|
19
|
+
Path = Agent::Path
|
20
|
+
NotFound = Agent::NotFound
|
21
|
+
|
22
|
+
def setup
|
23
|
+
@testdir = Dir.getwd + "/test" #File.dirname($0) doesn't work with rcov :-(
|
24
|
+
@caldir = @testdir + "/calendars"
|
25
|
+
@eventsz = Dir[@caldir + "/**/*.ics"].size
|
26
|
+
assert(@testdir)
|
27
|
+
assert(test(?d, @caldir), "no caldir "+@caldir)
|
28
|
+
end
|
29
|
+
|
30
|
+
def _test_each(repo, eventsz)
|
31
|
+
repo.each do |cal|
|
32
|
+
assert_equal(eventsz, cal.events.count, cal.name)
|
33
|
+
assert("", File.extname(cal.name))
|
34
|
+
assert_equal(cal.displayed, true)
|
35
|
+
cal.events do |c|
|
36
|
+
assert_instance_of(Vpim::Icalendar::Vevent, c)
|
37
|
+
end
|
38
|
+
cal.events.each do |c|
|
39
|
+
assert_instance_of(Vpim::Icalendar::Vevent, c)
|
40
|
+
end
|
41
|
+
assert_equal(0, cal.todos.count)
|
42
|
+
assert(cal.encode)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_apple3
|
47
|
+
repo = Apple3.new(@caldir)
|
48
|
+
|
49
|
+
assert_equal(1, repo.count)
|
50
|
+
|
51
|
+
_test_each(repo, @eventsz)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_dir
|
55
|
+
assert(test(?d, @caldir))
|
56
|
+
|
57
|
+
repo = Directory.new(@caldir)
|
58
|
+
|
59
|
+
assert_equal(@eventsz, repo.count)
|
60
|
+
|
61
|
+
_test_each(repo, 1)
|
62
|
+
end
|
63
|
+
|
64
|
+
def assert_is_text_calendar(text)
|
65
|
+
lines = text.split("\n")
|
66
|
+
lines = lines.first, lines.last
|
67
|
+
assert_equal("BEGIN:VCALENDAR", lines.first.upcase, lines)
|
68
|
+
assert_equal("END:VCALENDAR", lines.last.upcase, lines)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_agent_calendars
|
72
|
+
repo = Apple3.new(@caldir)
|
73
|
+
rest = Agent::Calendars.new(repo)
|
74
|
+
|
75
|
+
out1, form = rest.get(Path.new("http://host/here", "/here"))
|
76
|
+
assert_equal("text/html", form)
|
77
|
+
#puts(out1)
|
78
|
+
|
79
|
+
out1, form = rest.get(Path.new("http://host/here/weather%2fLeavenworth", "/here"))
|
80
|
+
assert_equal("text/html", form)
|
81
|
+
#puts(out1)
|
82
|
+
|
83
|
+
out2, form = rest.get(Path.new("http://host/here/weather%2fLeavenworth/calendar", "/here"))
|
84
|
+
assert_equal("text/calendar", form)
|
85
|
+
assert_is_text_calendar(out2)
|
86
|
+
|
87
|
+
#assert_equal(out1, out2)
|
88
|
+
|
89
|
+
assert_raise(Vpim::Agent::NotFound) do
|
90
|
+
rest.get(Path.new("http://host/here/weather%2fLeavenworth/an_unknown_protocol", "/here"))
|
91
|
+
end
|
92
|
+
assert_raise(Vpim::Agent::NotFound) do
|
93
|
+
rest.get(Path.new("http://host/here/no_such_calendar", "/here"))
|
94
|
+
end
|
95
|
+
|
96
|
+
assert_equal(["","/","/"], Vpim::Agent::Path.split_path("/%2F/%2F"))
|
97
|
+
assert_equal(["/","/"], Vpim::Agent::Path.split_path("%2F/%2F"))
|
98
|
+
assert_equal(["calendars", "weather/Leavenworth"],
|
99
|
+
Vpim::Agent::Path.split_path("calendars/weather%2FLeavenworth"))
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_agent_calendar_atom
|
103
|
+
repo = Apple3.new(@caldir)
|
104
|
+
rest = Agent::Calendars.new(repo)
|
105
|
+
|
106
|
+
out, form = rest.get(Path.new("http://host/here/weather%2fLeavenworth/atom", "/here"))
|
107
|
+
assert_equal("application/atom+xml", form)
|
108
|
+
#pp out
|
109
|
+
#assert_is_atom(out)
|
110
|
+
end
|
111
|
+
|
112
|
+
def _test_path_shift(url, shifts)
|
113
|
+
# last shift should be a nil
|
114
|
+
shifts << nil
|
115
|
+
|
116
|
+
# presence or absence of a trailing / should not affect shifting
|
117
|
+
["", "/"].each do |trailer|
|
118
|
+
path = Path.new(url + trailer)
|
119
|
+
shifts.each do |_|
|
120
|
+
assert_equal(_, path.shift)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_path_shift
|
126
|
+
_test_path_shift("http://host.ex", [])
|
127
|
+
_test_path_shift("http://host.ex/a", ["a"])
|
128
|
+
_test_path_shift("http://host.ex/a/b", ["a", "b"])
|
129
|
+
_test_path_shift("http://host.ex/a/b/c", ["a", "b", "c"])
|
130
|
+
end
|
131
|
+
|
132
|
+
def _test_path_prefix(base, parts, shifts, prefix)
|
133
|
+
path = Path.new(base+parts.join("/"))
|
134
|
+
shifts.times{ path.shift }
|
135
|
+
assert_equal(prefix, path.prefix)
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_path_prefix
|
139
|
+
_test_path_prefix("http://host.ex/", [], 0, "/")
|
140
|
+
_test_path_prefix("http://host.ex/", ["a"], 0, "/")
|
141
|
+
_test_path_prefix("http://host.ex/", ["a"], 1, "/")
|
142
|
+
_test_path_prefix("http://host.ex/", ["a"], 2, "/a/")
|
143
|
+
_test_path_prefix("http://host.ex/", ["a"], 3, "/a/")
|
144
|
+
_test_path_prefix("http://host.ex/", ["a", "b"], 0, "/")
|
145
|
+
_test_path_prefix("http://host.ex/", ["a", "b"], 1, "/")
|
146
|
+
_test_path_prefix("http://host.ex/", ["a", "b"], 2, "/a/")
|
147
|
+
_test_path_prefix("http://host.ex/", ["a", "b"], 3, "/a/b/")
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_atomize
|
151
|
+
repo = Apple3.new(@caldir)
|
152
|
+
cal = repo.find{true}
|
153
|
+
a = Vpim::Agent::Atomize.new(cal)
|
154
|
+
assert( a.get(Path.new("http://example.com/path")))
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
data/test/test_rrule.rb
ADDED
@@ -0,0 +1,1030 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
ENV['TZ'] = 'EST5EDT'
|
4
|
+
|
5
|
+
require 'vpim/rrule'
|
6
|
+
require 'vpim/icalendar'
|
7
|
+
require 'test/unit'
|
8
|
+
|
9
|
+
require 'pp'
|
10
|
+
|
11
|
+
=begin
|
12
|
+
class Date
|
13
|
+
alias :inspect :to_s
|
14
|
+
end
|
15
|
+
=end
|
16
|
+
|
17
|
+
class TestRrule < Test::Unit::TestCase
|
18
|
+
Rrule = Vpim::Rrule
|
19
|
+
|
20
|
+
#=begin
|
21
|
+
# Comment out these if you want printing!
|
22
|
+
def puts(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def pp(*args)
|
26
|
+
end
|
27
|
+
#=end
|
28
|
+
def parse_vec(vec)
|
29
|
+
pp vec
|
30
|
+
vec = vec.gsub(/.*#.*\(/, '(')
|
31
|
+
pp vec
|
32
|
+
vec = vec.split("\n")
|
33
|
+
pp vec
|
34
|
+
ovec = []
|
35
|
+
|
36
|
+
vec.each do |v|
|
37
|
+
time = v[0,18]
|
38
|
+
dates = v[18,v.length - 18]
|
39
|
+
|
40
|
+
pp time
|
41
|
+
pp dates
|
42
|
+
|
43
|
+
time.gsub!(/\((\d\d\d\d) (\d):/) { "(#{$1} 0#{$2}:" }
|
44
|
+
dates.split(';').each do |mondays|
|
45
|
+
mon, days = mondays.split(' ')
|
46
|
+
|
47
|
+
# debug mon
|
48
|
+
# debug days
|
49
|
+
days.split(',').each do |d|
|
50
|
+
# debug d
|
51
|
+
r = d.split '-'
|
52
|
+
# debug r
|
53
|
+
case r.length
|
54
|
+
when 1 then r = [ r[0].to_i ]
|
55
|
+
when 2 then r = r[0].to_i .. r[1].to_i
|
56
|
+
else
|
57
|
+
raise "don't grok #{d}"
|
58
|
+
end
|
59
|
+
r.each do |d0|
|
60
|
+
# debug time, mon, d, d0
|
61
|
+
ovec << sprintf("%s%s %.2d", time, mon, d0)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
ovec
|
68
|
+
end
|
69
|
+
|
70
|
+
def Test(rule, dtstart = nil, expected = nil)
|
71
|
+
puts "---> #{rule}"
|
72
|
+
puts " #{dtstart}" if dtstart
|
73
|
+
|
74
|
+
expected = parse_vec(expected)
|
75
|
+
|
76
|
+
pp expected.length
|
77
|
+
|
78
|
+
start = Time.now
|
79
|
+
|
80
|
+
if dtstart
|
81
|
+
start = Vpim::Rrule.time_from_rfc2425(dtstart)
|
82
|
+
end
|
83
|
+
|
84
|
+
rrule = Vpim::Rrule.new(start, rule)
|
85
|
+
|
86
|
+
# debug rrule
|
87
|
+
|
88
|
+
# count = 1
|
89
|
+
# rrule.each do |t|
|
90
|
+
# puts format("count=%3d %s", count, t.to_s)
|
91
|
+
# count += 1
|
92
|
+
# end
|
93
|
+
|
94
|
+
got = rrule.map { |t|
|
95
|
+
t.strftime("(%Y %I:%M %p %Z)%B %d")
|
96
|
+
}
|
97
|
+
|
98
|
+
if expected && got != expected
|
99
|
+
puts "length: got=#{got.length} expected=#{expected.length}"
|
100
|
+
(0..expected.length).each do |i|
|
101
|
+
if(got[i] != expected[i])
|
102
|
+
puts sprintf("%d: %34s %s %s", i, got[i], got[i] == expected[i] ? '==' : '!=', expected[i])
|
103
|
+
end
|
104
|
+
end
|
105
|
+
#p got
|
106
|
+
#p expected
|
107
|
+
end
|
108
|
+
assert_equal(expected, got)
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_rfc2445_examples_daily
|
112
|
+
|
113
|
+
# Daily for 10 occurrences:
|
114
|
+
#
|
115
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
116
|
+
# RRULE:FREQ=DAILY;COUNT=10
|
117
|
+
#
|
118
|
+
# ==> (1997 9:00 AM EDT)September 2-11
|
119
|
+
|
120
|
+
Test(
|
121
|
+
'FREQ=DAILY;COUNT=10',
|
122
|
+
'19970902T090000',
|
123
|
+
<<VEC
|
124
|
+
# ==> (1997 9:00 AM EDT)September 2-11
|
125
|
+
VEC
|
126
|
+
)
|
127
|
+
|
128
|
+
# Daily until December 24, 1997:
|
129
|
+
#
|
130
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
131
|
+
# RRULE:FREQ=DAILY;UNTIL=19971224T000000Z
|
132
|
+
#
|
133
|
+
# ==> (1997 9:00 AM EDT)September 2-30;October 1-25
|
134
|
+
# (1997 9:00 AM EST)October 26-31;November 1-30;December 1-23
|
135
|
+
|
136
|
+
Test(
|
137
|
+
'FREQ=DAILY;UNTIL=19971224T000000Z',
|
138
|
+
'19970902T090000',
|
139
|
+
<<VEC
|
140
|
+
# ==> (1997 9:00 AM EDT)September 2-30;October 1-25
|
141
|
+
# (1997 9:00 AM EST)October 26-31;November 1-30;December 1-23
|
142
|
+
VEC
|
143
|
+
);
|
144
|
+
|
145
|
+
# Every other day - forever:
|
146
|
+
#
|
147
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
148
|
+
# RRULE:FREQ=DAILY;INTERVAL=2
|
149
|
+
# ==> (1997 9:00 AM EDT)September2,4,6,8...24,26,28,30;
|
150
|
+
# October 2,4,6...20,22,24
|
151
|
+
# (1997 9:00 AM EST)October 26,28,30;November 1,3,5,7...25,27,29;
|
152
|
+
# Dec 1,3,...
|
153
|
+
|
154
|
+
Test(
|
155
|
+
'FREQ=DAILY;INTERVAL=2;count=27',
|
156
|
+
'19970902T090000',
|
157
|
+
<<VEC
|
158
|
+
# ==> (1997 9:00 AM EDT)September 2,4,6,8,10,12,14,16,18,20,22,24,26,28,30;October 2,4,6,8,10,12,14,16,18,20,22,24
|
159
|
+
VEC
|
160
|
+
)
|
161
|
+
|
162
|
+
# Every 10 days, 5 occurrences:
|
163
|
+
#
|
164
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
165
|
+
# RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5
|
166
|
+
#
|
167
|
+
# ==> (1997 9:00 AM EDT)September 2,12,22;October 2,12
|
168
|
+
|
169
|
+
Test(
|
170
|
+
'FREQ=DAILY;COUNT=5;Interval=10',
|
171
|
+
'19970902T090000',
|
172
|
+
<<VEC
|
173
|
+
# ==> (1997 9:00 AM EDT)September 2,12,22;October 2,12
|
174
|
+
VEC
|
175
|
+
)
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_rfc2445_examples_yearly
|
180
|
+
#
|
181
|
+
# Everyday in January, for 3 years:
|
182
|
+
#
|
183
|
+
# DTSTART;TZID=US-Eastern:19980101T090000
|
184
|
+
# RRULE:FREQ=YEARLY;UNTIL=20000131T090000Z;
|
185
|
+
# BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA
|
186
|
+
# or
|
187
|
+
# RRULE:FREQ=DAILY;UNTIL=20000131T090000Z;BYMONTH=1
|
188
|
+
#
|
189
|
+
# ==> (1998 9:00 AM EDT)January 1-31
|
190
|
+
# (1999 9:00 AM EDT)January 1-31
|
191
|
+
# (2000 9:00 AM EDT)January 1-31
|
192
|
+
|
193
|
+
# FIXME -
|
194
|
+
# I believe the UNTIL time, being in UTC, is BEFORE (2000 9:00 AM
|
195
|
+
# EDT)January 31 , so the last date in the result vector is not valid.
|
196
|
+
#
|
197
|
+
# Also, January is in EST, not EDT!
|
198
|
+
|
199
|
+
Test(
|
200
|
+
'FREQ=YEARLY;UNTIL=20000131T090000Z;BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA',
|
201
|
+
'19980101T090000',
|
202
|
+
<<VEC
|
203
|
+
# ==> (1998 9:00 AM EST)January 1-31
|
204
|
+
# (1999 9:00 AM EST)January 1-31
|
205
|
+
# (2000 9:00 AM EST)January 1-30
|
206
|
+
VEC
|
207
|
+
)
|
208
|
+
|
209
|
+
Test(
|
210
|
+
'FREQ=DAILY;UNTIL=20000131T090000Z;BYMONTH=1',
|
211
|
+
'19980101T090000',
|
212
|
+
<<VEC
|
213
|
+
# ==> (1998 9:00 AM EST)January 1-31
|
214
|
+
# (1999 9:00 AM EST)January 1-31
|
215
|
+
# (2000 9:00 AM EST)January 1-30
|
216
|
+
VEC
|
217
|
+
)
|
218
|
+
end
|
219
|
+
|
220
|
+
def test_rfc2445_examples_weekly_for_10_occurrences
|
221
|
+
# Weekly for 10 occurrences
|
222
|
+
#
|
223
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
224
|
+
# RRULE:FREQ=WEEKLY;COUNT=10
|
225
|
+
#
|
226
|
+
# ==> (1997 9:00 AM EDT)September 2,9,16,23,30;October 7,14,21
|
227
|
+
# (1997 9:00 AM EST)October 28;November 4
|
228
|
+
|
229
|
+
Test(
|
230
|
+
'FREQ=WEEKLY;COUNT=10',
|
231
|
+
'19970902T090000',
|
232
|
+
<<VEC
|
233
|
+
# ==> (1997 9:00 AM EDT)September 2,9,16,23,30;October 7,14,21
|
234
|
+
# (1997 9:00 AM EST)October 28;November 4
|
235
|
+
VEC
|
236
|
+
)
|
237
|
+
end
|
238
|
+
|
239
|
+
def test_rfc2445_examples_weekly_until_dec24_1997
|
240
|
+
# Weekly until December 24, 1997
|
241
|
+
#
|
242
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
243
|
+
# RRULE:FREQ=WEEKLY;UNTIL=19971224T000000Z
|
244
|
+
#
|
245
|
+
# ==> (1997 9:00 AM EDT)September 2,9,16,23,30;October 7,14,21
|
246
|
+
# (1997 9:00 AM EST)October 28;November 4,11,18,25;December 2,9,16,23
|
247
|
+
|
248
|
+
Test(
|
249
|
+
'FREQ=WEEKLY;UNTIL=19971224T000000Z',
|
250
|
+
'19970902T090000',
|
251
|
+
<<VEC
|
252
|
+
# ==> (1997 9:00 AM EDT)September 2,9,16,23,30;October 7,14,21
|
253
|
+
# (1997 9:00 AM EST)October 28;November 4,11,18,25;December 2,9,16,23
|
254
|
+
VEC
|
255
|
+
)
|
256
|
+
|
257
|
+
end
|
258
|
+
|
259
|
+
def test_rfc2445_examples_every_other_week_forever
|
260
|
+
# Every other week - forever:
|
261
|
+
#
|
262
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
263
|
+
# RRULE:FREQ=WEEKLY;INTERVAL=2;WKST=SU
|
264
|
+
#
|
265
|
+
# ==> (1997 9:00 AM EDT)September 2,16,30;October 14
|
266
|
+
# (1997 9:00 AM EST)October 28;November 11,25;December 9,23
|
267
|
+
# (1998 9:00 AM EST)January 6,20;February
|
268
|
+
# ...
|
269
|
+
|
270
|
+
Test(
|
271
|
+
'FREQ=WEEKLY;INTERVAL=2;WKST=SU;count=11',
|
272
|
+
'19970902T090000',
|
273
|
+
<<VEC
|
274
|
+
# ==> (1997 9:00 AM EDT)September 2,16,30;October 14
|
275
|
+
# (1997 9:00 AM EST)October 28;November 11,25;December 9,23
|
276
|
+
# (1998 9:00 AM EST)January 6,20
|
277
|
+
VEC
|
278
|
+
)
|
279
|
+
end
|
280
|
+
|
281
|
+
def test_rfc2445_examples_weekly_on_t_and_th_for_5_weeks
|
282
|
+
# Weekly on Tuesday and Thursday for 5 weeks:
|
283
|
+
#
|
284
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
285
|
+
# RRULE:FREQ=WEEKLY;UNTIL=19971007T000000Z;WKST=SU;BYDAY=TU,TH
|
286
|
+
# or
|
287
|
+
#
|
288
|
+
# RRULE:FREQ=WEEKLY;COUNT=10;WKST=SU;BYDAY=TU,TH
|
289
|
+
#
|
290
|
+
# ==> (1997 9:00 AM EDT)September 2,4,9,11,16,18,23,25,30;October 2
|
291
|
+
Test(
|
292
|
+
'FREQ=WEEKLY;UNTIL=19971007T000000Z;WKST=SU;BYDAY=TU,TH',
|
293
|
+
'19970902T090000',
|
294
|
+
<<VEC
|
295
|
+
# ==> (1997 9:00 AM EDT)September 2,4,9,11,16,18,23,25,30;October 2
|
296
|
+
VEC
|
297
|
+
)
|
298
|
+
end
|
299
|
+
|
300
|
+
def test_rfc2445_examples_every_other_week_m_w_f_until_dec24
|
301
|
+
# Every other week on Monday, Wednesday and Friday until December 24,
|
302
|
+
# 1997, but starting on Tuesday, September 2, 1997:
|
303
|
+
#
|
304
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
305
|
+
# RRULE:FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;
|
306
|
+
# BYDAY=MO,WE,FR
|
307
|
+
# ==> (1997 9:00 AM EDT)September 2,3,5,15,17,19,29;October
|
308
|
+
# 1,3,13,15,17
|
309
|
+
# (1997 9:00 AM EST)October 27,29,31;November 10,12,14,24,26,28;
|
310
|
+
# December 8,10,12,22
|
311
|
+
|
312
|
+
Test(
|
313
|
+
'FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;BYDAY=MO,WE,FR',
|
314
|
+
'19970902T090000',
|
315
|
+
<<VEC
|
316
|
+
# ==> (1997 9:00 AM EDT)September 2,3,5,15,17,19,29;October 1,3,13,15,17
|
317
|
+
# (1997 9:00 AM EST)October 27,29,31;November 10,12,14,24,26,28;December 8,10,12,22
|
318
|
+
VEC
|
319
|
+
)
|
320
|
+
end
|
321
|
+
|
322
|
+
def test_rfc2445_examples_every_other_week_t_th_for_8
|
323
|
+
# Every other week on Tuesday and Thursday, for 8 occurrences:
|
324
|
+
#
|
325
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
326
|
+
# RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH
|
327
|
+
#
|
328
|
+
# ==> (1997 9:00 AM EDT)September 2,4,16,18,30;October 2,14,16
|
329
|
+
Test(
|
330
|
+
'FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH',
|
331
|
+
'19970902T090000',
|
332
|
+
<<VEC
|
333
|
+
# ==> (1997 9:00 AM EDT)September 2,4,16,18,30;October 2,14,16
|
334
|
+
VEC
|
335
|
+
)
|
336
|
+
end
|
337
|
+
|
338
|
+
def test_rfc2445_examples_monthly
|
339
|
+
# Monthly on the 1st Friday for ten occurrences:
|
340
|
+
#
|
341
|
+
# DTSTART;TZID=US-Eastern:19970905T090000
|
342
|
+
# RRULE:FREQ=MONTHLY;COUNT=10;BYDAY=1FR
|
343
|
+
#
|
344
|
+
# ==> (1997 9:00 AM EDT)September 5;October 3
|
345
|
+
# (1997 9:00 AM EST)November 7;Dec 5
|
346
|
+
# (1998 9:00 AM EST)January 2;February 6;March 6;April 3
|
347
|
+
# (1998 9:00 AM EDT)May 1;June 5
|
348
|
+
|
349
|
+
Test(
|
350
|
+
'FREQ=MONTHLY;COUNT=10;BYDAY=1FR',
|
351
|
+
'19970905T090000',
|
352
|
+
<<VEC
|
353
|
+
# ==> (1997 9:00 AM EDT)September 5;October 3
|
354
|
+
# (1997 9:00 AM EST)November 7;December 5
|
355
|
+
# (1998 9:00 AM EST)January 2;February 6;March 6;April 3
|
356
|
+
# (1998 9:00 AM EDT)May 1;June 5
|
357
|
+
VEC
|
358
|
+
)
|
359
|
+
|
360
|
+
|
361
|
+
# Monthly on the 1st Friday until December 24, 1997:
|
362
|
+
#
|
363
|
+
# DTSTART;TZID=US-Eastern:19970905T090000
|
364
|
+
# RRULE:FREQ=MONTHLY;UNTIL=19971224T000000Z;BYDAY=1FR
|
365
|
+
#
|
366
|
+
# ==> (1997 9:00 AM EDT)September 5;October 3
|
367
|
+
# (1997 9:00 AM EST)November 7;December 5
|
368
|
+
|
369
|
+
Test(
|
370
|
+
'FREQ=MONTHLY;UNTIL=19971224T000000Z;BYDAY=1FR',
|
371
|
+
'19970905T090000',
|
372
|
+
<<VEC
|
373
|
+
# ==> (1997 9:00 AM EDT)September 5;October 3
|
374
|
+
# (1997 9:00 AM EST)November 7;December 5
|
375
|
+
VEC
|
376
|
+
)
|
377
|
+
|
378
|
+
# Every other month on the 1st and last Sunday of the month for 10
|
379
|
+
# occurrences:
|
380
|
+
#
|
381
|
+
# DTSTART;TZID=US-Eastern:19970907T090000
|
382
|
+
# RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU
|
383
|
+
#
|
384
|
+
# ==> (1997 9:00 AM EDT)September 7,28
|
385
|
+
# (1997 9:00 AM EST)November 2,30
|
386
|
+
# (1998 9:00 AM EST)January 4,25;March 1,29
|
387
|
+
# (1998 9:00 AM EDT)May 3,31
|
388
|
+
|
389
|
+
Test(
|
390
|
+
'FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU',
|
391
|
+
'19970907T090000',
|
392
|
+
<<VEC
|
393
|
+
# ==> (1997 9:00 AM EDT)September 7,28
|
394
|
+
# (1997 9:00 AM EST)November 2,30
|
395
|
+
# (1998 9:00 AM EST)January 4,25;March 1,29
|
396
|
+
# (1998 9:00 AM EDT)May 3,31
|
397
|
+
VEC
|
398
|
+
)
|
399
|
+
|
400
|
+
# Monthly on the second to last Monday of the month for 6 months:
|
401
|
+
#
|
402
|
+
# DTSTART;TZID=US-Eastern:19970922T090000
|
403
|
+
# RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO
|
404
|
+
#
|
405
|
+
# ==> (1997 9:00 AM EDT)September 22;October 20
|
406
|
+
# (1997 9:00 AM EST)November 17;December 22
|
407
|
+
# (1998 9:00 AM EST)January 19;February 16
|
408
|
+
|
409
|
+
Test(
|
410
|
+
'FREQ=MONTHLY;COUNT=6;BYDAY=-2MO',
|
411
|
+
'19970922T090000',
|
412
|
+
<<VEC
|
413
|
+
# ==> (1997 9:00 AM EDT)September 22;October 20
|
414
|
+
# (1997 9:00 AM EST)November 17;December 22
|
415
|
+
# (1998 9:00 AM EST)January 19;February 16
|
416
|
+
VEC
|
417
|
+
)
|
418
|
+
|
419
|
+
# Monthly on the third to the last day of the month, forever:
|
420
|
+
#
|
421
|
+
# DTSTART;TZID=US-Eastern:19970928T090000
|
422
|
+
# RRULE:FREQ=MONTHLY;BYMONTHDAY=-3
|
423
|
+
#
|
424
|
+
# ==> (1997 9:00 AM EDT)September 28
|
425
|
+
# (1997 9:00 AM EST)October 29;November 28;December 29
|
426
|
+
# (1998 9:00 AM EST)January 29;February 26
|
427
|
+
# ...
|
428
|
+
|
429
|
+
Test(
|
430
|
+
'FREQ=MONTHLY;BYMONTHDAY=-3;count=6',
|
431
|
+
'19970928T090000',
|
432
|
+
<<VEC
|
433
|
+
# ==> (1997 9:00 AM EDT)September 28
|
434
|
+
# (1997 9:00 AM EST)October 29;November 28;December 29
|
435
|
+
# (1998 9:00 AM EST)January 29;February 26
|
436
|
+
VEC
|
437
|
+
)
|
438
|
+
|
439
|
+
# Monthly on the 2nd and 15th of the month for 10 occurrences:
|
440
|
+
#
|
441
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
442
|
+
# RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15
|
443
|
+
#
|
444
|
+
# ==> (1997 9:00 AM EDT)September 2,15;October 2,15
|
445
|
+
# (1997 9:00 AM EST)November 2,15;December 2,15
|
446
|
+
# (1998 9:00 AM EST)January 2,15
|
447
|
+
|
448
|
+
Test(
|
449
|
+
'FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15',
|
450
|
+
'19970902T090000',
|
451
|
+
<<VEC
|
452
|
+
# ==> (1997 9:00 AM EDT)September 2,15;October 2,15
|
453
|
+
# (1997 9:00 AM EST)November 2,15;December 2,15
|
454
|
+
# (1998 9:00 AM EST)January 2,15
|
455
|
+
VEC
|
456
|
+
)
|
457
|
+
|
458
|
+
# Monthly on the first and last day of the month for 10 occurrences:
|
459
|
+
#
|
460
|
+
# DTSTART;TZID=US-Eastern:19970930T090000
|
461
|
+
# RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1
|
462
|
+
#
|
463
|
+
# ==> (1997 9:00 AM EDT)September 30;October 1
|
464
|
+
# (1997 9:00 AM EST)October 31;November 1,30;December 1,31
|
465
|
+
# (1998 9:00 AM EST)January 1,31;February 1
|
466
|
+
|
467
|
+
Test(
|
468
|
+
'FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1',
|
469
|
+
'19970930T090000',
|
470
|
+
<<VEC
|
471
|
+
# ==> (1997 9:00 AM EDT)September 30;October 1
|
472
|
+
# (1997 9:00 AM EST)October 31;November 1,30;December 1,31
|
473
|
+
# (1998 9:00 AM EST)January 1,31;February 1
|
474
|
+
VEC
|
475
|
+
)
|
476
|
+
|
477
|
+
# Every 18 months on the 10th thru 15th of the month for 10
|
478
|
+
# occurrences:
|
479
|
+
#
|
480
|
+
# DTSTART;TZID=US-Eastern:19970910T090000
|
481
|
+
# RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,
|
482
|
+
# 15
|
483
|
+
#
|
484
|
+
# ==> (1997 9:00 AM EDT)September 10,11,12,13,14,15
|
485
|
+
# (1999 9:00 AM EST)March 10,11,12,13
|
486
|
+
|
487
|
+
Test(
|
488
|
+
'FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,15',
|
489
|
+
'19970910T090000',
|
490
|
+
<<VEC
|
491
|
+
# ==> (1997 9:00 AM EDT)September 10,11,12,13,14,15
|
492
|
+
# (1999 9:00 AM EST)March 10,11,12,13
|
493
|
+
VEC
|
494
|
+
)
|
495
|
+
|
496
|
+
# Every Tuesday, every other month:
|
497
|
+
#
|
498
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
499
|
+
# RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU
|
500
|
+
#
|
501
|
+
# ==> (1997 9:00 AM EDT)September 2,9,16,23,30
|
502
|
+
# (1997 9:00 AM EST)November 4,11,18,25
|
503
|
+
# (1998 9:00 AM EST)January 6,13,20,27;March 3,10,17,24,31
|
504
|
+
# ...
|
505
|
+
|
506
|
+
Test(
|
507
|
+
'FREQ=MONTHLY;INTERVAL=2;BYDAY=TU;count=18',
|
508
|
+
'19970902T090000',
|
509
|
+
<<VEC
|
510
|
+
# ==> (1997 9:00 AM EDT)September 2,9,16,23,30
|
511
|
+
# (1997 9:00 AM EST)November 4,11,18,25
|
512
|
+
# (1998 9:00 AM EST)January 6,13,20,27;March 3,10,17,24,31
|
513
|
+
VEC
|
514
|
+
)
|
515
|
+
end
|
516
|
+
|
517
|
+
def test_rfc2445_examples_misc1
|
518
|
+
# Yearly in June and July for 10 occurrences:
|
519
|
+
#
|
520
|
+
# DTSTART;TZID=US-Eastern:19970610T090000
|
521
|
+
# RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7
|
522
|
+
# ==> (1997 9:00 AM EDT)June 10;July 10
|
523
|
+
# (1998 9:00 AM EDT)June 10;July 10
|
524
|
+
# (1999 9:00 AM EDT)June 10;July 10
|
525
|
+
# (2000 9:00 AM EDT)June 10;July 10
|
526
|
+
# (2001 9:00 AM EDT)June 10;July 10
|
527
|
+
# Note: Since none of the BYDAY, BYMONTHDAY or BYYEARDAY components
|
528
|
+
# are specified, the day is gotten from DTSTART
|
529
|
+
|
530
|
+
Test(
|
531
|
+
'FREQ=YEARLY;COUNT=10;BYMONTH=6,7',
|
532
|
+
'19970610T090000',
|
533
|
+
<<VEC
|
534
|
+
# ==> (1997 9:00 AM EDT)June 10;July 10
|
535
|
+
# (1998 9:00 AM EDT)June 10;July 10
|
536
|
+
# (1999 9:00 AM EDT)June 10;July 10
|
537
|
+
# (2000 9:00 AM EDT)June 10;July 10
|
538
|
+
# (2001 9:00 AM EDT)June 10;July 10
|
539
|
+
VEC
|
540
|
+
)
|
541
|
+
|
542
|
+
# Every other year on January, February, and March for 10 occurrences:
|
543
|
+
#
|
544
|
+
# DTSTART;TZID=US-Eastern:19970310T090000
|
545
|
+
# RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3
|
546
|
+
#
|
547
|
+
# ==> (1997 9:00 AM EST)March 10
|
548
|
+
# (1999 9:00 AM EST)January 10;February 10;March 10
|
549
|
+
# (2001 9:00 AM EST)January 10;February 10;March 10
|
550
|
+
# (2003 9:00 AM EST)January 10;February 10;March 10
|
551
|
+
|
552
|
+
Test(
|
553
|
+
'FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3',
|
554
|
+
'19970310T090000',
|
555
|
+
<<VEC
|
556
|
+
# ==> (1997 9:00 AM EST)March 10
|
557
|
+
# (1999 9:00 AM EST)January 10;February 10;March 10
|
558
|
+
# (2001 9:00 AM EST)January 10;February 10;March 10
|
559
|
+
# (2003 9:00 AM EST)January 10;February 10;March 10
|
560
|
+
VEC
|
561
|
+
)
|
562
|
+
|
563
|
+
# Every 3rd year on the 1st, 100th and 200th day for 10 occurrences:
|
564
|
+
#
|
565
|
+
# DTSTART;TZID=US-Eastern:19970101T090000
|
566
|
+
# RRULE:FREQ=YEARLY;INTERVAL=3;COUNT=10;BYYEARDAY=1,100,200
|
567
|
+
#
|
568
|
+
# ==> (1997 9:00 AM EST)January 1
|
569
|
+
# (1997 9:00 AM EDT)April 10;July 19
|
570
|
+
# (2000 9:00 AM EST)January 1
|
571
|
+
# (2000 9:00 AM EDT)April 9;July 18
|
572
|
+
# (2003 9:00 AM EST)January 1
|
573
|
+
# (2003 9:00 AM EDT)April 10;July 19
|
574
|
+
# (2006 9:00 AM EST)January 1
|
575
|
+
|
576
|
+
Test(
|
577
|
+
'FREQ=YEARLY;INTERVAL=3;COUNT=10;BYYEARDAY=1,100,200',
|
578
|
+
'19970101T090000',
|
579
|
+
<<VEC
|
580
|
+
# ==> (1997 9:00 AM EST)January 1
|
581
|
+
# (1997 9:00 AM EDT)April 10;July 19
|
582
|
+
# (2000 9:00 AM EST)January 1
|
583
|
+
# (2000 9:00 AM EDT)April 9;July 18
|
584
|
+
# (2003 9:00 AM EST)January 1
|
585
|
+
# (2003 9:00 AM EDT)April 10;July 19
|
586
|
+
# (2006 9:00 AM EST)January 1
|
587
|
+
VEC
|
588
|
+
)
|
589
|
+
|
590
|
+
# Every 20th Monday of the year, forever:
|
591
|
+
# DTSTART;TZID=US-Eastern:19970519T090000
|
592
|
+
# RRULE:FREQ=YEARLY;BYDAY=20MO
|
593
|
+
#
|
594
|
+
# ==> (1997 9:00 AM EDT)May 19
|
595
|
+
# (1998 9:00 AM EDT)May 18
|
596
|
+
# (1999 9:00 AM EDT)May 17
|
597
|
+
# ...
|
598
|
+
|
599
|
+
Test(
|
600
|
+
'FREQ=YEARLY;BYDAY=20MO;count=3',
|
601
|
+
'19970519T090000',
|
602
|
+
<<VEC
|
603
|
+
# ==> (1997 9:00 AM EDT)May 19
|
604
|
+
# (1998 9:00 AM EDT)May 18
|
605
|
+
# (1999 9:00 AM EDT)May 17
|
606
|
+
VEC
|
607
|
+
)
|
608
|
+
|
609
|
+
# Monday of week number 20 (where the default start of the week is
|
610
|
+
# Monday), forever:
|
611
|
+
#
|
612
|
+
# DTSTART;TZID=US-Eastern:19970512T090000
|
613
|
+
# RRULE:FREQ=YEARLY;BYWEEKNO=20;BYDAY=MO
|
614
|
+
#
|
615
|
+
# ==> (1997 9:00 AM EDT)May 12
|
616
|
+
# (1998 9:00 AM EDT)May 11
|
617
|
+
# (1999 9:00 AM EDT)May 17
|
618
|
+
# ...
|
619
|
+
|
620
|
+
# TODO
|
621
|
+
|
622
|
+
# Every Thursday in March, forever:
|
623
|
+
#
|
624
|
+
# DTSTART;TZID=US-Eastern:19970313T090000
|
625
|
+
# RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH
|
626
|
+
#
|
627
|
+
# ==> (1997 9:00 AM EST)March 13,20,27
|
628
|
+
# (1998 9:00 AM EST)March 5,12,19,26
|
629
|
+
# (1999 9:00 AM EST)March 4,11,18,25
|
630
|
+
# ...
|
631
|
+
|
632
|
+
Test(
|
633
|
+
'FREQ=YEARLY;BYMONTH=3;BYDAY=TH;count=11',
|
634
|
+
'19970313T090000',
|
635
|
+
<<VEC
|
636
|
+
# ==> (1997 9:00 AM EST)March 13,20,27
|
637
|
+
# (1998 9:00 AM EST)March 5,12,19,26
|
638
|
+
# (1999 9:00 AM EST)March 4,11,18,25
|
639
|
+
VEC
|
640
|
+
)
|
641
|
+
|
642
|
+
# Every Thursday, but only during June, July, and August, forever:
|
643
|
+
#
|
644
|
+
# DTSTART;TZID=US-Eastern:19970605T090000
|
645
|
+
# RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8
|
646
|
+
#
|
647
|
+
# ==> (1997 9:00 AM EDT)June 5,12,19,26;July 3,10,17,24,31;
|
648
|
+
# August 7,14,21,28
|
649
|
+
# (1998 9:00 AM EDT)June 4,11,18,25;July 2,9,16,23,30;
|
650
|
+
# August 6,13,20,27
|
651
|
+
# (1999 9:00 AM EDT)June 3,10,17,24;July 1,8,15,22,29;
|
652
|
+
# August 5,12,19,26
|
653
|
+
# ...
|
654
|
+
|
655
|
+
Test(
|
656
|
+
'FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8;count=39',
|
657
|
+
'19970605T090000',
|
658
|
+
<<VEC
|
659
|
+
# ==> (1997 9:00 AM EDT)June 5,12,19,26;July 3,10,17,24,31;August 7,14,21,28
|
660
|
+
# (1998 9:00 AM EDT)June 4,11,18,25;July 2,9,16,23,30;August 6,13,20,27
|
661
|
+
# (1999 9:00 AM EDT)June 3,10,17,24;July 1,8,15,22,29;August 5,12,19,26
|
662
|
+
VEC
|
663
|
+
)
|
664
|
+
|
665
|
+
=begin
|
666
|
+
|
667
|
+
EXDATE isn't supported.
|
668
|
+
|
669
|
+
# Every Friday the 13th, forever:
|
670
|
+
#
|
671
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
672
|
+
# EXDATE;TZID=US-Eastern:19970902T090000
|
673
|
+
# RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13
|
674
|
+
# ==> (1998 9:00 AM EST)February 13;March 13;November 13
|
675
|
+
# (1999 9:00 AM EDT)August 13
|
676
|
+
# (2000 9:00 AM EDT)October 13
|
677
|
+
# ...
|
678
|
+
Test(
|
679
|
+
'FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13;count=5',
|
680
|
+
'19970902T090000',
|
681
|
+
<<VEC
|
682
|
+
# ==> (1998 9:00 AM EST)February 13;March 13;November 13
|
683
|
+
# (1999 9:00 AM EDT)August 13
|
684
|
+
# (2000 9:00 AM EDT)October 13
|
685
|
+
VEC
|
686
|
+
)
|
687
|
+
=end
|
688
|
+
|
689
|
+
# The first Saturday that follows the first Sunday of the month,
|
690
|
+
# forever:
|
691
|
+
#
|
692
|
+
# DTSTART;TZID=US-Eastern:19970913T090000
|
693
|
+
# RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13
|
694
|
+
#
|
695
|
+
# ==> (1997 9:00 AM EDT)September 13;October 11
|
696
|
+
# (1997 9:00 AM EST)November 8;December 13
|
697
|
+
# (1998 9:00 AM EST)January 10;February 7;March 7
|
698
|
+
# (1998 9:00 AM EDT)April 11;May 9;June 13...
|
699
|
+
# ...
|
700
|
+
|
701
|
+
Test(
|
702
|
+
'FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13;count=10',
|
703
|
+
'19970913T090000',
|
704
|
+
<<VEC
|
705
|
+
# ==> (1997 9:00 AM EDT)September 13;October 11
|
706
|
+
# (1997 9:00 AM EST)November 8;December 13
|
707
|
+
# (1998 9:00 AM EST)January 10;February 7;March 7
|
708
|
+
# (1998 9:00 AM EDT)April 11;May 9;June 13...
|
709
|
+
VEC
|
710
|
+
)
|
711
|
+
|
712
|
+
# Every four years, the first Tuesday after a Monday in November,
|
713
|
+
# forever (U.S. Presidential Election day):
|
714
|
+
#
|
715
|
+
# DTSTART;TZID=US-Eastern:19961105T090000
|
716
|
+
# RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,
|
717
|
+
# 5,6,7,8
|
718
|
+
#
|
719
|
+
# ==> (1996 9:00 AM EST)November 5
|
720
|
+
# (2000 9:00 AM EST)November 7
|
721
|
+
# (2004 9:00 AM EST)November 2
|
722
|
+
# ...
|
723
|
+
|
724
|
+
Test(
|
725
|
+
'FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8;count=3',
|
726
|
+
'19961105T090000',
|
727
|
+
<<VEC
|
728
|
+
# ==> (1996 9:00 AM EST)November 5
|
729
|
+
# (2000 9:00 AM EST)November 7
|
730
|
+
# (2004 9:00 AM EST)November 2
|
731
|
+
VEC
|
732
|
+
)
|
733
|
+
|
734
|
+
# The 3rd instance into the month of one of Tuesday, Wednesday or
|
735
|
+
# Thursday, for the next 3 months:
|
736
|
+
#
|
737
|
+
# DTSTART;TZID=US-Eastern:19970904T090000
|
738
|
+
# RRULE:FREQ=MONTHLY;COUNT=3;BYDAY=TU,WE,TH;BYSETPOS=3
|
739
|
+
#
|
740
|
+
# ==> (1997 9:00 AM EDT)September 4;October 7
|
741
|
+
# (1997 9:00 AM EST)November 6
|
742
|
+
|
743
|
+
Test(
|
744
|
+
'FREQ=MONTHLY;COUNT=3;BYDAY=TU,WE,TH;BYSETPOS=3',
|
745
|
+
'19970904T090000',
|
746
|
+
<<VEC
|
747
|
+
# ==> (1997 9:00 AM EDT)September 4;October 7
|
748
|
+
# (1997 9:00 AM EST)November 6
|
749
|
+
VEC
|
750
|
+
)
|
751
|
+
|
752
|
+
end
|
753
|
+
|
754
|
+
def test_rfc2445_example_2nd_last_weekday_of_month
|
755
|
+
# The 2nd to last weekday of the month:
|
756
|
+
#
|
757
|
+
# DTSTART;TZID=US-Eastern:19970929T090000
|
758
|
+
# RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-2
|
759
|
+
#
|
760
|
+
# ==> (1997 9:00 AM EDT)September 29
|
761
|
+
# (1997 9:00 AM EST)October 30;November 27;December 30
|
762
|
+
# (1998 9:00 AM EST)January 29;February 26;March 30
|
763
|
+
# ...
|
764
|
+
#
|
765
|
+
|
766
|
+
Test(
|
767
|
+
'FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-2;count=7',
|
768
|
+
'19970929T090000',
|
769
|
+
<<VEC
|
770
|
+
# ==> (1997 9:00 AM EDT)September 29
|
771
|
+
# (1997 9:00 AM EST)October 30;November 27;December 30
|
772
|
+
# (1998 9:00 AM EST)January 29;February 26;March 30
|
773
|
+
VEC
|
774
|
+
)
|
775
|
+
end
|
776
|
+
|
777
|
+
def test_rfc2445_examples_misc2
|
778
|
+
# Every 3 hours from 9:00 AM to 5:00 PM on a specific day:
|
779
|
+
#
|
780
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
781
|
+
# RRULE:FREQ=HOURLY;INTERVAL=3;UNTIL=19970902T170000Z
|
782
|
+
#
|
783
|
+
# ==> (September 2, 1997 EDT)09:00,12:00,15:00
|
784
|
+
#
|
785
|
+
# Every 15 minutes for 6 occurrences:
|
786
|
+
#
|
787
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
788
|
+
# RRULE:FREQ=MINUTELY;INTERVAL=15;COUNT=6
|
789
|
+
#
|
790
|
+
# ==> (September 2, 1997 EDT)09:00,09:15,09:30,09:45,10:00,10:15
|
791
|
+
#
|
792
|
+
# Every hour and a half for 4 occurrences:
|
793
|
+
#
|
794
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
795
|
+
# RRULE:FREQ=MINUTELY;INTERVAL=90;COUNT=4
|
796
|
+
#
|
797
|
+
# ==> (September 2, 1997 EDT)09:00,10:30;12:00;13:30
|
798
|
+
#
|
799
|
+
# Every 20 minutes from 9:00 AM to 4:40 PM every day:
|
800
|
+
#
|
801
|
+
# DTSTART;TZID=US-Eastern:19970902T090000
|
802
|
+
# RRULE:FREQ=DAILY;BYHOUR=9,10,11,12,13,14,15,16;BYMINUTE=0,20,40
|
803
|
+
# or
|
804
|
+
# RRULE:FREQ=MINUTELY;INTERVAL=20;BYHOUR=9,10,11,12,13,14,15,16
|
805
|
+
#
|
806
|
+
# ==> (September 2, 1997 EDT)9:00,9:20,9:40,10:00,10:20,
|
807
|
+
# ... 16:00,16:20,16:40
|
808
|
+
# (September 3, 1997 EDT)9:00,9:20,9:40,10:00,10:20,
|
809
|
+
# ...16:00,16:20,16:40
|
810
|
+
# ...
|
811
|
+
|
812
|
+
end
|
813
|
+
|
814
|
+
def test_rfc2445_examples_weekly_days_differ_on_wkst
|
815
|
+
# An example where the days generated makes a difference because of
|
816
|
+
# WKST:
|
817
|
+
#
|
818
|
+
# DTSTART;TZID=US-Eastern:19970805T090000
|
819
|
+
# RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=MO
|
820
|
+
#
|
821
|
+
# ==> (1997 EDT)Aug 5,10,19,24
|
822
|
+
Test(
|
823
|
+
'FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=MO',
|
824
|
+
'19970805T090000',
|
825
|
+
<<VEC
|
826
|
+
# ==> (1997 9:00 AM EDT)August 5,10,19,24
|
827
|
+
VEC
|
828
|
+
)
|
829
|
+
|
830
|
+
#
|
831
|
+
# changing only WKST from MO to SU, yields different results...
|
832
|
+
#
|
833
|
+
# DTSTART;TZID=US-Eastern:19970805T090000
|
834
|
+
# RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=SU
|
835
|
+
# ==> (1997 EDT)August 5,17,19,31
|
836
|
+
|
837
|
+
Test(
|
838
|
+
'FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=SU',
|
839
|
+
'19970805T090000',
|
840
|
+
<<VEC
|
841
|
+
# ==> (1997 9:00 AM EDT)August 5,17,19,31
|
842
|
+
VEC
|
843
|
+
)
|
844
|
+
end
|
845
|
+
|
846
|
+
def test_us_laborday
|
847
|
+
=begin
|
848
|
+
Patch with test from Sam Stephenson at 37signals:
|
849
|
+
|
850
|
+
We're using your vPim library at 37signals for the Backpack Calendar
|
851
|
+
(http://backpackit.com/calendar ) and ran into an issue with the "US
|
852
|
+
Holidays" calendar available at http://ical.mac.com/ical/US32Holidays.ics .
|
853
|
+
Specifically, calling Vpim::Rrule#each for events such as Labor Day:
|
854
|
+
|
855
|
+
DTSTART;VALUE=DATE:20020902
|
856
|
+
DTEND;VALUE=DATE:20020903
|
857
|
+
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=9;BYDAY=1MO
|
858
|
+
|
859
|
+
would never yield any recurrences.
|
860
|
+
=end
|
861
|
+
|
862
|
+
# The first Monday in September, forever (Labor Day):
|
863
|
+
#
|
864
|
+
# DTSTART;TZID=US-Eastern:20020902T090000
|
865
|
+
# RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=9;BYDAY=1MO
|
866
|
+
#
|
867
|
+
# ==> (2002 9:00 AM EST)September 2
|
868
|
+
# (2003 9:00 AM EST)September 1
|
869
|
+
# (2004 9:00 AM EST)September 6
|
870
|
+
# ...
|
871
|
+
|
872
|
+
Test(
|
873
|
+
'FREQ=YEARLY;INTERVAL=1;BYMONTH=9;BYDAY=1MO;count=3',
|
874
|
+
'20020902T090000',
|
875
|
+
<<VEC
|
876
|
+
# ==> (2002 9:00 AM EDT)September 2
|
877
|
+
# (2003 9:00 AM EDT)September 1
|
878
|
+
# (2004 9:00 AM EDT)September 6
|
879
|
+
VEC
|
880
|
+
)
|
881
|
+
end
|
882
|
+
|
883
|
+
def test_zipdx_weekly_1
|
884
|
+
# Example provided by Zipdx
|
885
|
+
# Produced by: Zimbra-Calendar-Provider
|
886
|
+
# Interop tested against Apple iCal 3.0.2
|
887
|
+
Test(
|
888
|
+
'FREQ=WEEKLY;UNTIL=20080501;INTERVAL=1;BYDAY=TU,TH',
|
889
|
+
'20080415T160000',
|
890
|
+
<<VEC
|
891
|
+
# ==> (2008 4:00 PM EDT)April 15,17,22,24,29
|
892
|
+
VEC
|
893
|
+
);
|
894
|
+
end
|
895
|
+
|
896
|
+
def test_zipdx_weekly_2
|
897
|
+
# Example provided by Zipdx
|
898
|
+
# Produced by: -//Microsoft Corporation//Outlook 11.0 MIMEDIR//EN
|
899
|
+
# Interop tested against Apple iCal 3.0.2
|
900
|
+
Test(
|
901
|
+
'FREQ=WEEKLY;COUNT=9;INTERVAL=2;BYDAY=MO,WE,FR;WKST=SU',
|
902
|
+
'20080811T130000',
|
903
|
+
<<VEC
|
904
|
+
# ==> (2008 1:00 PM EDT)August 11,13,15,25,27,29;September 8,10,12
|
905
|
+
VEC
|
906
|
+
);
|
907
|
+
end
|
908
|
+
|
909
|
+
def test_zipdx_daily_1
|
910
|
+
# Example provided by Zipdx
|
911
|
+
# Produced by: Microsoft CDO for Microsoft Exchange
|
912
|
+
# Interop tested against Apple iCal 3.0.2
|
913
|
+
Test(
|
914
|
+
'FREQ=DAILY;COUNT=7;WKST=SU;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR',
|
915
|
+
'20080218T180000',
|
916
|
+
<<VEC
|
917
|
+
# ==> (2008 6:00 PM EST)February 18,19,20,21,22,25,26
|
918
|
+
VEC
|
919
|
+
);
|
920
|
+
end
|
921
|
+
|
922
|
+
def test_bysetpos_before_dtstart
|
923
|
+
# Note - this doesn't work with Apple iCal 3.0.2, I think its their bug.
|
924
|
+
Test(
|
925
|
+
'FREQ=MONTHLY;COUNT=5;BYDAY=MO;BYSETPOS=1,2',
|
926
|
+
'20080305T180000',
|
927
|
+
<<VEC
|
928
|
+
# ==> (2008 6:00 PM EST)March 5
|
929
|
+
# (2008 6:00 PM EDT)March 10
|
930
|
+
# (2008 6:00 PM EDT)April 7,14
|
931
|
+
# (2008 6:00 PM EDT)May 5
|
932
|
+
VEC
|
933
|
+
);
|
934
|
+
end
|
935
|
+
|
936
|
+
def test_bysetpos_after_until
|
937
|
+
Test(
|
938
|
+
'FREQ=MONTHLY;UNTIL=20080421;BYDAY=MO;BYSETPOS=-1',
|
939
|
+
'20080305T180000',
|
940
|
+
<<VEC
|
941
|
+
# ==> (2008 6:00 PM EST)March 5
|
942
|
+
# (2008 6:00 PM EDT)March 31
|
943
|
+
VEC
|
944
|
+
);
|
945
|
+
end
|
946
|
+
|
947
|
+
def test_bysetpos_zipdx_last_saturday
|
948
|
+
# In Microsoft Exchange, if I want a meeting to occur on a certain Saturday
|
949
|
+
# of each month, Exchange generates:
|
950
|
+
#
|
951
|
+
# RRULE:FREQ=MONTHLY;COUNT=4;WKST=SU;INTERVAL=1;BYDAY=-1SA
|
952
|
+
#
|
953
|
+
# However, if I use Microsoft Outlook, Outlook generates:
|
954
|
+
# RRULE:FREQ=MONTHLY;COUNT=4;INTERVAL=1;BYDAY=SA;BYSETPOS=-1;WKST=SU
|
955
|
+
# And we get confused and generate the meeting every week (instead of every
|
956
|
+
# month). I think this is because the library does not support BYSETPOS;
|
957
|
+
# this is stated in the documentation.
|
958
|
+
Test(
|
959
|
+
'FREQ=MONTHLY;COUNT=4;INTERVAL=1;WKST=SU;BYDAY=SA;BYSETPOS=-1',
|
960
|
+
'20080305T180000',
|
961
|
+
<<VEC
|
962
|
+
# ==> (2008 6:00 PM EST)March 5
|
963
|
+
# (2008 6:00 PM EDT)March 29
|
964
|
+
# (2008 6:00 PM EDT)April 26
|
965
|
+
# (2008 6:00 PM EDT)May 31
|
966
|
+
VEC
|
967
|
+
);
|
968
|
+
end
|
969
|
+
=begin
|
970
|
+
BEGIN:VEVENT
|
971
|
+
SUMMARY:Boxing Day
|
972
|
+
DESCRIPTION:First Weekday on or after December 26th.
|
973
|
+
DTSTAMP:20030701T000000Z
|
974
|
+
UID:holiday0042@icaldates.com
|
975
|
+
CATEGORIES:Holiday - Canada
|
976
|
+
DTSTART;VALUE=DATE:17531226
|
977
|
+
RRULE:FREQ=MONTHLY;BYMONTH=12;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYMONTHDAY=26,27,28;BYSETPOS=1
|
978
|
+
END:VEVENT
|
979
|
+
=end
|
980
|
+
|
981
|
+
|
982
|
+
def test_reccurrence_with_utc_dtstart
|
983
|
+
# Its wrong that the times yielded aren't in the timezone of DTSTART, but
|
984
|
+
# until vPim supports timezones, its the best it'll get.
|
985
|
+
txt = <<'__'
|
986
|
+
BEGIN:VCALENDAR
|
987
|
+
BEGIN:VEVENT
|
988
|
+
DTSTAMP:20080416T174954Z
|
989
|
+
ORGANIZER;CN=Anonymous:MAILTO:ano@nymo.us
|
990
|
+
CREATED:20080401T090904Z
|
991
|
+
LAST-MODIFIED:20080401T090904Z
|
992
|
+
SUMMARY:Very important recurring event
|
993
|
+
RRULE:FREQ=WEEKLY;UNTIL=20080415T093000Z;BYDAY=TU;BYHOUR=9
|
994
|
+
DTSTART:20080401T093000Z
|
995
|
+
DTEND:20080401T110000Z
|
996
|
+
TRANSP:OPAQUE
|
997
|
+
END:VEVENT
|
998
|
+
END:VCALENDAR
|
999
|
+
__
|
1000
|
+
cal = Vpim::Icalendar.decode(txt).first
|
1001
|
+
occurs = cal.events.to_a.first.occurrences.to_a
|
1002
|
+
#p occurs
|
1003
|
+
utc = occurs.map{|y| y.utc}
|
1004
|
+
#p utc
|
1005
|
+
expects = [
|
1006
|
+
Time.utc(2008, 4, 1, 9, 30),
|
1007
|
+
Time.utc(2008, 4, 8, 9, 30),
|
1008
|
+
Time.utc(2008, 4,15, 9, 30),
|
1009
|
+
]
|
1010
|
+
assert_equal(expects, utc)
|
1011
|
+
end
|
1012
|
+
|
1013
|
+
def test_maker
|
1014
|
+
assert_equal("FREQ=WEEKLY",
|
1015
|
+
Rrule::Maker.new{|m|m.frequency = "WEEKLY"}.encode)
|
1016
|
+
assert_equal("FREQ=WEEKLY;COUNT=2",
|
1017
|
+
Rrule::Maker.new{|m|m.frequency = "WEEKLY"; m.count = 2}.encode)
|
1018
|
+
assert_raises(ArgumentError) do
|
1019
|
+
Rrule::Maker.new{|m|m.count = 2; m.until = Time.now}
|
1020
|
+
end
|
1021
|
+
assert_raises(ArgumentError) do
|
1022
|
+
Rrule::Maker.new{|m|m.until = Time.now; m.count = 4}
|
1023
|
+
end
|
1024
|
+
assert_raises(ArgumentError) do
|
1025
|
+
Rrule::Maker.new.encode
|
1026
|
+
end
|
1027
|
+
end
|
1028
|
+
|
1029
|
+
end
|
1030
|
+
|