~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-14 11:27:20 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-20050914112720-c66a21de86eafa6e
trim fai cribbage

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