• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1dateutil examples
2=================
3
4.. contents::
5
6relativedelta examples
7----------------------
8
9.. testsetup:: relativedelta
10
11    from datetime import *; from dateutil.relativedelta import *
12    import calendar
13    NOW = datetime(2003, 9, 17, 20, 54, 47, 282310)
14    TODAY = date(2003, 9, 17)
15
16Let's begin our trip::
17
18    >>> from datetime import *; from dateutil.relativedelta import *
19    >>> import calendar
20
21Store some values::
22
23    >>> NOW = datetime.now()
24    >>> TODAY = date.today()
25    >>> NOW
26    datetime.datetime(2003, 9, 17, 20, 54, 47, 282310)
27    >>> TODAY
28    datetime.date(2003, 9, 17)
29
30Next month
31
32.. doctest:: relativedelta
33
34    >>> NOW+relativedelta(months=+1)
35    datetime.datetime(2003, 10, 17, 20, 54, 47, 282310)
36
37Next month, plus one week.
38
39.. doctest:: relativedelta
40
41    >>> NOW+relativedelta(months=+1, weeks=+1)
42    datetime.datetime(2003, 10, 24, 20, 54, 47, 282310)
43
44Next month, plus one week, at 10am.
45
46.. doctest:: relativedelta
47
48    >>> TODAY+relativedelta(months=+1, weeks=+1, hour=10)
49    datetime.datetime(2003, 10, 24, 10, 0)
50
51Here is another example using an absolute relativedelta.  Notice the use of
52year and month (both singular) which causes the values to be *replaced* in the
53original datetime rather than performing an arithmetic operation on them.
54
55.. doctest:: relativedelta
56
57    >>> NOW+relativedelta(year=1, month=1)
58    datetime.datetime(1, 1, 17, 20, 54, 47, 282310)
59
60Let's try the other way around. Notice that the
61hour setting we get in the relativedelta is relative,
62since it's a difference, and the weeks parameter
63has gone.
64
65.. doctest:: relativedelta
66
67    >>> relativedelta(datetime(2003, 10, 24, 10, 0), TODAY)
68    relativedelta(months=+1, days=+7, hours=+10)
69
70One month before one year.
71
72.. doctest:: relativedelta
73
74    >>> NOW+relativedelta(years=+1, months=-1)
75    datetime.datetime(2004, 8, 17, 20, 54, 47, 282310)
76
77How does it handle months with different numbers of days?
78Notice that adding one month will never cross the month
79boundary.
80
81.. doctest:: relativedelta
82
83    >>> date(2003,1,27)+relativedelta(months=+1)
84    datetime.date(2003, 2, 27)
85    >>> date(2003,1,31)+relativedelta(months=+1)
86    datetime.date(2003, 2, 28)
87    >>> date(2003,1,31)+relativedelta(months=+2)
88    datetime.date(2003, 3, 31)
89
90The logic for years is the same, even on leap years.
91
92.. doctest:: relativedelta
93
94    >>> date(2000,2,28)+relativedelta(years=+1)
95    datetime.date(2001, 2, 28)
96    >>> date(2000,2,29)+relativedelta(years=+1)
97    datetime.date(2001, 2, 28)
98
99    >>> date(1999,2,28)+relativedelta(years=+1)
100    datetime.date(2000, 2, 28)
101    >>> date(1999,3,1)+relativedelta(years=+1)
102    datetime.date(2000, 3, 1)
103
104    >>> date(2001,2,28)+relativedelta(years=-1)
105    datetime.date(2000, 2, 28)
106    >>> date(2001,3,1)+relativedelta(years=-1)
107    datetime.date(2000, 3, 1)
108
109Next friday
110
111.. doctest:: relativedelta
112
113    >>> TODAY+relativedelta(weekday=FR)
114    datetime.date(2003, 9, 19)
115
116    >>> TODAY+relativedelta(weekday=calendar.FRIDAY)
117    datetime.date(2003, 9, 19)
118
119Last friday in this month.
120
121.. doctest:: relativedelta
122
123    >>> TODAY+relativedelta(day=31, weekday=FR(-1))
124    datetime.date(2003, 9, 26)
125
126Next wednesday (it's today!).
127
128.. doctest:: relativedelta
129
130    >>> TODAY+relativedelta(weekday=WE(+1))
131    datetime.date(2003, 9, 17)
132
133Next wednesday, but not today.
134
135.. doctest:: relativedelta
136
137    >>> TODAY+relativedelta(days=+1, weekday=WE(+1))
138    datetime.date(2003, 9, 24)
139
140Following
141[http://www.cl.cam.ac.uk/~mgk25/iso-time.html ISO year week number notation]
142find the first day of the 15th week of 1997.
143
144.. doctest:: relativedelta
145
146    >>> datetime(1997,1,1)+relativedelta(day=4, weekday=MO(-1), weeks=+14)
147    datetime.datetime(1997, 4, 7, 0, 0)
148
149How long ago has the millennium changed?
150
151.. doctest:: relativedelta
152    :options: +NORMALIZE_WHITESPACE
153
154    >>> relativedelta(NOW, date(2001,1,1))
155    relativedelta(years=+2, months=+8, days=+16,
156                  hours=+20, minutes=+54, seconds=+47, microseconds=+282310)
157
158How old is John?
159
160.. doctest:: relativedelta
161    :options: +NORMALIZE_WHITESPACE
162
163    >>> johnbirthday = datetime(1978, 4, 5, 12, 0)
164    >>> relativedelta(NOW, johnbirthday)
165    relativedelta(years=+25, months=+5, days=+12,
166              hours=+8, minutes=+54, seconds=+47, microseconds=+282310)
167
168It works with dates too.
169
170.. doctest:: relativedelta
171
172    >>> relativedelta(TODAY, johnbirthday)
173    relativedelta(years=+25, months=+5, days=+11, hours=+12)
174
175Obtain today's date using the yearday:
176
177.. doctest:: relativedelta
178
179    >>> date(2003, 1, 1)+relativedelta(yearday=260)
180    datetime.date(2003, 9, 17)
181
182We can use today's date, since yearday should be absolute
183in the given year:
184
185.. doctest:: relativedelta
186
187    >>> TODAY+relativedelta(yearday=260)
188    datetime.date(2003, 9, 17)
189
190Last year it should be in the same day:
191
192.. doctest:: relativedelta
193
194    >>> date(2002, 1, 1)+relativedelta(yearday=260)
195    datetime.date(2002, 9, 17)
196
197But not in a leap year:
198
199.. doctest:: relativedelta
200
201    >>> date(2000, 1, 1)+relativedelta(yearday=260)
202    datetime.date(2000, 9, 16)
203
204We can use the non-leap year day to ignore this:
205
206.. doctest:: relativedelta
207
208    >>> date(2000, 1, 1)+relativedelta(nlyearday=260)
209    datetime.date(2000, 9, 17)
210
211rrule examples
212--------------
213These examples were converted from the RFC.
214
215Prepare the environment.
216
217.. testsetup:: rrule
218
219    from dateutil.rrule import *
220    from dateutil.parser import *
221    from datetime import *
222    import pprint
223    import sys
224    sys.displayhook = pprint.pprint
225
226.. doctest:: rrule
227
228    >>> from dateutil.rrule import *
229    >>> from dateutil.parser import *
230    >>> from datetime import *
231
232    >>> import pprint
233    >>> import sys
234    >>> sys.displayhook = pprint.pprint
235
236Daily, for 10 occurrences.
237
238.. doctest:: rrule
239   :options: +NORMALIZE_WHITESPACE
240
241    >>> list(rrule(DAILY, count=10,
242    ...            dtstart=parse("19970902T090000")))
243    [datetime.datetime(1997, 9, 2, 9, 0),
244     datetime.datetime(1997, 9, 3, 9, 0),
245     datetime.datetime(1997, 9, 4, 9, 0),
246     datetime.datetime(1997, 9, 5, 9, 0),
247     datetime.datetime(1997, 9, 6, 9, 0),
248     datetime.datetime(1997, 9, 7, 9, 0),
249     datetime.datetime(1997, 9, 8, 9, 0),
250     datetime.datetime(1997, 9, 9, 9, 0),
251     datetime.datetime(1997, 9, 10, 9, 0),
252     datetime.datetime(1997, 9, 11, 9, 0)]
253
254Daily until December 24, 1997
255
256.. doctest:: rrule
257   :options: +NORMALIZE_WHITESPACE, +ELLIPSIS
258
259    >>> list(rrule(DAILY,
260    ...            dtstart=parse("19970902T090000"),
261    ...            until=parse("19971224T000000")))
262    [datetime.datetime(1997, 9, 2, 9, 0),
263     datetime.datetime(1997, 9, 3, 9, 0),
264     datetime.datetime(1997, 9, 4, 9, 0),
265     ...
266     datetime.datetime(1997, 12, 21, 9, 0),
267     datetime.datetime(1997, 12, 22, 9, 0),
268     datetime.datetime(1997, 12, 23, 9, 0)]
269
270Every other day, 5 occurrences.
271
272.. doctest:: rrule
273   :options: +NORMALIZE_WHITESPACE
274
275    >>> list(rrule(DAILY, interval=2, count=5,
276    ...            dtstart=parse("19970902T090000")))
277    [datetime.datetime(1997, 9, 2, 9, 0),
278     datetime.datetime(1997, 9, 4, 9, 0),
279     datetime.datetime(1997, 9, 6, 9, 0),
280     datetime.datetime(1997, 9, 8, 9, 0),
281     datetime.datetime(1997, 9, 10, 9, 0)]
282
283Every 10 days, 5 occurrences.
284
285.. doctest:: rrule
286   :options: +NORMALIZE_WHITESPACE
287
288    >>> list(rrule(DAILY, interval=10, count=5,
289    ...            dtstart=parse("19970902T090000")))
290    [datetime.datetime(1997, 9, 2, 9, 0),
291     datetime.datetime(1997, 9, 12, 9, 0),
292     datetime.datetime(1997, 9, 22, 9, 0),
293     datetime.datetime(1997, 10, 2, 9, 0),
294     datetime.datetime(1997, 10, 12, 9, 0)]
295
296Everyday in January, for 3 years.
297
298.. doctest:: rrule
299   :options: +NORMALIZE_WHITESPACE, +ELLIPSIS
300
301    >>> list(rrule(YEARLY, bymonth=1, byweekday=range(7),
302    ...            dtstart=parse("19980101T090000"),
303    ...            until=parse("20000131T090000")))
304    [datetime.datetime(1998, 1, 1, 9, 0),
305     datetime.datetime(1998, 1, 2, 9, 0),
306     ...
307     datetime.datetime(1998, 1, 30, 9, 0),
308     datetime.datetime(1998, 1, 31, 9, 0),
309     datetime.datetime(1999, 1, 1, 9, 0),
310     datetime.datetime(1999, 1, 2, 9, 0),
311     ...
312     datetime.datetime(1999, 1, 30, 9, 0),
313     datetime.datetime(1999, 1, 31, 9, 0),
314     datetime.datetime(2000, 1, 1, 9, 0),
315     datetime.datetime(2000, 1, 2, 9, 0),
316     ...
317     datetime.datetime(2000, 1, 30, 9, 0),
318     datetime.datetime(2000, 1, 31, 9, 0)]
319
320Same thing, in another way.
321
322.. doctest:: rrule
323   :options: +NORMALIZE_WHITESPACE, +ELLIPSIS
324
325    >>> list(rrule(DAILY, bymonth=1,
326    ...            dtstart=parse("19980101T090000"),
327    ...            until=parse("20000131T090000")))
328    [datetime.datetime(1998, 1, 1, 9, 0),
329     ...
330     datetime.datetime(2000, 1, 31, 9, 0)]
331
332Weekly for 10 occurrences.
333
334.. doctest:: rrule
335   :options: +NORMALIZE_WHITESPACE
336
337    >>> list(rrule(WEEKLY, count=10,
338    ...            dtstart=parse("19970902T090000")))
339    [datetime.datetime(1997, 9, 2, 9, 0),
340     datetime.datetime(1997, 9, 9, 9, 0),
341     datetime.datetime(1997, 9, 16, 9, 0),
342     datetime.datetime(1997, 9, 23, 9, 0),
343     datetime.datetime(1997, 9, 30, 9, 0),
344     datetime.datetime(1997, 10, 7, 9, 0),
345     datetime.datetime(1997, 10, 14, 9, 0),
346     datetime.datetime(1997, 10, 21, 9, 0),
347     datetime.datetime(1997, 10, 28, 9, 0),
348     datetime.datetime(1997, 11, 4, 9, 0)]
349
350Every other week, 6 occurrences.
351
352.. doctest:: rrule
353   :options: +NORMALIZE_WHITESPACE
354
355    >>> list(rrule(WEEKLY, interval=2, count=6,
356    ...            dtstart=parse("19970902T090000")))
357    [datetime.datetime(1997, 9, 2, 9, 0),
358     datetime.datetime(1997, 9, 16, 9, 0),
359     datetime.datetime(1997, 9, 30, 9, 0),
360     datetime.datetime(1997, 10, 14, 9, 0),
361     datetime.datetime(1997, 10, 28, 9, 0),
362     datetime.datetime(1997, 11, 11, 9, 0)]
363
364Weekly on Tuesday and Thursday for 5 weeks.
365
366.. doctest:: rrule
367   :options: +NORMALIZE_WHITESPACE
368
369    >>> list(rrule(WEEKLY, count=10, wkst=SU, byweekday=(TU,TH),
370    ...            dtstart=parse("19970902T090000")))
371    [datetime.datetime(1997, 9, 2, 9, 0),
372     datetime.datetime(1997, 9, 4, 9, 0),
373     datetime.datetime(1997, 9, 9, 9, 0),
374     datetime.datetime(1997, 9, 11, 9, 0),
375     datetime.datetime(1997, 9, 16, 9, 0),
376     datetime.datetime(1997, 9, 18, 9, 0),
377     datetime.datetime(1997, 9, 23, 9, 0),
378     datetime.datetime(1997, 9, 25, 9, 0),
379     datetime.datetime(1997, 9, 30, 9, 0),
380     datetime.datetime(1997, 10, 2, 9, 0)]
381
382Every other week on Tuesday and Thursday, for 8 occurrences.
383
384.. doctest:: rrule
385   :options: +NORMALIZE_WHITESPACE
386
387    >>> list(rrule(WEEKLY, interval=2, count=8,
388    ...            wkst=SU, byweekday=(TU,TH),
389    ...            dtstart=parse("19970902T090000")))
390    [datetime.datetime(1997, 9, 2, 9, 0),
391     datetime.datetime(1997, 9, 4, 9, 0),
392     datetime.datetime(1997, 9, 16, 9, 0),
393     datetime.datetime(1997, 9, 18, 9, 0),
394     datetime.datetime(1997, 9, 30, 9, 0),
395     datetime.datetime(1997, 10, 2, 9, 0),
396     datetime.datetime(1997, 10, 14, 9, 0),
397     datetime.datetime(1997, 10, 16, 9, 0)]
398
399Monthly on the 1st Friday for ten occurrences.
400
401.. doctest:: rrule
402   :options: +NORMALIZE_WHITESPACE
403
404    >>> list(rrule(MONTHLY, count=10, byweekday=FR(1),
405    ...            dtstart=parse("19970905T090000")))
406    [datetime.datetime(1997, 9, 5, 9, 0),
407     datetime.datetime(1997, 10, 3, 9, 0),
408     datetime.datetime(1997, 11, 7, 9, 0),
409     datetime.datetime(1997, 12, 5, 9, 0),
410     datetime.datetime(1998, 1, 2, 9, 0),
411     datetime.datetime(1998, 2, 6, 9, 0),
412     datetime.datetime(1998, 3, 6, 9, 0),
413     datetime.datetime(1998, 4, 3, 9, 0),
414     datetime.datetime(1998, 5, 1, 9, 0),
415     datetime.datetime(1998, 6, 5, 9, 0)]
416
417Every other month on the 1st and last Sunday of the month for 10 occurrences.
418
419.. doctest:: rrule
420   :options: +NORMALIZE_WHITESPACE
421
422    >>> list(rrule(MONTHLY, interval=2, count=10,
423    ...            byweekday=(SU(1), SU(-1)),
424    ...            dtstart=parse("19970907T090000")))
425    [datetime.datetime(1997, 9, 7, 9, 0),
426     datetime.datetime(1997, 9, 28, 9, 0),
427     datetime.datetime(1997, 11, 2, 9, 0),
428     datetime.datetime(1997, 11, 30, 9, 0),
429     datetime.datetime(1998, 1, 4, 9, 0),
430     datetime.datetime(1998, 1, 25, 9, 0),
431     datetime.datetime(1998, 3, 1, 9, 0),
432     datetime.datetime(1998, 3, 29, 9, 0),
433     datetime.datetime(1998, 5, 3, 9, 0),
434     datetime.datetime(1998, 5, 31, 9, 0)]
435
436Monthly on the second to last Monday of the month for 6 months.
437
438.. doctest:: rrule
439   :options: +NORMALIZE_WHITESPACE
440
441    >>> list(rrule(MONTHLY, count=6, byweekday=MO(-2),
442    ...            dtstart=parse("19970922T090000")))
443    [datetime.datetime(1997, 9, 22, 9, 0),
444     datetime.datetime(1997, 10, 20, 9, 0),
445     datetime.datetime(1997, 11, 17, 9, 0),
446     datetime.datetime(1997, 12, 22, 9, 0),
447     datetime.datetime(1998, 1, 19, 9, 0),
448     datetime.datetime(1998, 2, 16, 9, 0)]
449
450
451Monthly on the third to the last day of the month, for 6 months.
452
453.. doctest:: rrule
454   :options: +NORMALIZE_WHITESPACE
455
456    >>> list(rrule(MONTHLY, count=6, bymonthday=-3,
457    ...            dtstart=parse("19970928T090000")))
458    [datetime.datetime(1997, 9, 28, 9, 0),
459     datetime.datetime(1997, 10, 29, 9, 0),
460     datetime.datetime(1997, 11, 28, 9, 0),
461     datetime.datetime(1997, 12, 29, 9, 0),
462     datetime.datetime(1998, 1, 29, 9, 0),
463     datetime.datetime(1998, 2, 26, 9, 0)]
464
465
466Monthly on the 2nd and 15th of the month for 5 occurrences.
467
468.. doctest:: rrule
469   :options: +NORMALIZE_WHITESPACE
470
471    >>> list(rrule(MONTHLY, count=5, bymonthday=(2,15),
472    ...            dtstart=parse("19970902T090000")))
473    [datetime.datetime(1997, 9, 2, 9, 0),
474     datetime.datetime(1997, 9, 15, 9, 0),
475     datetime.datetime(1997, 10, 2, 9, 0),
476     datetime.datetime(1997, 10, 15, 9, 0),
477     datetime.datetime(1997, 11, 2, 9, 0)]
478
479
480Monthly on the first and last day of the month for 3 occurrences.
481
482.. doctest:: rrule
483   :options: +NORMALIZE_WHITESPACE
484
485    >>> list(rrule(MONTHLY, count=5, bymonthday=(-1,1,),
486    ...            dtstart=parse("19970902T090000")))
487    [datetime.datetime(1997, 9, 30, 9, 0),
488     datetime.datetime(1997, 10, 1, 9, 0),
489     datetime.datetime(1997, 10, 31, 9, 0),
490     datetime.datetime(1997, 11, 1, 9, 0),
491     datetime.datetime(1997, 11, 30, 9, 0)]
492
493
494Every 18 months on the 10th thru 15th of the month for 10 occurrences.
495
496.. doctest:: rrule
497   :options: +NORMALIZE_WHITESPACE
498
499    >>> list(rrule(MONTHLY, interval=18, count=10,
500    ...            bymonthday=range(10,16),
501    ...            dtstart=parse("19970910T090000")))
502    [datetime.datetime(1997, 9, 10, 9, 0),
503     datetime.datetime(1997, 9, 11, 9, 0),
504     datetime.datetime(1997, 9, 12, 9, 0),
505     datetime.datetime(1997, 9, 13, 9, 0),
506     datetime.datetime(1997, 9, 14, 9, 0),
507     datetime.datetime(1997, 9, 15, 9, 0),
508     datetime.datetime(1999, 3, 10, 9, 0),
509     datetime.datetime(1999, 3, 11, 9, 0),
510     datetime.datetime(1999, 3, 12, 9, 0),
511     datetime.datetime(1999, 3, 13, 9, 0)]
512
513
514Every Tuesday, every other month, 6 occurences.
515
516.. doctest:: rrule
517   :options: +NORMALIZE_WHITESPACE
518
519    >>> list(rrule(MONTHLY, interval=2, count=6, byweekday=TU,
520    ...            dtstart=parse("19970902T090000")))
521    [datetime.datetime(1997, 9, 2, 9, 0),
522     datetime.datetime(1997, 9, 9, 9, 0),
523     datetime.datetime(1997, 9, 16, 9, 0),
524     datetime.datetime(1997, 9, 23, 9, 0),
525     datetime.datetime(1997, 9, 30, 9, 0),
526     datetime.datetime(1997, 11, 4, 9, 0)]
527
528
529Yearly in June and July for 10 occurrences.
530
531.. doctest:: rrule
532   :options: +NORMALIZE_WHITESPACE
533
534    >>> list(rrule(YEARLY, count=4, bymonth=(6,7),
535    ...            dtstart=parse("19970610T090000")))
536    [datetime.datetime(1997, 6, 10, 9, 0),
537     datetime.datetime(1997, 7, 10, 9, 0),
538     datetime.datetime(1998, 6, 10, 9, 0),
539     datetime.datetime(1998, 7, 10, 9, 0)]
540
541
542Every 3rd year on the 1st, 100th and 200th day for 4 occurrences.
543
544.. doctest:: rrule
545   :options: +NORMALIZE_WHITESPACE
546
547    >>> list(rrule(YEARLY, count=4, interval=3, byyearday=(1,100,200),
548    ...            dtstart=parse("19970101T090000")))
549    [datetime.datetime(1997, 1, 1, 9, 0),
550     datetime.datetime(1997, 4, 10, 9, 0),
551     datetime.datetime(1997, 7, 19, 9, 0),
552     datetime.datetime(2000, 1, 1, 9, 0)]
553
554
555Every 20th Monday of the year, 3 occurrences.
556
557.. doctest:: rrule
558   :options: +NORMALIZE_WHITESPACE
559
560    >>> list(rrule(YEARLY, count=3, byweekday=MO(20),
561    ...            dtstart=parse("19970519T090000")))
562    [datetime.datetime(1997, 5, 19, 9, 0),
563     datetime.datetime(1998, 5, 18, 9, 0),
564     datetime.datetime(1999, 5, 17, 9, 0)]
565
566
567Monday of week number 20 (where the default start of the week is Monday),
5683 occurrences.
569
570.. doctest:: rrule
571   :options: +NORMALIZE_WHITESPACE
572
573    >>> list(rrule(YEARLY, count=3, byweekno=20, byweekday=MO,
574    ...            dtstart=parse("19970512T090000")))
575    [datetime.datetime(1997, 5, 12, 9, 0),
576     datetime.datetime(1998, 5, 11, 9, 0),
577     datetime.datetime(1999, 5, 17, 9, 0)]
578
579
580The week number 1 may be in the last year.
581
582.. doctest:: rrule
583   :options: +NORMALIZE_WHITESPACE
584
585    >>> list(rrule(WEEKLY, count=3, byweekno=1, byweekday=MO,
586    ...            dtstart=parse("19970902T090000")))
587    [datetime.datetime(1997, 12, 29, 9, 0),
588     datetime.datetime(1999, 1, 4, 9, 0),
589     datetime.datetime(2000, 1, 3, 9, 0)]
590
591
592And the week numbers greater than 51 may be in the next year.
593
594.. doctest:: rrule
595   :options: +NORMALIZE_WHITESPACE
596
597    >>> list(rrule(WEEKLY, count=3, byweekno=52, byweekday=SU,
598    ...            dtstart=parse("19970902T090000")))
599    [datetime.datetime(1997, 12, 28, 9, 0),
600     datetime.datetime(1998, 12, 27, 9, 0),
601     datetime.datetime(2000, 1, 2, 9, 0)]
602
603
604Only some years have week number 53:
605
606.. doctest:: rrule
607   :options: +NORMALIZE_WHITESPACE
608
609    >>> list(rrule(WEEKLY, count=3, byweekno=53, byweekday=MO,
610    ...            dtstart=parse("19970902T090000")))
611    [datetime.datetime(1998, 12, 28, 9, 0),
612     datetime.datetime(2004, 12, 27, 9, 0),
613     datetime.datetime(2009, 12, 28, 9, 0)]
614
615
616Every Friday the 13th, 4 occurrences.
617
618.. doctest:: rrule
619   :options: +NORMALIZE_WHITESPACE
620
621    >>> list(rrule(YEARLY, count=4, byweekday=FR, bymonthday=13,
622    ...            dtstart=parse("19970902T090000")))
623    [datetime.datetime(1998, 2, 13, 9, 0),
624     datetime.datetime(1998, 3, 13, 9, 0),
625     datetime.datetime(1998, 11, 13, 9, 0),
626     datetime.datetime(1999, 8, 13, 9, 0)]
627
628
629Every four years, the first Tuesday after a Monday in November,
6303 occurrences (U.S. Presidential Election day):
631
632.. doctest:: rrule
633   :options: +NORMALIZE_WHITESPACE
634
635    >>> list(rrule(YEARLY, interval=4, count=3, bymonth=11,
636    ...            byweekday=TU, bymonthday=(2,3,4,5,6,7,8),
637    ...            dtstart=parse("19961105T090000")))
638    [datetime.datetime(1996, 11, 5, 9, 0),
639     datetime.datetime(2000, 11, 7, 9, 0),
640     datetime.datetime(2004, 11, 2, 9, 0)]
641
642
643The 3rd instance into the month of one of Tuesday, Wednesday or
644Thursday, for the next 3 months:
645
646.. doctest:: rrule
647   :options: +NORMALIZE_WHITESPACE
648
649    >>> list(rrule(MONTHLY, count=3, byweekday=(TU,WE,TH),
650    ...            bysetpos=3, dtstart=parse("19970904T090000")))
651    [datetime.datetime(1997, 9, 4, 9, 0),
652     datetime.datetime(1997, 10, 7, 9, 0),
653     datetime.datetime(1997, 11, 6, 9, 0)]
654
655
656The 2nd to last weekday of the month, 3 occurrences.
657
658.. doctest:: rrule
659   :options: +NORMALIZE_WHITESPACE
660
661    >>> list(rrule(MONTHLY, count=3, byweekday=(MO,TU,WE,TH,FR),
662    ...            bysetpos=-2, dtstart=parse("19970929T090000")))
663    [datetime.datetime(1997, 9, 29, 9, 0),
664     datetime.datetime(1997, 10, 30, 9, 0),
665     datetime.datetime(1997, 11, 27, 9, 0)]
666
667
668Every 3 hours from 9:00 AM to 5:00 PM on a specific day.
669
670.. doctest:: rrule
671   :options: +NORMALIZE_WHITESPACE
672
673    >>> list(rrule(HOURLY, interval=3,
674    ...            dtstart=parse("19970902T090000"),
675    ...            until=parse("19970902T170000")))
676    [datetime.datetime(1997, 9, 2, 9, 0),
677     datetime.datetime(1997, 9, 2, 12, 0),
678     datetime.datetime(1997, 9, 2, 15, 0)]
679
680
681Every 15 minutes for 6 occurrences.
682
683.. doctest:: rrule
684   :options: +NORMALIZE_WHITESPACE
685
686    >>> list(rrule(MINUTELY, interval=15, count=6,
687    ...            dtstart=parse("19970902T090000")))
688    [datetime.datetime(1997, 9, 2, 9, 0),
689     datetime.datetime(1997, 9, 2, 9, 15),
690     datetime.datetime(1997, 9, 2, 9, 30),
691     datetime.datetime(1997, 9, 2, 9, 45),
692     datetime.datetime(1997, 9, 2, 10, 0),
693     datetime.datetime(1997, 9, 2, 10, 15)]
694
695
696Every hour and a half for 4 occurrences.
697
698.. doctest:: rrule
699   :options: +NORMALIZE_WHITESPACE
700
701    >>> list(rrule(MINUTELY, interval=90, count=4,
702    ...            dtstart=parse("19970902T090000")))
703    [datetime.datetime(1997, 9, 2, 9, 0),
704     datetime.datetime(1997, 9, 2, 10, 30),
705     datetime.datetime(1997, 9, 2, 12, 0),
706     datetime.datetime(1997, 9, 2, 13, 30)]
707
708
709Every 20 minutes from 9:00 AM to 4:40 PM for two days.
710
711.. doctest:: rrule
712   :options: +NORMALIZE_WHITESPACE, +ELLIPSIS
713
714    >>> list(rrule(MINUTELY, interval=20, count=48,
715    ...            byhour=range(9,17), byminute=(0,20,40),
716    ...            dtstart=parse("19970902T090000")))
717    [datetime.datetime(1997, 9, 2, 9, 0),
718     datetime.datetime(1997, 9, 2, 9, 20),
719     ...
720     datetime.datetime(1997, 9, 2, 16, 20),
721     datetime.datetime(1997, 9, 2, 16, 40),
722     datetime.datetime(1997, 9, 3, 9, 0),
723     datetime.datetime(1997, 9, 3, 9, 20),
724     ...
725     datetime.datetime(1997, 9, 3, 16, 20),
726     datetime.datetime(1997, 9, 3, 16, 40)]
727
728
729An example where the days generated makes a difference because of `wkst`.
730
731.. doctest:: rrule
732   :options: +NORMALIZE_WHITESPACE
733
734    >>> list(rrule(WEEKLY, interval=2, count=4,
735    ...            byweekday=(TU,SU), wkst=MO,
736    ...            dtstart=parse("19970805T090000")))
737    [datetime.datetime(1997, 8, 5, 9, 0),
738     datetime.datetime(1997, 8, 10, 9, 0),
739     datetime.datetime(1997, 8, 19, 9, 0),
740     datetime.datetime(1997, 8, 24, 9, 0)]
741
742    >>> list(rrule(WEEKLY, interval=2, count=4,
743    ...            byweekday=(TU,SU), wkst=SU,
744    ...            dtstart=parse("19970805T090000")))
745    [datetime.datetime(1997, 8, 5, 9, 0),
746     datetime.datetime(1997, 8, 17, 9, 0),
747     datetime.datetime(1997, 8, 19, 9, 0),
748     datetime.datetime(1997, 8, 31, 9, 0)]
749
750
751rruleset examples
752-----------------
753Daily, for 7 days, jumping Saturday and Sunday occurrences.
754
755.. testsetup:: rruleset
756
757    import datetime
758
759    from dateutil.parser import parse
760    from dateutil.rrule import rrule, rruleset
761    from dateutil.rrule import YEARLY, MONTHLY, WEEKLY, DAILY
762    from dateutil.rrule import MO, TU, WE, TH, FR, SA, SU
763
764    import pprint
765    import sys
766    sys.displayhook = pprint.pprint
767
768.. doctest:: rruleset
769   :options: +NORMALIZE_WHITESPACE
770
771    >>> set = rruleset()
772    >>> set.rrule(rrule(DAILY, count=7,
773    ...                 dtstart=parse("19970902T090000")))
774    >>> set.exrule(rrule(YEARLY, byweekday=(SA,SU),
775    ...                  dtstart=parse("19970902T090000")))
776    >>> list(set)
777    [datetime.datetime(1997, 9, 2, 9, 0),
778     datetime.datetime(1997, 9, 3, 9, 0),
779     datetime.datetime(1997, 9, 4, 9, 0),
780     datetime.datetime(1997, 9, 5, 9, 0),
781     datetime.datetime(1997, 9, 8, 9, 0)]
782
783
784Weekly, for 4 weeks, plus one time on day 7, and not on day 16.
785
786.. doctest:: rruleset
787   :options: +NORMALIZE_WHITESPACE
788
789    >>> set = rruleset()
790    >>> set.rrule(rrule(WEEKLY, count=4,
791    ...           dtstart=parse("19970902T090000")))
792    >>> set.rdate(datetime.datetime(1997, 9, 7, 9, 0))
793    >>> set.exdate(datetime.datetime(1997, 9, 16, 9, 0))
794    >>> list(set)
795    [datetime.datetime(1997, 9, 2, 9, 0),
796     datetime.datetime(1997, 9, 7, 9, 0),
797     datetime.datetime(1997, 9, 9, 9, 0),
798     datetime.datetime(1997, 9, 23, 9, 0)]
799
800
801rrulestr() examples
802-------------------
803
804Every 10 days, 5 occurrences.
805
806.. testsetup:: rrulestr
807
808    from dateutil.parser import parse
809    from dateutil.rrule import rruleset, rrulestr
810
811    import pprint
812    import sys
813    sys.displayhook = pprint.pprint
814
815.. doctest:: rrulestr
816   :options: +NORMALIZE_WHITESPACE
817
818    >>> list(rrulestr("""
819    ... DTSTART:19970902T090000
820    ... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5
821    ... """))
822    [datetime.datetime(1997, 9, 2, 9, 0),
823     datetime.datetime(1997, 9, 12, 9, 0),
824     datetime.datetime(1997, 9, 22, 9, 0),
825     datetime.datetime(1997, 10, 2, 9, 0),
826     datetime.datetime(1997, 10, 12, 9, 0)]
827
828
829Same thing, but passing only the `RRULE` value.
830
831.. doctest:: rrulestr
832   :options: +NORMALIZE_WHITESPACE
833
834    >>> list(rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5",
835    ...               dtstart=parse("19970902T090000")))
836    [datetime.datetime(1997, 9, 2, 9, 0),
837     datetime.datetime(1997, 9, 12, 9, 0),
838     datetime.datetime(1997, 9, 22, 9, 0),
839     datetime.datetime(1997, 10, 2, 9, 0),
840     datetime.datetime(1997, 10, 12, 9, 0)]
841
842
843Notice that when using a single rule, it returns an
844`rrule` instance, unless `forceset` was used.
845
846.. doctest:: rrulestr
847   :options: +ELLIPSIS
848
849    >>> rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5")
850    <dateutil.rrule.rrule object at 0x...>
851
852    >>> rrulestr("""
853    ... DTSTART:19970902T090000
854    ... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5
855    ... """)
856    <dateutil.rrule.rrule object at 0x...>
857
858    >>> rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5", forceset=True)
859    <dateutil.rrule.rruleset object at 0x...>
860
861
862But when an `rruleset` is needed, it is automatically used.
863
864.. doctest:: rrulestr
865   :options: +ELLIPSIS
866
867    >>> rrulestr("""
868    ... DTSTART:19970902T090000
869    ... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5
870    ... RRULE:FREQ=DAILY;INTERVAL=5;COUNT=3
871    ... """)
872    <dateutil.rrule.rruleset object at 0x...>
873
874
875parse examples
876--------------
877The following code will prepare the environment:
878
879.. doctest:: tz
880
881    >>> from dateutil.parser import *
882    >>> from dateutil.tz import *
883    >>> from datetime import *
884    >>> TZOFFSETS = {"BRST": -10800}
885    >>> BRSTTZ = tzoffset("BRST", -10800)
886    >>> DEFAULT = datetime(2003, 9, 25)
887
888
889Some simple examples based on the `date` command, using the
890`ZOFFSET` dictionary to provide the BRST timezone offset.
891
892.. doctest:: tz
893    :options: +NORMALIZE_WHITESPACE
894
895    >>> parse("Thu Sep 25 10:36:28 BRST 2003", tzinfos=TZOFFSETS)
896    datetime.datetime(2003, 9, 25, 10, 36, 28,
897              tzinfo=tzoffset('BRST', -10800))
898
899    >>> parse("2003 10:36:28 BRST 25 Sep Thu", tzinfos=TZOFFSETS)
900    datetime.datetime(2003, 9, 25, 10, 36, 28,
901              tzinfo=tzoffset('BRST', -10800))
902
903
904Notice that since BRST is my local timezone, parsing it without
905further timezone settings will yield a `tzlocal` timezone.
906
907.. doctest:: tz
908
909    >>> parse("Thu Sep 25 10:36:28 BRST 2003")
910    datetime.datetime(2003, 9, 25, 10, 36, 28, tzinfo=tzlocal())
911
912
913We can also ask to ignore the timezone explicitly:
914
915.. doctest:: tz
916
917    >>> parse("Thu Sep 25 10:36:28 BRST 2003", ignoretz=True)
918    datetime.datetime(2003, 9, 25, 10, 36, 28)
919
920
921That's the same as processing a string without timezone:
922
923.. doctest:: tz
924
925    >>> parse("Thu Sep 25 10:36:28 2003")
926    datetime.datetime(2003, 9, 25, 10, 36, 28)
927
928
929Without the year, but passing our `DEFAULT` datetime to return
930the same year, no mattering what year we currently are in:
931
932.. doctest:: tz
933
934    >>> parse("Thu Sep 25 10:36:28", default=DEFAULT)
935    datetime.datetime(2003, 9, 25, 10, 36, 28)
936
937
938Strip it further:
939
940.. doctest:: tz
941
942    >>> parse("Thu Sep 10:36:28", default=DEFAULT)
943    datetime.datetime(2003, 9, 25, 10, 36, 28)
944
945    >>> parse("Thu 10:36:28", default=DEFAULT)
946    datetime.datetime(2003, 9, 25, 10, 36, 28)
947
948    >>> parse("Thu 10:36", default=DEFAULT)
949    datetime.datetime(2003, 9, 25, 10, 36)
950
951    >>> parse("10:36", default=DEFAULT)
952    datetime.datetime(2003, 9, 25, 10, 36)
953
954
955Strip in a different way:
956
957.. doctest:: tz
958
959    >>> parse("Thu Sep 25 2003")
960    datetime.datetime(2003, 9, 25, 0, 0)
961
962    >>> parse("Sep 25 2003")
963    datetime.datetime(2003, 9, 25, 0, 0)
964
965    >>> parse("Sep 2003", default=DEFAULT)
966    datetime.datetime(2003, 9, 25, 0, 0)
967
968    >>> parse("Sep", default=DEFAULT)
969    datetime.datetime(2003, 9, 25, 0, 0)
970
971    >>> parse("2003", default=DEFAULT)
972    datetime.datetime(2003, 9, 25, 0, 0)
973
974
975Another format, based on `date -R` (RFC822):
976
977.. doctest:: tz
978   :options: +NORMALIZE_WHITESPACE
979
980    >>> parse("Thu, 25 Sep 2003 10:49:41 -0300")
981    datetime.datetime(2003, 9, 25, 10, 49, 41,
982              tzinfo=tzoffset(None, -10800))
983
984
985ISO format:
986
987.. doctest:: tz
988   :options: +NORMALIZE_WHITESPACE
989
990    >>> parse("2003-09-25T10:49:41.5-03:00")
991    datetime.datetime(2003, 9, 25, 10, 49, 41, 500000,
992              tzinfo=tzoffset(None, -10800))
993
994
995Some variations:
996
997.. doctest:: tz
998
999    >>> parse("2003-09-25T10:49:41")
1000    datetime.datetime(2003, 9, 25, 10, 49, 41)
1001
1002    >>> parse("2003-09-25T10:49")
1003    datetime.datetime(2003, 9, 25, 10, 49)
1004
1005    >>> parse("2003-09-25T10")
1006    datetime.datetime(2003, 9, 25, 10, 0)
1007
1008    >>> parse("2003-09-25")
1009    datetime.datetime(2003, 9, 25, 0, 0)
1010
1011
1012ISO format, without separators:
1013
1014.. doctest:: tz
1015   :options: +NORMALIZE_WHITESPACE
1016
1017    >>> parse("20030925T104941.5-0300")
1018    datetime.datetime(2003, 9, 25, 10, 49, 41, 500000,
1019                      tzinfo=tzoffset(None, -10800))
1020
1021    >>> parse("20030925T104941-0300")
1022    datetime.datetime(2003, 9, 25, 10, 49, 41,
1023              tzinfo=tzoffset(None, -10800))
1024
1025    >>> parse("20030925T104941")
1026    datetime.datetime(2003, 9, 25, 10, 49, 41)
1027
1028    >>> parse("20030925T1049")
1029    datetime.datetime(2003, 9, 25, 10, 49)
1030
1031    >>> parse("20030925T10")
1032    datetime.datetime(2003, 9, 25, 10, 0)
1033
1034    >>> parse("20030925")
1035    datetime.datetime(2003, 9, 25, 0, 0)
1036
1037
1038Everything together.
1039
1040.. doctest:: tz
1041
1042    >>> parse("199709020900")
1043    datetime.datetime(1997, 9, 2, 9, 0)
1044    >>> parse("19970902090059")
1045    datetime.datetime(1997, 9, 2, 9, 0, 59)
1046
1047
1048Different date orderings:
1049
1050.. doctest:: tz
1051
1052    >>> parse("2003-09-25")
1053    datetime.datetime(2003, 9, 25, 0, 0)
1054
1055    >>> parse("2003-Sep-25")
1056    datetime.datetime(2003, 9, 25, 0, 0)
1057
1058    >>> parse("25-Sep-2003")
1059    datetime.datetime(2003, 9, 25, 0, 0)
1060
1061    >>> parse("Sep-25-2003")
1062    datetime.datetime(2003, 9, 25, 0, 0)
1063
1064    >>> parse("09-25-2003")
1065    datetime.datetime(2003, 9, 25, 0, 0)
1066
1067    >>> parse("25-09-2003")
1068    datetime.datetime(2003, 9, 25, 0, 0)
1069
1070
1071Check some ambiguous dates:
1072
1073.. doctest:: tz
1074
1075    >>> parse("10-09-2003")
1076    datetime.datetime(2003, 10, 9, 0, 0)
1077
1078    >>> parse("10-09-2003", dayfirst=True)
1079    datetime.datetime(2003, 9, 10, 0, 0)
1080
1081    >>> parse("10-09-03")
1082    datetime.datetime(2003, 10, 9, 0, 0)
1083
1084    >>> parse("10-09-03", yearfirst=True)
1085    datetime.datetime(2010, 9, 3, 0, 0)
1086
1087
1088Other date separators are allowed:
1089
1090.. doctest:: tz
1091
1092    >>> parse("2003.Sep.25")
1093    datetime.datetime(2003, 9, 25, 0, 0)
1094
1095    >>> parse("2003/09/25")
1096    datetime.datetime(2003, 9, 25, 0, 0)
1097
1098
1099Even with spaces:
1100
1101.. doctest:: tz
1102
1103    >>> parse("2003 Sep 25")
1104    datetime.datetime(2003, 9, 25, 0, 0)
1105
1106    >>> parse("2003 09 25")
1107    datetime.datetime(2003, 9, 25, 0, 0)
1108
1109
1110Hours with letters work:
1111
1112.. doctest:: tz
1113
1114    >>> parse("10h36m28.5s", default=DEFAULT)
1115    datetime.datetime(2003, 9, 25, 10, 36, 28, 500000)
1116
1117    >>> parse("01s02h03m", default=DEFAULT)
1118    datetime.datetime(2003, 9, 25, 2, 3, 1)
1119
1120    >>> parse("01h02m03", default=DEFAULT)
1121    datetime.datetime(2003, 9, 25, 1, 2, 3)
1122
1123    >>> parse("01h02", default=DEFAULT)
1124    datetime.datetime(2003, 9, 25, 1, 2)
1125
1126    >>> parse("01h02s", default=DEFAULT)
1127    datetime.datetime(2003, 9, 25, 1, 0, 2)
1128
1129
1130With AM/PM:
1131
1132.. doctest:: tz
1133
1134    >>> parse("10h am", default=DEFAULT)
1135    datetime.datetime(2003, 9, 25, 10, 0)
1136
1137    >>> parse("10pm", default=DEFAULT)
1138    datetime.datetime(2003, 9, 25, 22, 0)
1139
1140    >>> parse("12:00am", default=DEFAULT)
1141    datetime.datetime(2003, 9, 25, 0, 0)
1142
1143    >>> parse("12pm", default=DEFAULT)
1144    datetime.datetime(2003, 9, 25, 12, 0)
1145
1146
1147Some special treating for ''pertain'' relations:
1148
1149.. doctest:: tz
1150
1151    >>> parse("Sep 03", default=DEFAULT)
1152    datetime.datetime(2003, 9, 3, 0, 0)
1153
1154    >>> parse("Sep of 03", default=DEFAULT)
1155    datetime.datetime(2003, 9, 25, 0, 0)
1156
1157
1158Fuzzy parsing:
1159
1160.. doctest:: tz
1161   :options: +NORMALIZE_WHITESPACE
1162
1163    >>> s = "Today is 25 of September of 2003, exactly " \
1164    ...     "at 10:49:41 with timezone -03:00."
1165    >>> parse(s, fuzzy=True)
1166    datetime.datetime(2003, 9, 25, 10, 49, 41,
1167              tzinfo=tzoffset(None, -10800))
1168
1169
1170Other random formats:
1171
1172.. doctest:: tz
1173
1174    >>> parse("Wed, July 10, '96")
1175    datetime.datetime(1996, 7, 10, 0, 0)
1176
1177    >>> parse("1996.07.10 AD at 15:08:56 PDT", ignoretz=True)
1178    datetime.datetime(1996, 7, 10, 15, 8, 56)
1179
1180    >>> parse("Tuesday, April 12, 1952 AD 3:30:42pm PST", ignoretz=True)
1181    datetime.datetime(1952, 4, 12, 15, 30, 42)
1182
1183    >>> parse("November 5, 1994, 8:15:30 am EST", ignoretz=True)
1184    datetime.datetime(1994, 11, 5, 8, 15, 30)
1185
1186    >>> parse("3rd of May 2001")
1187    datetime.datetime(2001, 5, 3, 0, 0)
1188
1189    >>> parse("5:50 A.M. on June 13, 1990")
1190    datetime.datetime(1990, 6, 13, 5, 50)
1191
1192
1193tzutc examples
1194--------------
1195
1196.. doctest:: tzutc
1197
1198    >>> from datetime import *
1199    >>> from dateutil.tz import *
1200
1201    >>> datetime.now()
1202    datetime.datetime(2003, 9, 27, 9, 40, 1, 521290)
1203
1204    >>> datetime.now(tzutc())
1205    datetime.datetime(2003, 9, 27, 12, 40, 12, 156379, tzinfo=tzutc())
1206
1207    >>> datetime.now(tzutc()).tzname()
1208    'UTC'
1209
1210
1211tzoffset examples
1212-----------------
1213
1214.. doctest:: tzoffset
1215   :options: +NORMALIZE_WHITESPACE
1216
1217    >>> from datetime import *
1218    >>> from dateutil.tz import *
1219
1220    >>> datetime.now(tzoffset("BRST", -10800))
1221    datetime.datetime(2003, 9, 27, 9, 52, 43, 624904,
1222              tzinfo=tzinfo=tzoffset('BRST', -10800))
1223
1224    >>> datetime.now(tzoffset("BRST", -10800)).tzname()
1225    'BRST'
1226
1227    >>> datetime.now(tzoffset("BRST", -10800)).astimezone(tzutc())
1228    datetime.datetime(2003, 9, 27, 12, 53, 11, 446419,
1229              tzinfo=tzutc())
1230
1231
1232tzlocal examples
1233----------------
1234
1235.. doctest:: tzlocal
1236
1237    >>> from datetime import *
1238    >>> from dateutil.tz import *
1239
1240    >>> datetime.now(tzlocal())
1241    datetime.datetime(2003, 9, 27, 10, 1, 43, 673605,
1242              tzinfo=tzlocal())
1243
1244    >>> datetime.now(tzlocal()).tzname()
1245    'BRST'
1246
1247    >>> datetime.now(tzlocal()).astimezone(tzoffset(None, 0))
1248    datetime.datetime(2003, 9, 27, 13, 3, 0, 11493,
1249              tzinfo=tzoffset(None, 0))
1250
1251
1252tzstr examples
1253--------------
1254Here are examples of the recognized formats:
1255
1256  * `EST5EDT`
1257  * `EST5EDT4,M4.1.0/02:00:00,M10-5-0/02:00`
1258  * `EST5EDT4,95/02:00:00,298/02:00`
1259  * `EST5EDT4,J96/02:00:00,J299/02:00`
1260
1261Notice that if daylight information is not present, but a
1262daylight abbreviation was provided, `tzstr` will follow the
1263convention of using the first sunday of April to start daylight
1264saving, and the last sunday of October to end it. If start or
1265end time is not present, 2AM will be used, and if the daylight
1266offset is not present, the standard offset plus one hour will
1267be used. This convention is the same as used in the GNU libc.
1268
1269This also means that some of the above examples are exactly
1270equivalent, and all of these examples are equivalent
1271in the year of 2003.
1272
1273Here is the example mentioned in the
1274
1275[https://docs.python.org/3/library/time.html time module documentation].
1276
1277.. testsetup:: tzstr
1278
1279    import os
1280    import time
1281    from datetime import datetime
1282    from dateutil.tz import tzstr
1283
1284.. doctest:: tzstr
1285
1286    >>> os.environ['TZ'] = 'EST+05EDT,M4.1.0,M10.5.0'
1287    >>> time.tzset()
1288    >>> time.strftime('%X %x %Z')
1289    '02:07:36 05/08/03 EDT'
1290    >>> os.environ['TZ'] = 'AEST-10AEDT-11,M10.5.0,M3.5.0'
1291    >>> time.tzset()
1292    >>> time.strftime('%X %x %Z')
1293    '16:08:12 05/08/03 AEST'
1294
1295
1296And here is an example showing the same information using `tzstr`,
1297without touching system settings.
1298
1299.. doctest:: tzstr
1300
1301    >>> tz1 = tzstr('EST+05EDT,M4.1.0,M10.5.0')
1302    >>> tz2 = tzstr('AEST-10AEDT-11,M10.5.0,M3.5.0')
1303    >>> dt = datetime(2003, 5, 8, 2, 7, 36, tzinfo=tz1)
1304    >>> dt.strftime('%X %x %Z')
1305    '02:07:36 05/08/03 EDT'
1306    >>> dt.astimezone(tz2).strftime('%X %x %Z')
1307    '16:07:36 05/08/03 AEST'
1308
1309
1310Are these really equivalent?
1311
1312.. doctest:: tzstr
1313
1314    >>> tzstr('EST5EDT') == tzstr('EST5EDT,M4.1.0,M10.5.0')
1315    True
1316
1317
1318Check the daylight limit.
1319
1320.. doctest:: tzstr
1321
1322    >>> tz = tzstr('EST+05EDT,M4.1.0,M10.5.0')
1323    >>> datetime(2003, 4, 6, 1, 59, tzinfo=tz).tzname()
1324    'EST'
1325    >>> datetime(2003, 4, 6, 2, 00, tzinfo=tz).tzname()
1326    'EDT'
1327    >>> datetime(2003, 10, 26, 0, 59, tzinfo=tz).tzname()
1328    'EDT'
1329    >>> datetime(2003, 10, 26, 2, 00, tzinfo=tz).tzname()
1330    'EST'
1331
1332
1333tzrange examples
1334----------------
1335
1336.. testsetup:: tzrange
1337
1338    from dateutil.tz import tzrange, tzstr
1339
1340.. doctest:: tzrange
1341
1342    >>> tzstr('EST5EDT') == tzrange("EST", -18000, "EDT")
1343    True
1344
1345    >>> from dateutil.relativedelta import *
1346    >>> range1 = tzrange("EST", -18000, "EDT")
1347    >>> range2 = tzrange("EST", -18000, "EDT", -14400,
1348    ...                  relativedelta(hours=+2, month=4, day=1,
1349    ...                                weekday=SU(+1)),
1350    ...                  relativedelta(hours=+1, month=10, day=31,
1351    ...                                weekday=SU(-1)))
1352    >>> tzstr('EST5EDT') == range1 == range2
1353    True
1354
1355
1356Notice a minor detail in the last example: while the DST should end
1357at 2AM, the delta will catch 1AM. That's because the daylight saving
1358time should end at 2AM standard time (the difference between STD and
1359DST is 1h in the given example) instead of the DST time. That's how
1360the `tzinfo` subtypes should deal with the extra hour that happens
1361when going back to the standard time. Check
1362
1363[https://docs.python.org/3/library/datetime.html#datetime.tzinfo tzinfo documentation]
1364
1365for more information.
1366
1367tzfile examples
1368---------------
1369
1370.. testsetup:: tzfile
1371
1372    from datetime import datetime
1373    from dateutil.tz import tzfile, tzutc
1374
1375.. doctest:: tzfile
1376   :options: +NORMALIZE_WHITESPACE
1377
1378    >>> tz = tzfile("/etc/localtime")
1379    >>> datetime.now(tz)
1380    datetime.datetime(2003, 9, 27, 12, 3, 48, 392138,
1381              tzinfo=tzfile('/etc/localtime'))
1382
1383    >>> datetime.now(tz).astimezone(tzutc())
1384    datetime.datetime(2003, 9, 27, 15, 3, 53, 70863,
1385              tzinfo=tzutc())
1386
1387    >>> datetime.now(tz).tzname()
1388    'BRST'
1389    >>> datetime(2003, 1, 1, tzinfo=tz).tzname()
1390    'BRDT'
1391
1392
1393Check the daylight limit.
1394
1395.. doctest:: tzfile
1396
1397    >>> tz = tzfile('/usr/share/zoneinfo/EST5EDT')
1398    >>> datetime(2003, 4, 6, 1, 59, tzinfo=tz).tzname()
1399    'EST'
1400    >>> datetime(2003, 4, 6, 2, 00, tzinfo=tz).tzname()
1401    'EDT'
1402    >>> datetime(2003, 10, 26, 0, 59, tzinfo=tz).tzname()
1403    'EDT'
1404    >>> datetime(2003, 10, 26, 1, 00, tzinfo=tz).tzname()
1405    'EST'
1406
1407
1408tzical examples
1409---------------
1410Here is a sample file extracted from the RFC. This file defines
1411the `EST5EDT` timezone, and will be used in the following example.
1412
1413.. include:: samples/EST5EDT.ics
1414   :literal:
1415
1416And here is an example exploring a `tzical` type:
1417
1418.. doctest:: tzfile
1419
1420    >>> from dateutil.tz import *; from datetime import *
1421
1422    >>> tz = tzical('samples/EST5EDT.ics')
1423    >>> tz.keys()
1424    ['US-Eastern']
1425
1426    >>> est = tz.get('US-Eastern')
1427    >>> est
1428    <tzicalvtz 'US-Eastern'>
1429
1430    >>> datetime.now(est)
1431    datetime.datetime(2003, 10, 6, 19, 44, 18, 667987,
1432              tzinfo=<tzicalvtz 'US-Eastern'>)
1433
1434    >>> est == tz.get()
1435    True
1436
1437
1438Let's check the daylight ranges, as usual:
1439
1440.. doctest:: tzfile
1441
1442    >>> datetime(2003, 4, 6, 1, 59, tzinfo=est).tzname()
1443    'EST'
1444    >>> datetime(2003, 4, 6, 2, 00, tzinfo=est).tzname()
1445    'EDT'
1446
1447    >>> datetime(2003, 10, 26, 0, 59, tzinfo=est).tzname()
1448    'EDT'
1449    >>> datetime(2003, 10, 26, 1, 00, tzinfo=est).tzname()
1450    'EST'
1451
1452
1453tzwin examples
1454--------------
1455
1456.. doctest:: tzwin
1457
1458    >>> tz = tzwin("E. South America Standard Time")
1459
1460
1461tzwinlocal examples
1462-------------------
1463
1464
1465.. doctest:: tzwinlocal
1466
1467    >>> tz = tzwinlocal()
1468
1469# vim:ts=4:sw=4:et
1470