~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to fai/python-dateutil-0.4/README

  • Committer: Robert Collins
  • Date: 2005-09-13 15:11:39 UTC
  • mto: (147.2.6) (364.1.3 bzrtools)
  • mto: This revision was merged to the branch mainline in revision 324.
  • Revision ID: robertc@robertcollins.net-20050913151139-9ac920fc9d7bda31
TODOification

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
## This file is in the moin format. The latest version is found
 
2
## at https://moin.conectiva.com.br/DateUtil
 
3
 
 
4
== Contents ==
 
5
[[TableOfContents]]
 
6
 
 
7
== Description ==
 
8
The '''dateutil''' module provides powerful extensions to
 
9
the standard '''datetime''' module, available in Python 2.3+.
 
10
 
 
11
== Features ==
 
12
 
 
13
  * Computing of relative deltas (next month, next year,
 
14
  next monday, last week of month, etc);
 
15
 
 
16
  * Computing of relative deltas between two given
 
17
  date and/or datetime objects;
 
18
 
 
19
  * Computing of dates based on very flexible recurrence rules,
 
20
  using a superset of the
 
21
  [ftp://ftp.rfc-editor.org/in-notes/rfc2445.txt iCalendar]
 
22
  specification. Parsing of RFC strings is supported as well.
 
23
 
 
24
  * Generic parsing of dates in almost any string format;
 
25
 
 
26
  * Timezone (tzinfo) implementations for tzfile(5) format
 
27
  files (/etc/localtime, /usr/share/zoneinfo, etc), TZ
 
28
  environment string (in all known formats), iCalendar
 
29
  format files, given ranges (with help from relative deltas),
 
30
  local machine timezone, fixed offset timezone, and UTC timezone.
 
31
 
 
32
  * Computing of Easter Sunday dates for any given year,
 
33
  using Western, Orthodox or Julian algorithms;
 
34
 
 
35
  * More than 400 test cases.
 
36
 
 
37
== Quick example ==
 
38
Here's a snapshot, just to give an idea about the power of the
 
39
package. For more examples, look at the documentation below.
 
40
 
 
41
Suppose you want to know how much time is left, in
 
42
years/months/days/etc, before the next easter happening on a
 
43
year with a Friday 13th in August, and you want to get today's
 
44
date out of the "date" unix system command. Here is the code:
 
45
{{{
 
46
from dateutil.relativedelta import *
 
47
from dateutil.easter import *
 
48
from dateutil.rrule import *
 
49
from dateutil.parser import *
 
50
from datetime import *
 
51
import commands
 
52
import os
 
53
now = parse(commands.getoutput("date"))
 
54
today = now.date()
 
55
year = rrule(FREQ_YEARLY,bymonth=8,bymonthday=13,byweekday=FR)[0].year
 
56
rdelta = relativedelta(easter(year), today)
 
57
print "Today is:", today
 
58
print "Year with next Aug 13th on a Friday is:", year
 
59
print "How far is the Easter of that year:", rdelta
 
60
print "And the Easter of that year is:", today+rdelta
 
61
}}}
 
62
 
 
63
And here's the output:
 
64
{{{
 
65
Today is: 2003-10-11
 
66
Year with next Aug 13th on a Friday is: 2004
 
67
How far is the Easter of that year: relativedelta(months=+6)
 
68
And the Easter of that year is: 2004-04-11
 
69
}}}
 
70
 
 
71
{i} It was '''really''' a coincidence :)
 
72
 
 
73
== Download ==
 
74
The following files are available.
 
75
  * attachment:python-dateutil-0.3.tar.bz2
 
76
  * attachment:python-dateutil-0.3-1cl.noarch.rpm
 
77
 
 
78
== Author ==
 
79
The dateutil module was written by GustavoNiemeyer <niemeyer@conectiva.com>.
 
80
 
 
81
== Documentation ==
 
82
The following modules are available.
 
83
 
 
84
=== relativedelta ===
 
85
This module offers the '''relativedelta''' type, which is based 
 
86
on the specification of the excelent work done by M.-A. Lemburg in his
 
