vpim 0.597 → 0.602

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