87
[http://www.egenix.com/files/python/mxDateTime.html mxDateTime]
 
88
extension. However, notice that this type '''does not''' implement the
 
89
same algorithm as his work. Do not expect it to behave like
 
90
{{{mxDateTime}}}'s counterpart.
 
91
 
 
92
==== relativedelta type ====
 
93
 
 
94
There's two different ways to build a relativedelta instance. The
 
95
first one is passing it two {{{date}}}/{{{datetime}}} instances:
 
96
{{{
 
97
relativedelta(datetime1, datetime2)
 
98
}}}
 
99
 
 
100
This will build the relative difference between {{{datetime1}}} and
 
101
{{{datetime2}}}, so that the following constraint is always true:
 
102
{{{
 
103
datetime2+relativedelta(datetime1, datetime2) == datetime1
 
104
}}}
 
105
 
 
106
Notice that instead of {{{datetime}}} instances, you may use
 
107
{{{date}}} instances, or a mix of both.
 
108
 
 
109
And the other way is to use any of the following keyword arguments:
 
110
 
 
111
  year, month, day, hour, minute, seconds, microseconds::
 
112
  Absolute information.
 
113
 
 
114
  years, months, weeks, days, hours, minutes, seconds, microseconds::
 
115
  Relative information, may be negative.
 
116
 
 
117
  weekday::
 
118
  One of the weekday instances ({{{MO}}}, {{{TU}}}, etc). These
 
119
  instances may receive a parameter {{{n}}}, specifying the {{{n}}}th
 
120
  weekday, which could be positive or negative (like {{{MO(+2)}}} or
 
121
  {{{MO(-3)}}}. Not specifying it is the same as specifying {{{+1}}}.
 
122
  You can also use an integer, where {{{0=MO}}}. Notice that,
 
123
  for example, if the calculated date is already Monday, using
 
124
  {{{MO}}} or {{{MO(+1)}}} (which is the same thing in this context),
 
125
  won't change the day.
 
126
 
 
127
  leapdays::
 
128
  Will add given days to the date found, but only if the computed
 
129
  year is a leap year and the computed date is post 28 of february.
 
130
 
 
131
  yearday, nlyearday::
 
132
  Set the yearday or the non-leap year day (jump leap days).
 
133
  These are converted to {{{day}}}/{{{month}}}/{{{leapdays}}}
 
134
  information.
 
135
 
 
136
==== Behavior of operations ====
 
137
If you're curious about exactly how the relative delta will act
 
138
on operations, here is a description of its behavior.
 
139
 
 
140
  1. Calculate the absolute year, using the {{{year}}} argument, or the
 
141
  original datetime year, if the argument is not present.
 
142
  1. Add the relative {{{years}}} argument to the absolute year.
 
143
  1. Do steps 1 and 2 for {{{month}}}/{{{months}}}.
 
144
  1. Calculate the absolute day, using the {{{day}}} argument, or the
 
145
  original datetime day, if the argument is not present. Then, subtract
 
146
  from the day until it fits in the year and month found after their
 
147
  operations.
 
148
  1. Add the relative {{{days}}} argument to the absolute day. Notice
 
149
  that the {{{weeks}}} argument is multiplied by 7 and added to {{{days}}}.
 
150
  1. If {{{leapdays}}} is present, the computed year is a leap year, and
 
151
  the computed month is after february, remove one day from the found date.
 
152
  1. Do steps 1 and 2 for {{{hour}}}/{{{hours}}}, {{{minute}}}/{{{minutes}}},
 
153
  {{{second}}}/{{{seconds}}}, {{{microsecond}}}/{{{microseconds}}}.
 
154
  1. If the {{{weekday}}} argument is present, calculate the {{{n}}}th
 
155
  occurrence of the given weekday.
 
156
 
 
157
==== Examples ====
 
158
 
 
159
Let's begin our trip.
 
160
{{{
 
161
>>> from datetime import *; from dateutil.relativedelta import *
 
162
>>> import calendar
 
163
}}}
 
164
 
 
165
Store some values.
 
166
{{{
 
167
>>> NOW = datetime.now()
 
168
>>> TODAY = date.today()
 
169
>>> NOW
 
170
datetime.datetime(2003, 9, 17, 20, 54, 47, 282310)
 
171
>>> TODAY
 
172
datetime.date(2003, 9, 17)
 
173
}}}
 
174
 
 
175
Next month.
 
176
{{{
 
177
>>> NOW+relativedelta(months=+1)
 
178
datetime.datetime(2003, 10, 17, 20, 54, 47, 282310)
 
179
}}}
 
180
 
 
181
Next month, plus one week.
 
182
{{{
 
183
>>> NOW+relativedelta(months=+1, weeks=+1)
 
184
datetime.datetime(2003, 10, 24, 20, 54, 47, 282310)
 
185
}}}
 
186
 
 
187
Next month, plus one week, at 10am.
 
188
{{{
 
189
>>> TODAY+relativedelta(months=+1, weeks=+1, hour=10)
 
190
datetime.datetime(2003, 10, 24, 10, 0)
 
191
}}}
 
192
 
 
193
Let's try the other way around. Notice that the
 
194
hour setting we get in the relativedelta is relative,
 
195
since it's a difference, and the weeks parameter
 
196
has gone.
 
197
{{{
 
198
>>> relativedelta(datetime(2003, 10, 24, 10, 0), TODAY)
 
199
relativedelta(months=+1, days=+7, hours=+10)
 
200
}}}
 
201
 
 
202
One month before one year.
 
203
{{{
 
204
>>> NOW+relativedelta(years=+1, months=-1)
 
205
datetime.datetime(2004, 8, 17, 20, 54, 47, 282310)
 
206
}}}
 
207
 
 
208
How does it handle months with different numbers of days?
 
209
Notice that adding one month will never cross the month
 
210
boundary.
 
211
{{{
 
212
>>> date(2003,1,27)+relativedelta(months=+1)
 
213
datetime.date(2003, 2, 27)
 
214
>>> date(2003,1,31)+relativedelta(months=+1)
 
215
datetime.date(2003, 2, 28)
 
216
>>> date(2003,1,31)+relativedelta(months=+2)
 
217
datetime.date(2003, 3, 31)
 
218
}}}
 
219
 
 
220
The logic for years is the same, even on leap years.
 
221
{{{
 
222
>>> date(2000,2,28)+relativedelta(years=+1)
 
223
datetime.date(2001, 2, 28)
 
224
>>> date(2000,2,29)+relativedelta(years=+1)
 
225
datetime.date(2001, 2, 28)
 
226
 
 
227
>>> date(1999,2,28)+relativedelta(years=+1)
 
228
datetime.date(2000, 2, 28)
 
229
>>> date(1999,3,1)+relativedelta(years=+1)
 
230
datetime.date(2000, 3, 1)
 
231
 
 
232
>>> date(2001,2,28)+relativedelta(years=-1)
 
233
datetime.date(2000, 2, 28)
 
234
>>> date(2001,3,1)+relativedelta(years=-1)
 
235
datetime.date(2000, 3, 1)
 
236
}}}
 
237
 
 
238
Next friday.
 
239
{{{
 
240
>>> TODAY+relativedelta(weekday=FR)
 
241
datetime.date(2003, 9, 19)
 
242
 
 
243
>>> TODAY+relativedelta(weekday=calendar.FRIDAY)
 
244
datetime.date(2003, 9, 19)
 
245
}}}
 
246
 
 
247
Last friday in this month.
 
248
{{{
 
249
>>> TODAY+relativedelta(day=31, weekday=FR(-1))
 
250
datetime.date(2003, 9, 26)
 
251
}}}
 
252
 
 
253
Next wednesday (it's today!).
 
254
{{{
 
255
>>> TODAY+relativedelta(weekday=WE(+1))
 
256
datetime.date(2003, 9, 17)
 
257
}}}
 
258
 
 
259
Next wednesday, but not today.
 
260
{{{
 
261
>>> TODAY+relativedelta(days=+1, weekday=WE(+1))
 
262
datetime.date(2003, 9, 24)
 
263
}}}
 
264
 
 
265
Following
 
266
[http://www.cl.cam.ac.uk/~mgk25/iso-time.html ISO year week number notation]
 
267
find the first day of the 15th week of 1997.
 
268
{{{
 
269
>>> datetime(1997,1,1)+relativedelta(day=4, weekday=MO(-1), weeks=+14)
 
270
datetime.datetime(1997, 4, 7, 0, 0)
 
271
}}}
 
272
 
 
273
How long ago has the millennium changed?
 
274
{{{
 
275
>>> relativedelta(NOW, date(2001,1,1))
 
276
relativedelta(years=+2, months=+8, days=+16, hours=+20, minutes=+54, seconds=+47, microseconds=+282310)
 
277
}}}
 
278
 
 
279
How old is John?
 
280
{{{
 
281
>>> johnbirthday = datetime(1978, 4, 5, 12, 0)
 
282
>>> relativedelta(NOW, johnbirthday)
 
283
relativedelta(years=+25, months=+5, days=+12, hours=+8, minutes=+54, seconds=+47, microseconds=+282310)
 
284
}}}
 
285
 
 
286
It works with dates too.
 
287
{{{
 
288
>>> relativedelta(TODAY, johnbirthday)
 
289
relativedelta(years=+25, months=+5, days=+11, hours=+12)
 
290
}}}
 
291
 
 
292
Obtain today's date using the yearday:
 
293
{{{
 
294
>>> date(2003, 1, 1)+relativedelta(yearday=260)
 
295
datetime.date(2003, 9, 17)
 
296
}}}
 
297
 
 
298
We can use today's date, since yearday should be absolute
 
299
in the given year:
 
300
{{{
 
301
>>> TODAY+relativedelta(yearday=260)
 
302
datetime.date(2003, 9, 17)
 
303
}}}
 
304
 
 
305
Last year it should be in the same day:
 
306
{{{
 
307
>>> date(2002, 1, 1)+relativedelta(yearday=260)
 
308
datetime.date(2002, 9, 17)
 
309
}}}
 
310
 
 
311
But not in a leap year:
 
312
{{{
 
313
>>> date(2000, 1, 1)+relativedelta(yearday=260)
 
314
datetime.date(2000, 9, 16)
 
315
}}}
 
316
 
 
317
We can use the non-leap year day to ignore this:
 
318
{{{
 
319
>>> date(2000, 1, 1)+relativedelta(nlyearday=260)
 
320
datetime.date(2000, 9, 17)
 
321
}}}
 
322
 
 
323
=== rrule ===
 
324
The rrule module offers a small, complete, and very fast, implementation
 
325
of the recurrence rules documented in the 
 
326
[ftp://ftp.rfc-editor.org/in-notes/rfc2445.txt iCalendar RFC], including
 
327
support for caching of results.
 
328
 
 
329
==== rrule type ====
 
330
That's the base of the rrule operation. It accepts all the keywords
 
331
defined in the RFC as its constructor parameters (except {{{byday}}},
 
332
which was renamed to {{{byweekday}}}) and more. The constructor
 
333
prototype is:
 
334
{{{
 
335
rrule(freq)
 
336
}}}
 
337
 
 
338
Where {{{freq}}} must be one of {{{FREQ_YEARLY}}}, {{{FREQ_MONTHLY}}},
 
339
{{{FREQ_WEEKLY}}}, {{{FREQ_DAILY}}}, {{{FREQ_HOURLY}}}, {{{FREQ_MINUTELY}}},
 
340
or {{{FREQ_SECONDLY}}}.
 
341
 
 
342
Additionally, it supports the following keyword arguments:
 
343
 
 
344
    cache::
 
345
    If given, it must be a boolean value specifying to enable
 
346
    or disable caching of results. If you will use the same
 
347
    {{{rrule}}} instance multiple times, enabling caching will
 
348
    improve the performance considerably.
 
349
 
 
350
    dtstart::
 
351
    The recurrence start. Besides being the base for the
 
352
    recurrence, missing parameters in the final recurrence
 
353
    instances will also be extracted from this date. If not
 
354
    given, {{{datetime.now()}}} will be used instead.
 
355
 
 
356
    interval::
 
357
    The interval between each {{{freq}}} iteration. For example,
 
358
    when using {{{FREQ_YEARLY}}}, an interval of {{{2}}} means
 
359
    once every two years, but with {{{FREQ_HOURLY}}}, it means
 
360
    once every two hours. The default interval is {{{1}}}.
 
361
 
 
362
    wkst::
 
363
    The week start day. Must be one of the {{{MO}}}, {{{TU}}},
 
364
    {{{WE}}} constants, or an integer, specifying the first day
 
365
    of the week. This will affect recurrences based on weekly
 
366
    periods. The default week start is got from
 
367
    {{{calendar.firstweekday()}}}, and may be modified by
 
368
    {{{calendar.setfirstweekday()}}}.
 
369
 
 
370
    count::
 
371
    How many occurrences will be generated.
 
372
 
 
373
    until::
 
374
    If given, this must be a {{{datetime}}} instance, that will
 
375
    specify the limit of the recurrence. If a recurrence instance
 
376
    happens to be the same as the {{{datetime}}} instance given
 
377
    in the {{{until}}} keyword, this will be the last occurrence.
 
378
 
 
379
    bysetpos::
 
380
    If given, it must be either an integer, or a sequence of
 
381
    integers, positive or negative. Each given integer will
 
382
    specify an occurrence number, corresponding to the nth
 
383
    occurrence of the rule inside the frequency period. For
 
384
    example, a {{{bysetpos}}} of {{{-1}}} if combined with a
 
385
    {{{FREQ_MONTHLY}}} frequency, and a {{{byweekday}}} of
 
386
    {{{(MO, TU, WE, TH, FR)}}}, will result in the last work
 
387
    day of every month.
 
388
 
 
389
    bymonth::
 
390
    If given, it must be either an integer, or a sequence of
 
391
    integers, meaning the months to apply the recurrence to.
 
392
 
 
393
    bymonthday::
 
394
    If given, it must be either an integer, or a sequence of
 
395
    integers, meaning the month days to apply the recurrence to.
 
396
 
 
397
    byyearday::
 
398
    If given, it must be either an integer, or a sequence of
 
399
    integers, meaning the year days to apply the recurrence to.
 
400
 
 
401
    byweekno::
 
402
    If given, it must be either an integer, or a sequence of
 
403
    integers, meaning the week numbers to apply the recurrence
 
404
    to. Week numbers have the meaning described in ISO8601,
 
405
    that is, the first week of the year is that containing at
 
406
    least four days of the new year.
 
407
    
 
408
    byweekday::
 
409
    If given, it must be either an integer ({{{0 == MO}}}), a
 
410
    sequence of integers, one of the weekday constants
 
411
    ({{{MO}}}, {{{TU}}}, etc), or a sequence of these constants.
 
412
    When given, these variables will define the weekdays where
 
413
    the recurrence will be applied. It's also possible to use
 
414
    an argument {{{n}}} for the weekday instances, which will
 
415
    mean the {{{n}}}''th'' occurrence of this weekday in the
 
416
    period. For example, with {{{FREQ_MONTHLY}}}, or with
 
417
    {{{FREQ_YEARLY}}} and {{{BYMONTH}}}, using {{{FR(+1)}}}
 
418
    in {{{byweekday}}} will specify the first friday of the
 
419
    month where the recurrence happens. Notice that in the RFC
 
420
    documentation, this is specified as {{{BYDAY}}}, but was
 
421
    renamed to avoid the ambiguity of that keyword.
 
422
 
 
423
    byhour::
 
424
    If given, it must be either an integer, or a sequence of
 
425
    integers, meaning the hours to apply the recurrence to.
 
426
 
 
427
    byminute::
 
428
    If given, it must be either an integer, or a sequence of
 
429
    integers, meaning the minutes to apply the recurrence to.
 
430
 
 
431
    bysecond::
 
432
    If given, it must be either an integer, or a sequence of
 
433
    integers, meaning the seconds to apply the recurrence to.
 
434
 
 
435
    byeaster::
 
436
    If given, it must be either an integer, or a sequence of
 
437
    integers, positive or negative. Each integer will define
 
438
    an offset from the Easter Sunday. Passing the offset
 
439
    {{{0}}} to {{{byeaster}}} will yield the Easter Sunday
 
440
    itself. This is an extension to the RFC specification.
 
441
 
 
442
==== rrule methods ====
 
443
The following methods are available in {{{rrule}}} instances:
 
444
 
 
445
    rrule.before(dt, inc=False)::
 
446
    Returns the last recurrence before the given {{{datetime}}}
 
447
    instance. The {{{inc}}} keyword defines what happens if
 
448
    {{{dt}}} '''is''' an occurrence. With {{{inc == True}}},
 
449
    if {{{dt}}} itself is an occurrence, it will be returned.
 
450
 
 
451
    rrule.after(dt, inc=False)::
 
452
    Returns the first recurrence after the given {{{datetime}}}
 
453
    instance. The {{{inc}}} keyword defines what happens if
 
454
    {{{dt}}} '''is''' an occurrence. With {{{inc == True}}},
 
455
    if {{{dt}}} itself is an occurrence, it will be returned.
 
456
 
 
457
    rrule.between(after, before, inc=False)::
 
458
    Returns all the occurrences of the rrule between {{{after}}}
 
459
    and {{{before}}}. The {{{inc}}} keyword defines what happens
 
460
    if {{{after}}} and/or {{{before}}} are themselves occurrences.
 
461
    With {{{inc == True}}}, they will be included in the list,
 
462
    if they are found in the recurrence set.
 
463
 
 
464
    rrule.count()::
 
465
    Returns the number of recurrences in this set. It will have
 
466
    go trough the whole recurrence, if this hasn't been done
 
467
    before.
 
468
 
 
469
Besides these methods, {{{rrule}}} instances also support
 
470
the {{{__getitem__()}}} and {{{__contains__()}}} special methods,
 
471
meaning that these are valid expressions:
 
472
{{{
 
473
rr = rrule(...)
 
474
if datetime(...) in rr:
 
475
    ...
 
476
print rr[0]
 
477
print rr[-1]
 
478
print rr[1:2]
 
479
print rr[::-2]
 
480
}}}
 
481
 
 
482
The getitem/slicing mechanism is smart enough to avoid getting the whole
 
483
recurrence set, if possible.
 
484
 
 
485
==== Notes ====
 
486
 
 
487
  * The rrule type has no {{{byday}}} keyword. The equivalent keyword
 
488
  has been replaced by the {{{byweekday}}} keyword, to remove the
 
489
  ambiguity present in the original keyword.
 
490
 
 
491
  * Unlike documented in the RFC, the starting datetime ({{{dtstart}}})
 
492
  is not the first recurrence instance, unless it does fit in the
 
493
  specified rules. In a python module context, this behavior makes more
 
494
  sense than otherwise. Notice that you can easily get the original
 
495
  behavior by using a rruleset and adding the {{{dtstart}}} as an
 
496
  {{{rdate}}} recurrence.
 
497
 
 
498
  * Unlike documented in the RFC, every keyword is valid on every
 
499
  frequency (the RFC documents that {{{byweekno}}} is only valid
 
500
  on yearly frequencies, for example).
 
501
 
 
502
  * In addition to the documented keywords, a {{{byeaster}}} keyword
 
503
  was introduced, making it easy to compute recurrent events relative
 
504
  to the Easter Sunday.
 
505
 
 
506
==== rrule examples ====
 
507
These examples were converted from the RFC.
 
508
 
 
509
Prepare the environment.
 
510
{{{
 
511
>>> from dateutil.rrule import *
 
512
>>> from dateutil.parser import *
 
513
>>> from datetime import *
 
514
 
 
515
>>> import pprint
 
516
>>> import sys
 
517
>>> sys.displayhook = pprint.pprint
 
518
}}}
 
519
 
 
520
Daily, for 10 occurrences.
 
521
{{{
 
522
>>> list(rrule(FREQ_DAILY, count=10, dtstart=parse("19970902T090000")))
 
523
[datetime.datetime(1997, 9, 2, 9, 0),
 
524
 datetime.datetime(1997, 9, 3, 9, 0),
 
525
 datetime.datetime(1997, 9, 4, 9, 0),
 
526
 datetime.datetime(1997, 9, 5, 9, 0),
 
527
 datetime.datetime(1997, 9, 6, 9, 0),
 
528
 datetime.datetime(1997, 9, 7, 9, 0),
 
529
 datetime.datetime(1997, 9, 8, 9, 0),
 
530
 datetime.datetime(1997, 9, 9, 9, 0),
 
531
 datetime.datetime(1997, 9, 10, 9, 0),
 
532
 datetime.datetime(1997, 9, 11, 9, 0)]
 
533
}}}
 
534
 
 
535
Daily until December 24, 1997
 
536
{{{
 
537
>>> list(rrule(FREQ_DAILY, dtstart=parse("19970902T090000"), until=parse("19971224T000000")))
 
538
[datetime.datetime(1997, 9, 2, 9, 0),
 
539
 datetime.datetime(1997, 9, 3, 9, 0),
 
540
 datetime.datetime(1997, 9, 4, 9, 0),
 
541
 (...)
 
542
 datetime.datetime(1997, 12, 21, 9, 0),
 
543
 datetime.datetime(1997, 12, 22, 9, 0),
 
544
 datetime.datetime(1997, 12, 23, 9, 0)]
 
545
}}}
 
546
 
 
547
Every other day, 5 occurrences.
 
548
{{{
 
549
>>> list(rrule(FREQ_DAILY, interval=2, count=5, dtstart=parse("19970902T090000")))
 
550
[datetime.datetime(1997, 9, 2, 9, 0),
 
551
 datetime.datetime(1997, 9, 4, 9, 0),
 
552
 datetime.datetime(1997, 9, 6, 9, 0),
 
553
 datetime.datetime(1997, 9, 8, 9, 0),
 
554
 datetime.datetime(1997, 9, 10, 9, 0)]
 
555
}}}
 
556
 
 
557
Every 10 days, 5 occurrences.
 
558
{{{
 
559
>>> list(rrule(FREQ_DAILY, interval=10, count=5, dtstart=parse("19970902T090000")))
 
560
[datetime.datetime(1997, 9, 2, 9, 0),
 
561
 datetime.datetime(1997, 9, 12, 9, 0),
 
562
 datetime.datetime(1997, 9, 22, 9, 0),
 
563
 datetime.datetime(1997, 10, 2, 9, 0),
 
564
 datetime.datetime(1997, 10, 12, 9, 0)]
 
565
}}}
 
566
 
 
567
Everyday in January, for 3 years.
 
568
{{{
 
569
>>> list(rrule(FREQ_YEARLY, bymonth=1, byweekday=range(7), dtstart=parse("19980101T090000"), until=parse("20000131T090000")))
 
570
[datetime.datetime(1998, 1, 1, 9, 0),
 
571
 datetime.datetime(1998, 1, 2, 9, 0),
 
572
 (...)
 
573
 datetime.datetime(1998, 1, 30, 9, 0),
 
574
 datetime.datetime(1998, 1, 31, 9, 0),
 
575
 datetime.datetime(1999, 1, 1, 9, 0),
 
576
 datetime.datetime(1999, 1, 2, 9, 0),
 
577
 (...)
 
578
 datetime.datetime(1999, 1, 30, 9, 0),
 
579
 datetime.datetime(1999, 1, 31, 9, 0),
 
580
 datetime.datetime(2000, 1, 1, 9, 0),
 
581
 datetime.datetime(2000, 1, 2, 9, 0),
 
582
 (...)
 
583
 datetime.datetime(2000, 1, 29, 9, 0),
 
584
 datetime.datetime(2000, 1, 31, 9, 0)]
 
585
}}} 
 
586
 
 
587
Same thing, in another way.
 
588
{{{
 
589
>>> list(rrule(FREQ_DAILY, bymonth=1, dtstart=parse("19980101T090000"), until=parse("20000131T090000")))
 
590
(...)
 
591
}}}
 
592
 
 
593
Weekly for 10 occurrences.
 
594
{{{
 
595
>>> list(rrule(FREQ_WEEKLY, count=10, dtstart=parse("19970902T090000")))
 
596
[datetime.datetime(1997, 9, 2, 9, 0),
 
597
 datetime.datetime(1997, 9, 9, 9, 0),
 
598
 datetime.datetime(1997, 9, 16, 9, 0),
 
599
 datetime.datetime(1997, 9, 23, 9, 0),
 
600
 datetime.datetime(1997, 9, 30, 9, 0),
 
601
 datetime.datetime(1997, 10, 7, 9, 0),
 
602
 datetime.datetime(1997, 10, 14, 9, 0),
 
603
 datetime.datetime(1997, 10, 21, 9, 0),
 
604
 datetime.datetime(1997, 10, 28, 9, 0),
 
605
 datetime.datetime(1997, 11, 4, 9, 0)]
 
606
}}}
 
607
 
 
608
Every other week, 6 occurrences.
 
609
{{{
 
610
>>> list(rrule(FREQ_WEEKLY, interval=2, count=6, dtstart=parse("19970902T090000")))
 
611
[datetime.datetime(1997, 9, 2, 9, 0),
 
612
 datetime.datetime(1997, 9, 16, 9, 0),
 
613
 datetime.datetime(1997, 9, 30, 9, 0),
 
614
 datetime.datetime(1997, 10, 14, 9, 0),
 
615
 datetime.datetime(1997, 10, 28, 9, 0),
 
616
 datetime.datetime(1997, 11, 11, 9, 0)]
 
617
}}}
 
618
 
 
619
Weekly on Tuesday and Thursday for 5 weeks.
 
620
{{{
 
621
>>> list(rrule(FREQ_WEEKLY, count=10, wkst=SU, byweekday=(TU,TH), dtstart=parse(
 
622
"19970902T090000")))
 
623
[datetime.datetime(1997, 9, 2, 9, 0),
 
624
 datetime.datetime(1997, 9, 4, 9, 0),
 
625
 datetime.datetime(1997, 9, 9, 9, 0),
 
626
 datetime.datetime(1997, 9, 11, 9, 0),
 
627
 datetime.datetime(1997, 9, 16, 9, 0),
 
628
 datetime.datetime(1997, 9, 18, 9, 0),
 
629
 datetime.datetime(1997, 9, 23, 9, 0),
 
630
 datetime.datetime(1997, 9, 25, 9, 0),
 
631
 datetime.datetime(1997, 9, 30, 9, 0),
 
632
 datetime.datetime(1997, 10, 2, 9, 0)]
 
633
}}}
 
634
 
 
635
Every other week on Tuesday and Thursday, for 8 occurrences.
 
636
{{{
 
637
>>> list(rrule(FREQ_WEEKLY, interval=2, count=8, wkst=SU, byweekday=(TU,TH), dts
 
638
tart=parse("19970902T090000")))
 
639
[datetime.datetime(1997, 9, 2, 9, 0),
 
640
 datetime.datetime(1997, 9, 4, 9, 0),
 
641
 datetime.datetime(1997, 9, 16, 9, 0),
 
642
 datetime.datetime(1997, 9, 18, 9, 0),
 
643
 datetime.datetime(1997, 9, 30, 9, 0),
 
644
 datetime.datetime(1997, 10, 2, 9, 0),
 
645
 datetime.datetime(1997, 10, 14, 9, 0),
 
646
 datetime.datetime(1997, 10, 16, 9, 0)]
 
647
}}}
 
648
 
 
649
Monthly on the 1st Friday for ten occurrences.
 
650
{{{
 
651
>>> list(rrule(FREQ_MONTHLY, count=10, byweekday=FR(1), dtstart=parse("19970905T090000")))
 
652
[datetime.datetime(1997, 9, 5, 9, 0),
 
653
 datetime.datetime(1997, 10, 3, 9, 0),
 
654
 datetime.datetime(1997, 11, 7, 9, 0),
 
655
 datetime.datetime(1997, 12, 5, 9, 0),
 
656
 datetime.datetime(1998, 1, 2, 9, 0),
 
657
 datetime.datetime(1998, 2, 6, 9, 0),
 
658
 datetime.datetime(1998, 3, 6, 9, 0),
 
659
 datetime.datetime(1998, 4, 3, 9, 0),
 
660
 datetime.datetime(1998, 5, 1, 9, 0),
 
661
 datetime.datetime(1998, 6, 5, 9, 0)]
 
662
}}}
 
663
 
 
664
Every other month on the 1st and last Sunday of the month for 10 occurrences.
 
665
{{{
 
666
>>> list(rrule(FREQ_MONTHLY, interval=2, count=10, byweekday=(SU(1), SU(-1)), dtstart=parse("19970907T090000")))
 
667
[datetime.datetime(1997, 9, 7, 9, 0),
 
668
 datetime.datetime(1997, 9, 28, 9, 0),
 
669
 datetime.datetime(1997, 11, 2, 9, 0),
 
670
 datetime.datetime(1997, 11, 30, 9, 0),
 
671
 datetime.datetime(1998, 1, 4, 9, 0),
 
672
 datetime.datetime(1998, 1, 25, 9, 0),
 
673
 datetime.datetime(1998, 3, 1, 9, 0),
 
674
 datetime.datetime(1998, 3, 29, 9, 0),
 
675
 datetime.datetime(1998, 5, 3, 9, 0),
 
676
 datetime.datetime(1998, 5, 31, 9, 0)]
 
677
}}}
 
678
 
 
679
Monthly on the second to last Monday of the month for 6 months.
 
680
{{{
 
681
>>> list(rrule(FREQ_MONTHLY, count=6, byweekday=MO(-2), dtstart=parse("19970922T090000")))
 
682
[datetime.datetime(1997, 9, 22, 9, 0),
 
683
 datetime.datetime(1997, 10, 20, 9, 0),
 
684
 datetime.datetime(1997, 11, 17, 9, 0),
 
685
 datetime.datetime(1997, 12, 22, 9, 0),
 
686
 datetime.datetime(1998, 1, 19, 9, 0),
 
687
 datetime.datetime(1998, 2, 16, 9, 0)]
 
688
}}}
 
689
 
 
690
Monthly on the third to the last day of the month, for 6 months.
 
691
{{{
 
692
>>> list(rrule(FREQ_MONTHLY, count=6, bymonthday=-3, dtstart=parse("19970928T090000")))
 
693
[datetime.datetime(1997, 9, 28, 9, 0),
 
694
 datetime.datetime(1997, 10, 29, 9, 0),
 
695
 datetime.datetime(1997, 11, 28, 9, 0),
 
696
 datetime.datetime(1997, 12, 29, 9, 0),
 
697
 datetime.datetime(1998, 1, 29, 9, 0),
 
698
 datetime.datetime(1998, 2, 26, 9, 0)]
 
699
}}}
 
700
 
 
701
Monthly on the 2nd and 15th of the month for 5 occurrences.
 
702
{{{
 
703
>>> list(rrule(FREQ_MONTHLY, count=5, bymonthday=(2,15), dtstart=parse("19970902T090000")))
 
704
[datetime.datetime(1997, 9, 2, 9, 0),
 
705
 datetime.datetime(1997, 9, 15, 9, 0),
 
706
 datetime.datetime(1997, 10, 2, 9, 0),
 
707
 datetime.datetime(1997, 10, 15, 9, 0),
 
708
 datetime.datetime(1997, 11, 2, 9, 0)]
 
709
}}}
 
710
 
 
711
Monthly on the first and last day of the month for 3 occurrences.
 
712
{{{
 
713
>>> list(rrule(FREQ_MONTHLY, count=5, bymonthday=(-1,1,), dtstart=parse("1997090
 
714
2T090000")))
 
715
[datetime.datetime(1997, 9, 30, 9, 0),
 
716
 datetime.datetime(1997, 10, 1, 9, 0),
 
717
 datetime.datetime(1997, 10, 31, 9, 0),
 
718
 datetime.datetime(1997, 11, 1, 9, 0),
 
719
 datetime.datetime(1997, 11, 30, 9, 0)]
 
720
}}}
 
721
 
 
722
Every 18 months on the 10th thru 15th of the month for 10 occurrences.
 
723
{{{
 
724
>>> list(rrule(FREQ_MONTHLY, interval=18, count=10, bymonthday=range(10,16), dtstart=parse("19970910T090000")))
 
725
[datetime.datetime(1997, 9, 10, 9, 0),
 
726
 datetime.datetime(1997, 9, 11, 9, 0),
 
727
 datetime.datetime(1997, 9, 12, 9, 0),
 
728
 datetime.datetime(1997, 9, 13, 9, 0),
 
729
 datetime.datetime(1997, 9, 14, 9, 0),
 
730
 datetime.datetime(1997, 9, 15, 9, 0),
 
731
 datetime.datetime(1999, 3, 10, 9, 0),
 
732
 datetime.datetime(1999, 3, 11, 9, 0),
 
733
 datetime.datetime(1999, 3, 12, 9, 0),
 
734
 datetime.datetime(1999, 3, 13, 9, 0)]
 
735
}}}
 
736
 
 
737
Every Tuesday, every other month, 6 occurences.
 
738
{{{
 
739
>>> list(rrule(FREQ_MONTHLY, interval=2, count=6, byweekday=TU, dtstart=parse("1
 
740
9970902T090000")))
 
741
[datetime.datetime(1997, 9, 2, 9, 0),
 
742
 datetime.datetime(1997, 9, 9, 9, 0),
 
743
 datetime.datetime(1997, 9, 16, 9, 0),
 
744
 datetime.datetime(1997, 9, 23, 9, 0),
 
745
 datetime.datetime(1997, 9, 30, 9, 0),
 
746
 datetime.datetime(1997, 11, 4, 9, 0)]
 
747
}}}
 
748
 
 
749
Yearly in June and July for 10 occurrences.
 
750
{{{
 
751
>>> list(rrule(FREQ_YEARLY, count=4, bymonth=(6,7), dtstart=parse("19970610T0900
 
752
00")))
 
753
[datetime.datetime(1997, 6, 10, 9, 0),
 
754
 datetime.datetime(1997, 7, 10, 9, 0),
 
755
 datetime.datetime(1998, 6, 10, 9, 0),
 
756
 datetime.datetime(1998, 7, 10, 9, 0)]
 
757
}}}
 
758
 
 
759
Every 3rd year on the 1st, 100th and 200th day for 4 occurrences.
 
760
{{{
 
761
>>> list(rrule(FREQ_YEARLY, count=4, interval=3, byyearday=(1,100,200), dtstart=parse("19970101T090000")))
 
762
[datetime.datetime(1997, 1, 1, 9, 0),
 
763
 datetime.datetime(1997, 4, 10, 9, 0),
 
764
 datetime.datetime(1997, 7, 19, 9, 0),
 
765
 datetime.datetime(2000, 1, 1, 9, 0)]
 
766
}}}
 
767
 
 
768
Every 20th Monday of the year, 3 occurrences.
 
769
{{{
 
770
>>> list(rrule(FREQ_YEARLY, count=3, byweekday=MO(20), dtstart=parse("19970519T090000")))
 
771
[datetime.datetime(1997, 5, 19, 9, 0),
 
772
 datetime.datetime(1998, 5, 18, 9, 0),
 
773
 datetime.datetime(1999, 5, 17, 9, 0)]
 
774
}}}
 
775
 
 
776
Monday of week number 20 (where the default start of the week is Monday),
 
777
3 occurrences.
 
778
{{{
 
779
>>> list(rrule(FREQ_YEARLY, count=3, byweekno=20, byweekday=MO, dtstart=parse("19970512T090000")))
 
780
[datetime.datetime(1997, 5, 12, 9, 0),
 
781
 datetime.datetime(1998, 5, 11, 9, 0),
 
782
 datetime.datetime(1999, 5, 17, 9, 0)]
 
783
}}}
 
784
 
 
785
The week number 1 may be in the last year.
 
786
{{{
 
787
>>> list(rrule(FREQ_WEEKLY, count=3, byweekno=1, byweekday=MO, dtstart=parse("19970902T090000")))
 
788
[datetime.datetime(1997, 12, 29, 9, 0),
 
789
 datetime.datetime(1999, 1, 4, 9, 0),
 
790
 datetime.datetime(2000, 1, 3, 9, 0)]
 
791
}}}
 
792
 
 
793
And the week numbers greater than 51 may be in the next year.
 
794
{{{
 
795
>>> list(rrule(FREQ_WEEKLY, count=3, byweekno=52, byweekday=SU, dtstart=parse("19970902T090000")))
 
796
[datetime.datetime(1997, 12, 28, 9, 0),
 
797
 datetime.datetime(1998, 12, 27, 9, 0),
 
798
 datetime.datetime(2000, 1, 2, 9, 0)]
 
799
}}}
 
800
 
 
801
Only some years have week number 53:
 
802
{{{
 
803
>>> list(rrule(FREQ_WEEKLY, count=3, byweekno=53, byweekday=MO, dtstart=parse("19970902T090000")))
 
804
[datetime.datetime(1998, 12, 28, 9, 0),
 
805
 datetime.datetime(2004, 12, 27, 9, 0),
 
806
 datetime.datetime(2009, 12, 28, 9, 0)]
 
807
}}}
 
808
 
 
809
Every Friday the 13th, 4 occurrences.
 
810
{{{
 
811
>>> list(rrule(FREQ_YEARLY, count=4, byweekday=FR, bymonthday=13, dtstart=parse(
 
812
"19970902T090000")))
 
813
[datetime.datetime(1998, 2, 13, 9, 0),
 
814
 datetime.datetime(1998, 3, 13, 9, 0),
 
815
 datetime.datetime(1998, 11, 13, 9, 0),
 
816
 datetime.datetime(1999, 8, 13, 9, 0)]
 
817
}}}
 
818
 
 
819
Every four years, the first Tuesday after a Monday in November,
 
820
3 occurrences (U.S. Presidential Election day):
 
821
{{{
 
822
>>> list(rrule(FREQ_YEARLY, interval=4, count=3, bymonth=11, byweekday=TU, bymonthday=(2,3,4,5,6,7,8), dtstart=parse("19961105T090000")))
 
823
[datetime.datetime(1996, 11, 5, 9, 0),
 
824
 datetime.datetime(2000, 11, 7, 9, 0),
 
825
 datetime.datetime(2004, 11, 2, 9, 0)]
 
826
}}}
 
827
 
 
828
The 3rd instance into the month of one of Tuesday, Wednesday or
 
829
Thursday, for the next 3 months:
 
830
{{{
 
831
>>> list(rrule(FREQ_MONTHLY, count=3, byweekday=(TU,WE,TH), bysetpos=3, dtstart=parse("19970904T090000")))
 
832
[datetime.datetime(1997, 9, 4, 9, 0),
 
833
 datetime.datetime(1997, 10, 7, 9, 0),
 
834
 datetime.datetime(1997, 11, 6, 9, 0)]
 
835
}}}
 
836
 
 
837
The 2nd to last weekday of the month, 3 occurrences.
 
838
{{{
 
839
>>> list(rrule(FREQ_MONTHLY, count=3, byweekday=(MO,TU,WE,TH,FR), bysetpos=-2, d
 
840
tstart=parse("19970929T090000")))
 
841
[datetime.datetime(1997, 9, 29, 9, 0),
 
842
 datetime.datetime(1997, 10, 30, 9, 0),
 
843
 datetime.datetime(1997, 11, 27, 9, 0)]
 
844
}}}
 
845
 
 
846
Every 3 hours from 9:00 AM to 5:00 PM on a specific day.
 
847
{{{
 
848
>>> list(rrule(FREQ_HOURLY, interval=3, dtstart=parse("19970902T090000"), until=parse("19970902T170000")))
 
849
[datetime.datetime(1997, 9, 2, 9, 0),
 
850
 datetime.datetime(1997, 9, 2, 12, 0),
 
851
 datetime.datetime(1997, 9, 2, 15, 0)]
 
852
}}}
 
853
 
 
854
Every 15 minutes for 6 occurrences.
 
855
{{{
 
856
>>> list(rrule(FREQ_MINUTELY, interval=15, count=6, dtstart=parse("19970902T0900
 
857
00")))
 
858
[datetime.datetime(1997, 9, 2, 9, 0),
 
859
 datetime.datetime(1997, 9, 2, 9, 15),
 
860
 datetime.datetime(1997, 9, 2, 9, 30),
 
861
 datetime.datetime(1997, 9, 2, 9, 45),
 
862
 datetime.datetime(1997, 9, 2, 10, 0),
 
863
 datetime.datetime(1997, 9, 2, 10, 15)]
 
864
}}}
 
865
 
 
866
Every hour and a half for 4 occurrences.
 
867
{{{
 
868
>>> list(rrule(FREQ_MINUTELY, interval=90, count=4, dtstart=parse("19970902T0900
 
869
00")))
 
870
[datetime.datetime(1997, 9, 2, 9, 0),
 
871
 datetime.datetime(1997, 9, 2, 10, 30),
 
872
 datetime.datetime(1997, 9, 2, 12, 0),
 
873
 datetime.datetime(1997, 9, 2, 13, 30)]
 
874
}}}
 
875
 
 
876
Every 20 minutes from 9:00 AM to 4:40 PM for two days.
 
877
{{{
 
878
>>> list(rrule(FREQ_MINUTELY, interval=20, count=48, byhour=range(9,17), byminut
 
879
e=(0,20,40), dtstart=parse("19970902T090000")))
 
880
[datetime.datetime(1997, 9, 2, 9, 0),
 
881
 datetime.datetime(1997, 9, 2, 9, 20),
 
882
 (...)
 
883
 datetime.datetime(1997, 9, 2, 16, 20),
 
884
 datetime.datetime(1997, 9, 2, 16, 40),
 
885
 datetime.datetime(1997, 9, 3, 9, 0),
 
886
 datetime.datetime(1997, 9, 3, 9, 20),
 
887
 (...)
 
888
 datetime.datetime(1997, 9, 3, 16, 20),
 
889
 datetime.datetime(1997, 9, 3, 16, 40)]
 
890
}}}
 
891
 
 
892
An example where the days generated makes a difference because of {{{wkst}}}.
 
893
{{{
 
894
>>> list(rrule(FREQ_WEEKLY, interval=2, count=4, byweekday=(TU,SU), wkst=MO, dtstart=parse("19970805T090000")))
 
895
[datetime.datetime(1997, 8, 5, 9, 0),
 
896
 datetime.datetime(1997, 8, 10, 9, 0),
 
897
 datetime.datetime(1997, 8, 19, 9, 0),
 
898
 datetime.datetime(1997, 8, 24, 9, 0)]
 
899
 
 
900
>>> list(rrule(FREQ_WEEKLY, interval=2, count=4, byweekday=(TU,SU), wkst=SU, dts
 
901
tart=parse("19970805T090000")))
 
902
[datetime.datetime(1997, 8, 5, 9, 0),
 
903
 datetime.datetime(1997, 8, 17, 9, 0),
 
904
 datetime.datetime(1997, 8, 19, 9, 0),
 
905
 datetime.datetime(1997, 8, 31, 9, 0)]
 
906
}}}
 
907
 
 
908
==== rruleset type ====
 
909
The {{{rruleset}}} type allows more complex recurrence setups, mixing
 
910
multiple rules, dates, exclusion rules, and exclusion dates.
 
911
The type constructor takes the following keyword arguments:
 
912
 
 
913
    cache::
 
914
    If True, caching of results will be enabled, improving performance
 
915
    of multiple queries considerably.
 
916
 
 
917
==== rruleset methods ====
 
918
The following methods are available:
 
919
 
 
920
    rruleset.rrule(rrule)::
 
921
    Include the given {{{rrule}}} instance in the recurrence set
 
922
    generation.
 
923
 
 
924
    rruleset.rdate(dt)::
 
925
    Include the given {{{datetime}}} instance in the recurrence
 
926
    set generation.
 
927
    
 
928
    rruleset.exrule(rrule)::
 
929
    Include the given {{{rrule}}} instance in the recurrence set
 
930
    exclusion list. Dates which are part of the given recurrence
 
931
    rules will not be generated, even if some inclusive {{{rrule}}}
 
932
    or {{{rdate}}} matches them.
 
933
 
 
934
    rruleset.exdate(dt)::
 
935
    Include the given {{{datetime}}} instance in the recurrence set
 
936
    exclusion list. Dates included that way will not be generated,
 
937
    even if some inclusive {{{rrule}}} or {{{rdate}}} matches them.
 
938
 
 
939
    rruleset.before(dt, inc=False)::
 
940
    Returns the last recurrence before the given {{{datetime}}}
 
941
    instance. The {{{inc}}} keyword defines what happens if
 
942
    {{{dt}}} '''is''' an occurrence. With {{{inc == True}}},
 
943
    if {{{dt}}} itself is an occurrence, it will be returned.
 
944
 
 
945
    rruleset.after(dt, inc=False)::
 
946
    Returns the first recurrence after the given {{{datetime}}}
 
947
    instance. The {{{inc}}} keyword defines what happens if
 
948
    {{{dt}}} '''is''' an occurrence. With {{{inc == True}}},
 
949
    if {{{dt}}} itself is an occurrence, it will be returned.
 
950
 
 
951
    rruleset.between(after, before, inc=False)::
 
952
    Returns all the occurrences of the rrule between {{{after}}}
 
953
    and {{{before}}}. The {{{inc}}} keyword defines what happens
 
954
    if {{{after}}} and/or {{{before}}} are themselves occurrences.
 
955
    With {{{inc == True}}}, they will be included in the list,
 
956
    if they are found in the recurrence set.
 
957
 
 
958
    rruleset.count()::
 
959
    Returns the number of recurrences in this set. It will have
 
960
    go trough the whole recurrence, if this hasn't been done
 
961
    before.
 
962
 
 
963
Besides these methods, {{{rruleset}}} instances also support
 
964
the {{{__getitem__()}}} and {{{__contains__()}}} special methods,
 
965
meaning that these are valid expressions:
 
966
{{{
 
967
set = rruleset(...)
 
968
if datetime(...) in set:
 
969
    ...
 
970
print set[0]
 
971
print set[-1]
 
972
print set[1:2]
 
973
print set[::-2]
 
974
}}}
 
975
 
 
976
The getitem/slicing mechanism is smart enough to avoid getting the whole
 
977
recurrence set, if possible.
 
978
 
 
979
==== rruleset examples ====
 
980
Daily, for 7 days, jumping Saturday and Sunday occurrences.
 
981
{{{
 
982
>>> set = rruleset()
 
983
>>> set.rrule(rrule(FREQ_DAILY, count=7, dtstart=parse("19970902T090000")))
 
984
>>> set.exrule(rrule(FREQ_YEARLY, byweekday=(SA,SU), dtstart=parse("19970902T090000")))
 
985
>>> list(set)
 
986
[datetime.datetime(1997, 9, 2, 9, 0),
 
987
 datetime.datetime(1997, 9, 3, 9, 0),
 
988
 datetime.datetime(1997, 9, 4, 9, 0),
 
989
 datetime.datetime(1997, 9, 5, 9, 0),
 
990
 datetime.datetime(1997, 9, 8, 9, 0)]
 
991
}}}
 
992
 
 
993
Weekly, for 4 weeks, plus one time on day 7, and not on day 16.
 
994
{{{
 
995
>>> set = rruleset()
 
996
>>> set.rrule(rrule(FREQ_WEEKLY, count=4, dtstart=parse("19970902T090000")))
 
997
>>> set.rdate(datetime.datetime(1997, 9, 7, 9, 0))
 
998
>>> set.exdate(datetime.datetime(1997, 9, 16, 9, 0))
 
999
>>> list(set)
 
1000
[datetime.datetime(1997, 9, 2, 9, 0),
 
1001
 datetime.datetime(1997, 9, 7, 9, 0),
 
1002
 datetime.datetime(1997, 9, 9, 9, 0),
 
1003
 datetime.datetime(1997, 9, 23, 9, 0)]
 
1004
}}}
 
1005
 
 
1006
==== rrulestr() function ====
 
1007
The {{{rrulestr()}}} function is a parser for ''RFC-like'' syntaxes.
 
1008
The function prototype is:
 
1009
{{{
 
1010
rrulestr(str)
 
1011
}}}
 
1012
 
 
1013
The string passed as parameter may be a multiple line string, a
 
1014
single line string, or just the {{{RRULE}}} property value.
 
1015
 
 
1016
Additionally, it accepts the following keyword arguments:
 
1017
 
 
1018
    cache::
 
1019
    If {{{True}}}, the {{{rruleset}}} or {{{rrule}}} created instance
 
1020
    will cache its results. Default is not to cache.
 
1021
 
 
1022
    dtstart::
 
1023
    If given, it must be a {{{datetime}}} instance that will be used
 
1024
    when no {{{DTSTART}}} property is found in the parsed string. If
 
1025
    it is not given, and the property is not found, {{{datetime.now()}}}
 
1026
    will be used instead.
 
1027
 
 
1028
    unfold::
 
1029
    If set to {{{True}}}, lines will be unfolded following the RFC
 
1030
    specification. It defaults to {{{False}}}, meaning that spaces
 
1031
    before every line will be stripped.
 
1032
 
 
1033
    forceset::
 
1034
    If set to {{{True}}} a {{{rruleset}}} instance will be returned,
 
1035
    even if only a single rule is found. The default is to return an
 
1036
    {{{rrule}}} if possible, and an {{{rruleset}}} if necessary.
 
1037
 
 
1038
    compatible::
 
1039
    If set to {{{True}}}, the parser will operate in RFC-compatible
 
1040
    mode. Right now it means that {{{unfold}}} will be turned on,
 
1041
    and if a {{{DTSTART}}} is found, it will be considered the first     
 
1042
    recurrence instance, as documented in the RFC.
 
1043
 
 
1044
    ignoretz::
 
1045
    If set to {{{True}}}, the date parser will ignore timezone
 
1046
    information available in the {{{DTSTART}}} property, or the
 
1047
    {{{UNTIL}}} attribute.
 
1048
 
 
1049
    tzinfos::
 
1050
    If set, it will be passed to the datetime string parser to
 
1051
    resolve unknown timezone settings. For more information about
 
1052
    what could be used here, check the parser documentation.
 
1053
 
 
1054
==== rrulestr() examples ====
 
1055
 
 
1056
Every 10 days, 5 occurrences.
 
1057
{{{
 
1058
>>> list(rrulestr("""
 
1059
... DTSTART:19970902T090000
 
1060
... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5
 
1061
... """))
 
1062
[datetime.datetime(1997, 9, 2, 9, 0),
 
1063
 datetime.datetime(1997, 9, 12, 9, 0),
 
1064
 datetime.datetime(1997, 9, 22, 9, 0),
 
1065
 datetime.datetime(1997, 10, 2, 9, 0),
 
1066
 datetime.datetime(1997, 10, 12, 9, 0)]
 
1067
}}}
 
1068
 
 
1069
Same thing, but passing only the {{{RRULE}}} value.
 
1070
{{{
 
1071
>>> list(rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5", dtstart=parse("19970902T090000")))
 
1072
[datetime.datetime(1997, 9, 2, 9, 0),
 
1073
 datetime.datetime(1997, 9, 12, 9, 0),
 
1074
 datetime.datetime(1997, 9, 22, 9, 0),
 
1075
 datetime.datetime(1997, 10, 2, 9, 0),
 
1076
 datetime.datetime(1997, 10, 12, 9, 0)]
 
1077
}}}
 
1078
 
 
1079
Notice that when using a single rule, it returns an
 
1080
{{{rrule}}} instance, unless {{{forceset}}} was used.
 
1081
{{{
 
1082
>>> rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5")
 
1083
<dateutil.rrule.rrule instance at 0x30269f08>
 
1084
 
 
1085
>>> rrulestr("""
 
1086
... DTSTART:19970902T090000
 
1087
... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5
 
1088
... """)
 
1089
<dateutil.rrule.rrule instance at 0x302699e0>
 
1090
 
 
1091
>>> rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5", forceset=True)
 
1092
<dateutil.rrule.rruleset instance at 0x30269f08>
 
1093
}}}
 
1094
 
 
1095
But when an {{{rruleset}}} is needed, it is automatically used.
 
1096
{{{
 
1097
>>> rrulestr("""
 
1098
... DTSTART:19970902T090000
 
1099
... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5
 
1100
... RRULE:FREQ=DAILY;INTERVAL=5;COUNT=3
 
1101
... """)
 
1102
<dateutil.rrule.rruleset instance at 0x302699e0>
 
1103
}}}
 
1104
 
 
1105
=== parser ===
 
1106
This module offers a generic date/time string parser which is
 
1107
able to parse most known formats to represent a date and/or
 
1108
time.
 
1109
 
 
1110
==== parse() function ====
 
1111
That's probably the only function you'll need from this module.
 
1112
It offers you an interface to access the parser functionality and
 
1113
extract a {{{datetime}}} type out of a string.
 
1114
 
 
1115
The prototype of this function is:
 
1116
{{{
 
1117
parse(timestr)
 
1118
}}}
 
1119
 
 
1120
Additionally, the following keyword arguments are available:
 
1121
 
 
1122
    default::
 
1123
    If given, this must be a {{{datetime}}} instance. Any fields
 
1124
    missing in the parsed date will be copied from this instance.
 
1125
    The default value is the current date, at 00:00:00am.
 
1126
 
 
1127
    ignoretz::
 
1128
    If this is true, even if a timezone is found in the string,
 
1129
    the parser will not use it.
 
1130
 
 
1131
    tzinfos::
 
1132
    Using this keyword argument you may provide custom timezones
 
1133
    to the parser. If given, it must be either a dictionary with
 
1134
    the timezone abbreviation as key, or a function accepting a
 
1135
    timezone abbreviation and offset as argument. The dictionary
 
1136
    values and the function return must be a timezone offset
 
1137
    in seconds, a tzinfo subclass, or a string defining the
 
1138
    timezone (in the TZ environment variable format).
 
1139
 
 
1140
    dayfirst::
 
1141
    This option allow one to change the precedence in which
 
1142
    days are parsed in date strings. The default is given in the
 
1143
    parserinfo instance (the default parserinfo has it set to
 
1144
    False). If {{{dayfirst}}} is False, the {{{MM-DD-YYYY}}}
 
1145
    format will have precedence over {{{DD-MM-YYYY}}} in an
 
1146
    ambiguous date.
 
1147
 
 
1148
    yearfirst::
 
1149
    This option allow one to change the precedence in which
 
1150
    years are parsed in date strings. The default is given in
 
1151
    the parserinfo instance (the default parserinfo has it set
 
1152
    to False). If {{{yearfirst}}} is false, the {{{MM-DD-YY}}}
 
1153
    format will have precedence over {{{YY-MM-DD}}} in an
 
1154
    ambiguous date.
 
1155
 
 
1156
    fuzzy::
 
1157
    If {{{fuzzy}}} is set to True, unknown tokens in the string
 
1158
    will be ignored.
 
1159
 
 
1160
    parserinfo::
 
1161
    This parameter allows one to change how the string is parsed,
 
1162
    by using a different parserinfo class instance. Using it you
 
1163
    may, for example, intenationalize the parser strings, or make
 
1164
    it ignore additional words.
 
1165
 
 
1166
==== Format precedence ====
 
1167
Whenever an ambiguous date is found, the {{{dayfirst}}} and
 
1168
{{{yearfirst}}} parameters will control how the information
 
1169
is processed. Here is the precedence in each case:
 
1170
 
 
1171
If {{{dayfirst}}} is {{{False}}} and {{{yearfirst}}} is {{{False}}},
 
1172
(default, if no parameter is given):
 
1173
 
 
1174
    * {{{MM-DD-YY}}}
 
1175
    * {{{DD-MM-YY}}}
 
1176
    * {{{YY-MM-DD}}}
 
1177
 
 
1178
If {{{dayfirst}}} is {{{True}}} and {{{yearfirst}}} is {{{False}}}:
 
1179
 
 
1180
    * {{{DD-MM-YY}}}
 
1181
    * {{{MM-DD-YY}}}
 
1182
    * {{{YY-MM-DD}}}
 
1183
 
 
1184
If {{{dayfirst}}} is {{{False}}} and {{{yearfirst}}} is {{{True}}}:
 
1185
 
 
1186
    * {{{YY-MM-DD}}}
 
1187
    * {{{MM-DD-YY}}}
 
1188
    * {{{DD-MM-YY}}}
 
1189
 
 
1190
If {{{dayfirst}}} is {{{True}}} and {{{yearfirst}}} is {{{True}}}:
 
1191
 
 
1192
    * {{{YY-MM-DD}}}
 
1193
    * {{{DD-MM-YY}}}
 
1194
    * {{{MM-DD-YY}}}
 
1195
 
 
1196
==== Converting two digit years ====
 
1197
When a two digit year is found, it is processed considering
 
1198
the current year, so that the computed year is never more
 
1199
than 49 years after then current year, nor 50 years before the
 
1200
current year. In other words, if we are in year 2003, and the
 
1201
year 30 is found, it will be considered as 2030, but if the
 
1202
year 60 is found, it will be considered 1960.
 
1203
 
 
1204
==== Examples ====
 
1205
The following code will prepare the environment:
 
1206
{{{
 
1207
>>> from dateutil.parser import *
 
1208
>>> from dateutil.tz import *
 
1209
>>> from datetime import *
 
1210
>>> TZOFFSETS = {"BRST": -10800}
 
1211
>>> BRSTTZ = tzoffset(-10800, "BRST")
 
1212
>>> DEFAULT = datetime(2003, 9, 25)
 
1213
}}}
 
1214
 
 
1215
Some simple examples based on the {{{date}}} command, using the
 
1216
{{{TZOFFSET}}} dictionary to provide the BRST timezone offset.
 
1217
{{{
 
1218
>>> parse("Thu Sep 25 10:36:28 BRST 2003", tzinfos=TZOFFSETS)
 
1219
datetime.datetime(2003, 9, 25, 10, 36, 28, tzinfo=tzoffset('BRST', -10800))
 
1220
 
 
1221
>>> parse("2003 10:36:28 BRST 25 Sep Thu", tzinfos=TZOFFSETS)
 
1222
datetime.datetime(2003, 9, 25, 10, 36, 28, tzinfo=tzoffset('BRST', -10800))
 
1223
}}}
 
1224
 
 
1225
Notice that since BRST is my local timezone, parsing it without
 
1226
further timezone settings will yield a {{{tzlocal}}} timezone.
 
1227
{{{
 
1228
>>> parse("Thu Sep 25 10:36:28 BRST 2003")
 
1229
datetime.datetime(2003, 9, 25, 10, 36, 28, tzinfo=tzlocal())
 
1230
}}}
 
1231
 
 
1232
We can also ask to ignore the timezone explicitly:
 
1233
{{{
 
1234
>>> parse("Thu Sep 25 10:36:28 BRST 2003", ignoretz=True)
 
1235
datetime.datetime(2003, 9, 25, 10, 36, 28)
 
1236
}}}
 
1237
 
 
1238
That's the same as processing a string without timezone:
 
1239
{{{
 
1240
>>> parse("Thu Sep 25 10:36:28 2003")
 
1241
datetime.datetime(2003, 9, 25, 10, 36, 28)
 
1242
}}}
 
1243
 
 
1244
Without the year, but passing our {{{DEFAULT}}} datetime to return
 
1245
the same year, no mattering what year we currently are in:
 
1246
{{{
 
1247
>>> parse("Thu Sep 25 10:36:28", default=DEFAULT)
 
1248
datetime.datetime(2003, 9, 25, 10, 36, 28)
 
1249
}}}
 
1250
 
 
1251
Strip it further:
 
1252
{{{
 
1253
>>> parse("Thu Sep 10:36:28", default=DEFAULT)
 
1254
datetime.datetime(2003, 9, 25, 10, 36, 28)
 
1255
 
 
1256
>>> parse("Thu 10:36:28", default=DEFAULT)
 
1257
datetime.datetime(2003, 9, 25, 10, 36, 28)
 
1258
 
 
1259
>>> parse("Thu 10:36", default=DEFAULT)
 
1260
datetime.datetime(2003, 9, 25, 10, 36)
 
1261
 
 
1262
>>> parse("10:36", default=DEFAULT)
 
1263
datetime.datetime(2003, 9, 25, 10, 36)
 
1264
>>> 
 
1265
}}}
 
1266
 
 
1267
Strip in a different way:
 
1268
{{{
 
1269
>>> parse("Thu Sep 25 2003")
 
1270
datetime.datetime(2003, 9, 25, 0, 0)
 
1271
 
 
1272
>>> parse("Sep 25 2003")
 
1273
datetime.datetime(2003, 9, 25, 0, 0)
 
1274
 
 
1275
>>> parse("Sep 2003", default=DEFAULT)
 
1276
datetime.datetime(2003, 9, 25, 0, 0)
 
1277
 
 
1278
>>> parse("Sep", default=DEFAULT)
 
1279
datetime.datetime(2003, 9, 25, 0, 0)
 
1280
 
 
1281
>>> parse("2003", default=DEFAULT)
 
1282
datetime.datetime(2003, 9, 25, 0, 0)
 
1283
}}}
 
1284
 
 
1285
Another format, based on {{{date -R}}} (RFC822):
 
1286
{{{
 
1287
>>> parse("Thu, 25 Sep 2003 10:49:41 -0300")
 
1288
datetime.datetime(2003, 9, 25, 10, 49, 41, tzinfo=tzoffset(None, -10800))
 
1289
}}}
 
1290
 
 
1291
ISO format:
 
1292
{{{
 
1293
>>> parse("2003-09-25T10:49:41.5-03:00")
 
1294
datetime.datetime(2003, 9, 25, 10, 49, 41, 500000, tzinfo=tzoffset(None, -10800))
 
1295
}}}
 
1296
 
 
1297
Some variations:
 
1298
{{{
 
1299
>>> parse("2003-09-25T10:49:41")
 
1300
datetime.datetime(2003, 9, 25, 10, 49, 41)
 
1301
 
 
1302
>>> parse("2003-09-25T10:49")
 
1303
datetime.datetime(2003, 9, 25, 10, 49)
 
1304
 
 
1305
>>> parse("2003-09-25T10")
 
1306
datetime.datetime(2003, 9, 25, 10, 0)
 
1307
 
 
1308
>>> parse("2003-09-25")
 
1309
datetime.datetime(2003, 9, 25, 0, 0)
 
1310
}}}
 
1311
 
 
1312
ISO format, without separators:
 
1313
{{{
 
1314
>>> parse("20030925T104941.5-0300")
 
1315
datetime.datetime(2003, 9, 25, 10, 49, 41, 500000, tzinfo=tzinfo=tzoffset(None, -10800))
 
1316
 
 
1317
>>> parse("20030925T104941-0300")
 
1318
datetime.datetime(2003, 9, 25, 10, 49, 41, tzinfo=tzoffset(None, -10800))
 
1319
 
 
1320
>>> parse("20030925T104941")
 
1321
datetime.datetime(2003, 9, 25, 10, 49, 41)
 
1322
 
 
1323
>>> parse("20030925T1049")
 
1324
datetime.datetime(2003, 9, 25, 10, 49)
 
1325
 
 
1326
>>> parse("20030925T10")
 
1327
datetime.datetime(2003, 9, 25, 10, 0)
 
1328
 
 
1329
>>> parse("20030925")
 
1330
datetime.datetime(2003, 9, 25, 0, 0)
 
1331
}}}
 
1332
 
 
1333
Everything together.
 
1334
{{{
 
1335
>>> parse("199709020900")
 
1336
datetime.datetime(1997, 9, 2, 9, 0)
 
1337
>>> parse("19970902090059")
 
1338
datetime.datetime(1997, 9, 2, 9, 0, 59)
 
1339
}}}
 
1340
 
 
1341
Different date orderings:
 
1342
{{{
 
1343
>>> parse("2003-09-25")
 
1344
datetime.datetime(2003, 9, 25, 0, 0)
 
1345
 
 
1346
>>> parse("2003-Sep-25")
 
1347
datetime.datetime(2003, 9, 25, 0, 0)
 
1348
 
 
1349
>>> parse("25-Sep-2003")
 
1350
datetime.datetime(2003, 9, 25, 0, 0)
 
1351
 
 
1352
>>> parse("Sep-25-2003")
 
1353
datetime.datetime(2003, 9, 25, 0, 0)
 
1354
 
 
1355
>>> parse("09-25-2003")
 
1356
datetime.datetime(2003, 9, 25, 0, 0)
 
1357
 
 
1358
>>> parse("25-09-2003")
 
1359
datetime.datetime(2003, 9, 25, 0, 0)
 
1360
}}}
 
1361
 
 
1362
Check some ambiguous dates:
 
1363
{{{
 
1364
>>> parse("10-09-2003")
 
1365
datetime.datetime(2003, 10, 9, 0, 0)
 
1366
 
 
1367
>>> parse("10-09-2003", dayfirst=True)
 
1368
datetime.datetime(2003, 9, 10, 0, 0)
 
1369
 
 
1370
>>> parse("10-09-03")
 
1371
datetime.datetime(2003, 10, 9, 0, 0)
 
1372
 
 
1373
>>> parse("10-09-03", yearfirst=True)
 
1374
datetime.datetime(2010, 9, 3, 0, 0)
 
1375
}}}
 
1376
 
 
1377
Other date separators are allowed:
 
1378
{{{
 
1379
>>> parse("2003.Sep.25")
 
1380
datetime.datetime(2003, 9, 25, 0, 0)
 
1381
 
 
1382
>>> parse("2003/09/25")
 
1383
datetime.datetime(2003, 9, 25, 0, 0)
 
1384
}}}
 
1385
 
 
1386
Even with spaces:
 
1387
{{{
 
1388
>>> parse("2003 Sep 25")
 
1389
datetime.datetime(2003, 9, 25, 0, 0)
 
1390
 
 
1391
>>> parse("2003 09 25")
 
1392
datetime.datetime(2003, 9, 25, 0, 0)
 
1393
}}}
 
1394
 
 
1395
Hours with letters work:
 
1396
{{{
 
1397
>>> parse("10h36m28.5s", default=DEFAULT)
 
1398
datetime.datetime(2003, 9, 25, 10, 36, 28, 500000)
 
1399
 
 
1400
>>> parse("01s02h03m", default=DEFAULT)
 
1401
datetime.datetime(2003, 9, 25, 2, 3, 1)
 
1402
 
 
1403
>>> parse("01h02m03", default=DEFAULT)
 
1404
datetime.datetime(2003, 9, 3, 1, 2)
 
1405
 
 
1406
>>> parse("01h02", default=DEFAULT)
 
1407
datetime.datetime(2003, 9, 2, 1, 0)
 
1408
 
 
1409
>>> parse("01h02s", default=DEFAULT)
 
1410
datetime.datetime(2003, 9, 25, 1, 0, 2)
 
1411
}}}
 
1412
 
 
1413
With AM/PM:
 
1414
{{{
 
1415
>>> parse("10h am", default=DEFAULT)
 
1416
datetime.datetime(2003, 9, 25, 10, 0)
 
1417
 
 
1418
>>> parse("10pm", default=DEFAULT)
 
1419
datetime.datetime(2003, 9, 25, 22, 0)
 
1420
 
 
1421
>>> parse("12:00am", default=DEFAULT)
 
1422
datetime.datetime(2003, 9, 25, 0, 0)
 
1423
 
 
1424
>>> parse("12pm", default=DEFAULT)
 
1425
datetime.datetime(2003, 9, 25, 12, 0)
 
1426
}}}
 
1427
 
 
1428
Some special treating for ''pertain'' relations:
 
1429
{{{
 
1430
>>> parse("Sep 03", default=DEFAULT)
 
1431
datetime.datetime(2003, 9, 3, 0, 0)
 
1432
 
 
1433
>>> parse("Sep of 03", default=DEFAULT)
 
1434
datetime.datetime(2003, 9, 25, 0, 0)
 
1435
}}}
 
1436
 
 
1437
Fuzzy parsing:
 
1438
{{{
 
1439
>>> s = "Today is 25 of September of 2003, exactly " \
 
1440
...     "at 10:49:41 with timezone -03:00."
 
1441
>>> parse(s, fuzzy=True)
 
1442
datetime.datetime(2003, 9, 25, 10, 49, 41, tzinfo=tzoffset(None, -10800))
 
1443
}}}
 
1444
 
 
1445
Other random formats:
 
1446
{{{
 
1447
>>> parse("Wed, July 10, '96")
 
1448
datetime.datetime(1996, 7, 10, 0, 0)
 
1449
 
 
1450
>>> parse("1996.07.10 AD at 15:08:56 PDT", ignoretz=True)
 
1451
datetime.datetime(1996, 7, 10, 15, 8, 56)
 
1452
 
 
1453
>>> parse("Tuesday, April 12, 1952 AD 3:30:42pm PST", ignoretz=True)
 
1454
datetime.datetime(1952, 4, 12, 15, 30, 42)
 
1455
 
 
1456
>>> parse("November 5, 1994, 8:15:30 am EST", ignoretz=True)
 
1457
datetime.datetime(1994, 11, 5, 8, 15, 30)
 
1458
 
 
1459
>>> parse("3rd of May 2001")
 
1460
datetime.datetime(2001, 5, 3, 0, 0)
 
1461
 
 
1462
>>> parse("5:50 A.M. on June 13, 1990")
 
1463
datetime.datetime(1990, 6, 13, 5, 50)
 
1464
}}}
 
1465
 
 
1466
=== easter ===
 
1467
This module offers a generic easter computing method for
 
1468
any given year, using Western, Orthodox or Julian algorithms.
 
1469
 
 
1470
==== easter() function ====
 
1471
This method was ported from the work done by
 
1472
[http://users.chariot.net.au/~gmarts/eastalg.htm GM Arts],
 
1473
on top of the algorithm by
 
1474
[http://www.tondering.dk/claus/calendar.html Claus Tondering],
 
1475
which was based in part on the algorithm of Ouding (1940),
 
1476
as quoted in "Explanatory Supplement to the Astronomical
 
1477
Almanac", P.  Kenneth Seidelmann, editor.
 
1478
 
 
1479
This algorithm implements three different easter
 
1480
calculation methods:
 
1481
 
 
1482
    1. Original calculation in Julian calendar, valid in
 
1483
    dates after 326 AD
 
1484
    1. Original method, with date converted to Gregorian
 
1485
    calendar, valid in years 1583 to 4099
 
1486
    1. Revised method, in Gregorian calendar, valid in
 
1487
    years 1583 to 4099 as well
 
1488
 
 
1489
These methods are represented by the constants:
 
1490
{{{
 
1491
EASTER_JULIAN   = 1
 
1492
EASTER_ORTHODOX = 2
 
1493
EASTER_WESTERN  = 3
 
1494
}}}
 
1495
 
 
1496
The default method is method 3.
 
1497
 
 
1498
=== tz ===
 
1499
This module offers timezone implementations subclassing
 
1500
the abstract {{{datetime.tzinfo}}} type. There are
 
1501
classes to handle [http://www.twinsun.com/tz/tz-link.htm tzfile]
 
1502
format files (usually are in /etc/localtime,
 
1503
/usr/share/zoneinfo, etc), TZ environment string (in all
 
1504
known formats), given ranges (with help from relative
 
1505
deltas), local machine timezone, fixed offset timezone,
 
1506
and UTC timezone.
 
1507
 
 
1508
==== tzutc type ====
 
1509
This type implements a basic UTC timezone. The constructor of this
 
1510
type accepts no parameters.
 
1511
 
 
1512
==== tzutc examples ====
 
1513
{{{
 
1514
>>> from datetime import *
 
1515
>>> from dateutil.tz import *
 
1516
 
 
1517
>>> datetime.now()
 
1518
datetime.datetime(2003, 9, 27, 9, 40, 1, 521290)
 
1519
 
 
1520
>>> datetime.now(tzutc())
 
1521
datetime.datetime(2003, 9, 27, 12, 40, 12, 156379, tzinfo=tzutc())
 
1522
 
 
1523
>>> datetime.now(tzutc()).tzname()
 
1524
'UTC'
 
1525
}}}
 
1526
 
 
1527
==== tzoffset type ====
 
1528
This type implements a fixed offset timezone, with no
 
1529
support to daylight saving times. Here is the prototype of the
 
1530
type constructor:
 
1531
{{{
 
1532
tzoffset(name, offset)
 
1533
}}}
 
1534
 
 
1535
The {{{name}}} parameter may be optionally set to {{{None}}}, and
 
1536
{{{offset}}} must be given in seconds.
 
1537
 
 
1538
==== tzoffset examples ====
 
1539
{{{
 
1540
>>> from datetime import *
 
1541
>>> from dateutil.tz import *
 
1542
 
 
1543
>>> datetime.now(tzoffset("BRST", -10800))
 
1544
datetime.datetime(2003, 9, 27, 9, 52, 43, 624904, tzinfo=tzinfo=tzoffset('BRST', -10800))
 
1545
 
 
1546
>>> datetime.now(tzoffset("BRST", -10800)).tzname()
 
1547
'BRST'
 
1548
 
 
1549
>>> datetime.now(tzoffset("BRST", -10800)).astimezone(tzutc())
 
1550
datetime.datetime(2003, 9, 27, 12, 53, 11, 446419, tzinfo=tzutc())
 
1551
}}}
 
1552
 
 
1553
==== tzlocal type ====
 
1554
This type implements timezone settings as known by the
 
1555
operating system. The constructor of this type accepts no
 
1556
parameters.
 
1557
 
 
1558
==== tzlocal examples ====
 
1559
{{{
 
1560
>>> from datetime import *
 
1561
>>> from dateutil.tz import *
 
1562
 
 
1563
>>> datetime.now(tzlocal())
 
1564
datetime.datetime(2003, 9, 27, 10, 1, 43, 673605, tzinfo=tzlocal())
 
1565
 
 
1566
>>> datetime.now(tzlocal()).tzname()
 
1567
'BRST'
 
1568
 
 
1569
>>> datetime.now(tzlocal()).astimezone(tzoffset(None, 0))
 
1570
datetime.datetime(2003, 9, 27, 13, 3, 0, 11493, tzinfo=tzoffset(None, 0))
 
1571
}}}
 
1572
 
 
1573
==== tzstr type ====
 
1574
This type implements timezone settings extracted from a
 
1575
string in known TZ environment variable formats. Here is the prototype
 
1576
of the constructor:
 
1577
{{{
 
1578
tzstr(str)
 
1579
}}}
 
1580
 
 
1581
==== tzstr examples ====
 
1582
Here are examples of the recognized formats:
 
1583
 
 
1584
  * {{{EST5EDT}}}
 
1585
  * {{{EST5EDT,4,0,6,7200,10,0,26,7200,3600}}}
 
1586
  * {{{EST5EDT,4,1,0,7200,10,-1,0,7200,3600}}}
 
1587
  * {{{EST5EDT4,M4.1.0/02:00:00,M10-5-0/02:00}}}
 
1588
  * {{{EST5EDT4,95/02:00:00,298/02:00}}}
 
1589
  * {{{EST5EDT4,J96/02:00:00,J299/02:00}}}
 
1590
 
 
1591
Notice that if daylight information is not present, but a
 
1592
daylight abbreviation was provided, {{{tzstr}}} will follow the
 
1593
convention of using the first sunday of April to start daylight
 
1594
saving, and the last sunday of October to end it. If start or
 
1595
end time is not present, 2AM will be used, and if the daylight
 
1596
offset is not present, the standard offset plus one hour will
 
1597
be used. This convention is the same as used in the GNU libc.
 
1598
 
 
1599
This also means that some of the above examples are exactly
 
1600
equivalent, and all of these examples are equivalent
 
1601
in the year of 2003.
 
1602
 
 
1603
Here is the example mentioned in the
 
1604
[http://www.python.org/doc/current/lib/module-time.html time module documentation].
 
1605
{{{
 
1606
>>> os.environ['TZ'] = 'EST+05EDT,M4.1.0,M10.5.0'
 
1607
>>> time.tzset()
 
1608
>>> time.strftime('%X %x %Z')
 
1609
'02:07:36 05/08/03 EDT'
 
1610
>>> os.environ['TZ'] = 'AEST-10AEDT-11,M10.5.0,M3.5.0'
 
1611
>>> time.tzset()
 
1612
>>> time.strftime('%X %x %Z')
 
1613
'16:08:12 05/08/03 AEST'
 
1614
}}}
 
1615
 
 
1616
And here is an example showing the same information using {{{tzstr}}},
 
1617
without touching system settings.
 
1618
{{{
 
1619
>>> tz1 = tzstr('EST+05EDT,M4.1.0,M10.5.0')
 
1620
>>> tz2 = tzstr('AEST-10AEDT-11,M10.5.0,M3.5.0')
 
1621
>>> dt = datetime(2003, 5, 8, 2, 7, 36, tzinfo=tz1)
 
1622
>>> dt.strftime('%X %x %Z')
 
1623
'02:07:36 05/08/03 EDT'
 
1624
>>> dt.astimezone(tz2).strftime('%X %x %Z')
 
1625
'16:07:36 05/08/03 AEST'
 
1626
}}}
 
1627
 
 
1628
Are these really equivalent?
 
1629
{{{
 
1630
>>> tzstr('EST5EDT') == tzstr('EST5EDT,4,1,0,7200,10,-1,0,7200,3600')
 
1631
True
 
1632
}}}
 
1633
 
 
1634
Check the daylight limit.
 
1635
{{{
 
1636
>>> datetime(2003, 4, 6, 1, 59, tzinfo=tz).tzname()
 
1637
'EST'
 
1638
>>> datetime(2003, 4, 6, 2, 00, tzinfo=tz).tzname()
 
1639
'EDT'
 
1640
>>> datetime(2003, 10, 26, 0, 59, tzinfo=tz).tzname()
 
1641
'EDT'
 
1642
>>> datetime(2003, 10, 26, 1, 00, tzinfo=tz).tzname()
 
1643
'EST'
 
1644
}}}  
 
1645
 
 
1646
==== tzrange type ====
 
1647
This type offers the same functionality as the {{{tzstr}}} type, but
 
1648
instead of timezone strings, information is passed using
 
1649
{{{relativedelta}}}s which are applied to a datetime set to the first
 
1650
day of the year. Here is the prototype of this type's constructor:
 
1651
{{{
 
1652
tzrange(stdabbr, stdoffset=None, dstabbr=None, dstoffset=None, start=None, end=None):
 
1653
}}}
 
1654
 
 
1655
Offsets must be given in seconds. Information not provided will be
 
1656
set to the defaults, as explained in the {{{tzstr}}} section above.
 
1657
 
 
1658
==== tzrange examples ====
 
1659
{{{
 
1660
>>> tzstr('EST5EDT') == tzrange("EST", -18000, "EDT")
 
1661
True
 
1662
 
 
1663
>>> from dateutil.relativedelta import *
 
1664
>>> range1 = tzrange("EST", -18000, "EDT")
 
1665
>>> range2 = tzrange("EST", -18000, "EDT", -14400,
 
1666
...                  relativedelta(hours=+2, month=4, day=1, weekday=SU(+1)),
 
1667
...                  relativedelta(hours=+1, month=10, day=31, weekday=SU(-1)))>>> tzstr('EST5EDT') == range1 == range2
 
1668
>>> tzstr('EST5EDT') == range1 == range2
 
1669
True
 
1670
}}}
 
1671
 
 
1672
Notice a minor detail in the last example: while the DST should end
 
1673
at 2AM, the delta will catch 1AM. That's because the daylight saving
 
1674
time should end at 2AM standard time (the difference between STD and
 
1675
DST is 1h in the given example) instead of the DST time. That's how
 
1676
the {{{tzinfo}}} subtypes should deal with the extra hour that happens
 
1677
when going back to the standard time. Check
 
1678
[http://www.python.org/doc/current/lib/datetime-tzinfo.html tzinfo documentation]
 
1679
for more information.
 
1680
 
 
1681
==== tzfile type ====
 
1682
This type allows one to use tzfile(5) format timezone files to extract
 
1683
current and historical zone information. Here is the type constructor
 
1684
prototype:
 
1685
{{{
 
1686
tzfile(fileobj)
 
1687
}}}
 
1688
 
 
1689
Where {{{fileobj}}} is either a filename or a file-like object with
 
1690
a {{{read()}}} method.
 
1691
 
 
1692
==== tzfile examples ====
 
1693
{{{
 
1694
>>> tz = tzfile("/etc/localtime")
 
1695
>>> datetime.now(tz)
 
1696
datetime.datetime(2003, 9, 27, 12, 3, 48, 392138, tzinfo=tzfile('/etc/localtime'))
 
1697
 
 
1698
>>> datetime.now(tz).astimezone(tzutc())
 
1699
datetime.datetime(2003, 9, 27, 15, 3, 53, 70863, tzinfo=tzutc())
 
1700
 
 
1701
>>> datetime.now(tz).tzname()
 
1702
'BRST'
 
1703
>>> datetime(2003, 1, 1, tzinfo=tz).tzname()
 
1704
'BRDT'
 
1705
}}}
 
1706
 
 
1707
Check the daylight limit.
 
1708
{{{
 
1709
>>> tz = tzfile('/usr/share/zoneinfo/EST5EDT')
 
1710
>>> datetime(2003, 4, 6, 1, 59, tzinfo=tz).tzname()
 
1711
'EST'
 
1712
>>> datetime(2003, 4, 6, 2, 00, tzinfo=tz).tzname()
 
1713
'EDT'
 
1714
>>> datetime(2003, 10, 26, 0, 59, tzinfo=tz).tzname()
 
1715
'EDT'
 
1716
>>> datetime(2003, 10, 26, 1, 00, tzinfo=tz).tzname()
 
1717
'EST'
 
1718
}}}  
 
1719
 
 
1720
==== tzical type ====
 
1721
This type is able to parse
 
1722
[ftp://ftp.rfc-editor.org/in-notes/rfc2445.txt iCalendar]
 
1723
style {{{VTIMEZONE}}} sessions into a Python timezone object.
 
1724
The constuctor prototype is:
 
1725
{{{
 
1726
tzical(fileobj)
 
1727
}}}
 
1728
 
 
1729
Where {{{fileobj}}} is either a filename or a file-like object with
 
1730
a {{{read()}}} method.
 
1731
 
 
1732
==== tzical methods ====
 
1733
 
 
1734
    tzical.get(tzid=None)::
 
1735
    Since a single iCalendar file may contain more than one timezone,
 
1736
    you must ask for the timezone you want with this method. If there's
 
1737
    more than one timezone in the parsed file, you'll need to pass the
 
1738
    {{{tzid}}} parameter. Otherwise, leaving it empty will yield the only
 
1739
    available timezone.
 
1740
 
 
1741
==== tzical examples ====
 
1742
Here is a sample file extracted from the RFC. This file defines
 
1743
the {{{EST5EDT}}} timezone, and will be used in the following example.
 
1744
{{{
 
1745
BEGIN:VTIMEZONE
 
1746
TZID:US-Eastern
 
1747
LAST-MODIFIED:19870101T000000Z
 
1748
TZURL:http://zones.stds_r_us.net/tz/US-Eastern
 
1749
BEGIN:STANDARD
 
1750
DTSTART:19671029T020000
 
1751
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
 
1752
TZOFFSETFROM:-0400
 
1753
TZOFFSETTO:-0500
 
1754
TZNAME:EST
 
1755
END:STANDARD
 
1756
BEGIN:DAYLIGHT
 
1757
DTSTART:19870405T020000
 
1758
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
 
1759
TZOFFSETFROM:-0500
 
1760
TZOFFSETTO:-0400
 
1761
TZNAME:EDT
 
1762
END:DAYLIGHT
 
1763
END:VTIMEZONE
 
1764
}}}
 
1765
 
 
1766
And here is an example exploring a {{{tzical}}} type:
 
1767
{{{
 
1768
>>> from dateutil.tz import *; from datetime import *
 
1769
 
 
1770
>>> tz = tzical('EST5EDT.ics')
 
1771
>>> tz.keys()
 
1772
['US-Eastern']
 
1773
 
 
1774
>>> est = tz.get('US-Eastern')
 
1775
>>> est
 
1776
<tzicalvtz 'US-Eastern'>
 
1777
 
 
1778
>>> datetime.now(est)
 
1779
datetime.datetime(2003, 10, 6, 19, 44, 18, 667987, tzinfo=<tzicalvtz 'US-Eastern'>)
 
1780
 
 
1781
>>> est == tz.get()
 
1782
True
 
1783
}}}
 
1784
 
 
1785
Let's check the daylight ranges, as usual:
 
1786
{{{
 
1787
>>> datetime(2003, 4, 6, 1, 59, tzinfo=est).tzname()
 
1788
'EST'
 
1789
>>> datetime(2003, 4, 6, 2, 00, tzinfo=est).tzname()
 
1790
'EDT'
 
1791
 
 
1792
>>> datetime(2003, 10, 26, 0, 59, tzinfo=est).tzname()
 
1793
'EDT'
 
1794
>>> datetime(2003, 10, 26, 1, 00, tzinfo=est).tzname()
 
1795
'EST'
 
1796
}}}
 
1797
 
 
1798
==== gettz() function ====
 
1799
This function is a helper that will try its best to get the right
 
1800
timezone for your environment, or for the given string. The prototype
 
1801
is as follows:
 
1802
{{{
 
1803
gettz(name=None)
 
1804
}}}
 
1805
 
 
1806
If given, the parameter may be a filename, a path relative to the base
 
1807
of the timezone information path (the base could be
 
1808
{{{/usr/share/zoneinfo}}}, for example), a string timezone
 
1809
specification, or a timezone abbreviation. If {{{name}}} is not given,
 
1810
and the {{{TZ}}} environment variable is set, it's used instead. If the
 
1811
parameter is not given, and {{{TZ}}} is not set, the default tzfile
 
1812
paths will be tried.
 
1813
 
 
1814
Example:
 
1815
{{{
 
1816
>>> from dateutil.tz import *
 
1817
>>> gettz()
 
1818
tzfile('/etc/localtime')
 
1819
 
 
1820
>>> gettz("America/Sao Paulo")
 
1821
tzfile('/usr/share/zoneinfo/America/Sao_Paulo')
 
1822
 
 
1823
>>> gettz("EST5EDT")
 
1824
tzfile('/usr/share/zoneinfo/EST5EDT')
 
1825
 
 
1826
>>> gettz("EST5")
 
1827
tzstr('EST5')
 
1828
 
 
1829
>>> gettz('BRST')
 
1830
tzlocal()
 
1831
 
 
1832
>>> os.environ["TZ"] = "America/Sao Paulo"
 
1833
>>> gettz()
 
1834
tzfile('/usr/share/zoneinfo/America/Sao_Paulo')
 
1835
 
 
1836
>>> os.environ["TZ"] = "BRST"
 
1837
>>> gettz()
 
1838
tzlocal()
 
1839
 
 
1840
>>> gettz("Unavailable")
 
1841
>>> 
 
1842
}}}
 
1843
 
 
1844
## vim:ft=moin