diff options
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | README.old | 2000 | ||||
-rw-r--r-- | README.rst | 106 | ||||
-rw-r--r-- | dateutil/rrule.py | 4 | ||||
-rw-r--r-- | docs/examples.rst | 1393 | ||||
-rw-r--r-- | docs/index.rst | 7 |
7 files changed, 1507 insertions, 2009 deletions
@@ -12,6 +12,7 @@ Version 2.3 - Fixed tzwin silently not imported on windows python2 +- New maintainer, together with new hosting: GitHub, Travis, Read-The-Docs Version 2.2 ----------- diff --git a/README.md b/README.md deleted file mode 100644 index 365f308..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -[![Build Status](https://travis-ci.org/dateutil/dateutil.svg?branch=master)](https://travis-ci.org/dateutil/dateutil) -= dateutil = -== Description == -The dateutil module provides powerful extensions to -the standard datetime module, available in Python. diff --git a/README.old b/README.old deleted file mode 100644 index b1afd9c..0000000 --- a/README.old +++ /dev/null @@ -1,2000 +0,0 @@ -## This file is in the moin format. The latest version is found -## at https://moin.conectiva.com.br/DateUtil - -== Contents == -[[TableOfContents]] - -== Description == -The '''dateutil''' module provides powerful extensions to -the standard '''datetime''' module, available in Python. - -== Features == - - * Computing of relative deltas (next month, next year, - next monday, last week of month, etc); - - * Computing of relative deltas between two given - date and/or datetime objects; - - * Computing of dates based on very flexible recurrence rules, - using a superset of the - [ftp://ftp.rfc-editor.org/in-notes/rfc2445.txt iCalendar] - specification. Parsing of RFC strings is supported as well. - - * Generic parsing of dates in almost any string format; - - * Timezone (tzinfo) implementations for tzfile(5) format - files (/etc/localtime, /usr/share/zoneinfo, etc), TZ - environment string (in all known formats), iCalendar - format files, given ranges (with help from relative deltas), - local machine timezone, fixed offset timezone, UTC timezone, - and Windows registry-based time zones. - - * Internal up-to-date world timezone information based on - Olson's database. - - * Computing of Easter Sunday dates for any given year, - using Western, Orthodox or Julian algorithms; - - * More than 400 test cases. - -== Quick example == -Here's a snapshot, just to give an idea about the power of the -package. For more examples, look at the documentation below. - -Suppose you want to know how much time is left, in -years/months/days/etc, before the next easter happening on a -year with a Friday 13th in August, and you want to get today's -date out of the "date" unix system command. Here is the code: -{{{ -from dateutil.relativedelta import * -from dateutil.easter import * -from dateutil.rrule import * -from dateutil.parser import * -from datetime import * -import commands -import os -now = parse(commands.getoutput("date")) -today = now.date() -year = rrule(YEARLY,bymonth=8,bymonthday=13,byweekday=FR)[0].year -rdelta = relativedelta(easter(year), today) -print "Today is:", today -print "Year with next Aug 13th on a Friday is:", year -print "How far is the Easter of that year:", rdelta -print "And the Easter of that year is:", today+rdelta -}}} - -And here's the output: -{{{ -Today is: 2003-10-11 -Year with next Aug 13th on a Friday is: 2004 -How far is the Easter of that year: relativedelta(months=+6) -And the Easter of that year is: 2004-04-11 -}}} - -{i} Being exactly 6 months ahead was '''really''' a coincidence :) - -== Download == -The following files are available. - * attachment:python-dateutil-1.0.tar.bz2 - * attachment:python-dateutil-1.0-1.noarch.rpm - -== Author == -The dateutil module was written by Gustavo Niemeyer <gustavo@niemeyer.net> and -is currently maintained by Tomi Pieviläinen <tomi.pievilainen@iki.fi>. The latest -code is available in [https://launchpad.net/dateutil Launchpad]. - -== Documentation == -The following modules are available. - -=== relativedelta === -This module offers the '''relativedelta''' type, which is based -on the specification of the excelent work done by M.-A. Lemburg in his -[http://www.egenix.com/files/python/mxDateTime.html mxDateTime] -extension. However, notice that this type '''does not''' implement the -same algorithm as his work. Do not expect it to behave like -{{{mxDateTime}}}'s counterpart. - -==== relativedelta type ==== - -There's two different ways to build a relativedelta instance. The -first one is passing it two {{{date}}}/{{{datetime}}} instances: -{{{ -relativedelta(datetime1, datetime2) -}}} - -This will build the relative difference between {{{datetime1}}} and -{{{datetime2}}}, so that the following constraint is always true: -{{{ -datetime2+relativedelta(datetime1, datetime2) == datetime1 -}}} - -Notice that instead of {{{datetime}}} instances, you may use -{{{date}}} instances, or a mix of both. - -And the other way is to use any of the following keyword arguments: - - year, month, day, hour, minute, second, microsecond:: - Absolute information. - - years, months, weeks, days, hours, minutes, seconds, microseconds:: - Relative information, may be negative. - - weekday:: - One of the weekday instances ({{{MO}}}, {{{TU}}}, etc). These - instances may receive a parameter {{{n}}}, specifying the {{{n}}}th - weekday, which could be positive or negative (like {{{MO(+2)}}} or - {{{MO(-3)}}}. Not specifying it is the same as specifying {{{+1}}}. - You can also use an integer, where {{{0=MO}}}. Notice that, - for example, if the calculated date is already Monday, using - {{{MO}}} or {{{MO(+1)}}} (which is the same thing in this context), - won't change the day. - - leapdays:: - Will add given days to the date found, but only if the computed - year is a leap year and the computed date is post 28 of february. - - yearday, nlyearday:: - Set the yearday or the non-leap year day (jump leap days). - These are converted to {{{day}}}/{{{month}}}/{{{leapdays}}} - information. - -==== Behavior of operations ==== -If you're curious about exactly how the relative delta will act -on operations, here is a description of its behavior. - - 1. Calculate the absolute year, using the {{{year}}} argument, or the - original datetime year, if the argument is not present. - 1. Add the relative {{{years}}} argument to the absolute year. - 1. Do steps 1 and 2 for {{{month}}}/{{{months}}}. - 1. Calculate the absolute day, using the {{{day}}} argument, or the - original datetime day, if the argument is not present. Then, subtract - from the day until it fits in the year and month found after their - operations. - 1. Add the relative {{{days}}} argument to the absolute day. Notice - that the {{{weeks}}} argument is multiplied by 7 and added to {{{days}}}. - 1. If {{{leapdays}}} is present, the computed year is a leap year, and - the computed month is after february, remove one day from the found date. - 1. Do steps 1 and 2 for {{{hour}}}/{{{hours}}}, {{{minute}}}/{{{minutes}}}, - {{{second}}}/{{{seconds}}}, {{{microsecond}}}/{{{microseconds}}}. - 1. If the {{{weekday}}} argument is present, calculate the {{{n}}}th - occurrence of the given weekday. - -==== Examples ==== - -Let's begin our trip. -{{{ ->>> from datetime import *; from dateutil.relativedelta import * ->>> import calendar -}}} - -Store some values. -{{{ ->>> NOW = datetime.now() ->>> TODAY = date.today() ->>> NOW -datetime.datetime(2003, 9, 17, 20, 54, 47, 282310) ->>> TODAY -datetime.date(2003, 9, 17) -}}} - -Next month. -{{{ ->>> NOW+relativedelta(months=+1) -datetime.datetime(2003, 10, 17, 20, 54, 47, 282310) -}}} - -Next month, plus one week. -{{{ ->>> NOW+relativedelta(months=+1, weeks=+1) -datetime.datetime(2003, 10, 24, 20, 54, 47, 282310) -}}} - -Next month, plus one week, at 10am. -{{{ ->>> TODAY+relativedelta(months=+1, weeks=+1, hour=10) -datetime.datetime(2003, 10, 24, 10, 0) -}}} - -Let's try the other way around. Notice that the -hour setting we get in the relativedelta is relative, -since it's a difference, and the weeks parameter -has gone. -{{{ ->>> relativedelta(datetime(2003, 10, 24, 10, 0), TODAY) -relativedelta(months=+1, days=+7, hours=+10) -}}} - -One month before one year. -{{{ ->>> NOW+relativedelta(years=+1, months=-1) -datetime.datetime(2004, 8, 17, 20, 54, 47, 282310) -}}} - -How does it handle months with different numbers of days? -Notice that adding one month will never cross the month -boundary. -{{{ ->>> date(2003,1,27)+relativedelta(months=+1) -datetime.date(2003, 2, 27) ->>> date(2003,1,31)+relativedelta(months=+1) -datetime.date(2003, 2, 28) ->>> date(2003,1,31)+relativedelta(months=+2) -datetime.date(2003, 3, 31) -}}} - -The logic for years is the same, even on leap years. -{{{ ->>> date(2000,2,28)+relativedelta(years=+1) -datetime.date(2001, 2, 28) ->>> date(2000,2,29)+relativedelta(years=+1) -datetime.date(2001, 2, 28) - ->>> date(1999,2,28)+relativedelta(years=+1) -datetime.date(2000, 2, 28) ->>> date(1999,3,1)+relativedelta(years=+1) -datetime.date(2000, 3, 1) - ->>> date(2001,2,28)+relativedelta(years=-1) -datetime.date(2000, 2, 28) ->>> date(2001,3,1)+relativedelta(years=-1) -datetime.date(2000, 3, 1) -}}} - -Next friday. -{{{ ->>> TODAY+relativedelta(weekday=FR) -datetime.date(2003, 9, 19) - ->>> TODAY+relativedelta(weekday=calendar.FRIDAY) -datetime.date(2003, 9, 19) -}}} - -Last friday in this month. -{{{ ->>> TODAY+relativedelta(day=31, weekday=FR(-1)) -datetime.date(2003, 9, 26) -}}} - -Next wednesday (it's today!). -{{{ ->>> TODAY+relativedelta(weekday=WE(+1)) -datetime.date(2003, 9, 17) -}}} - -Next wednesday, but not today. -{{{ ->>> TODAY+relativedelta(days=+1, weekday=WE(+1)) -datetime.date(2003, 9, 24) -}}} - -Following -[http://www.cl.cam.ac.uk/~mgk25/iso-time.html ISO year week number notation] -find the first day of the 15th week of 1997. -{{{ ->>> datetime(1997,1,1)+relativedelta(day=4, weekday=MO(-1), weeks=+14) -datetime.datetime(1997, 4, 7, 0, 0) -}}} - -How long ago has the millennium changed? -{{{ ->>> relativedelta(NOW, date(2001,1,1)) -relativedelta(years=+2, months=+8, days=+16, - hours=+20, minutes=+54, seconds=+47, microseconds=+282310) -}}} - -How old is John? -{{{ ->>> johnbirthday = datetime(1978, 4, 5, 12, 0) ->>> relativedelta(NOW, johnbirthday) -relativedelta(years=+25, months=+5, days=+12, - hours=+8, minutes=+54, seconds=+47, microseconds=+282310) -}}} - -It works with dates too. -{{{ ->>> relativedelta(TODAY, johnbirthday) -relativedelta(years=+25, months=+5, days=+11, hours=+12) -}}} - -Obtain today's date using the yearday: -{{{ ->>> date(2003, 1, 1)+relativedelta(yearday=260) -datetime.date(2003, 9, 17) -}}} - -We can use today's date, since yearday should be absolute -in the given year: -{{{ ->>> TODAY+relativedelta(yearday=260) -datetime.date(2003, 9, 17) -}}} - -Last year it should be in the same day: -{{{ ->>> date(2002, 1, 1)+relativedelta(yearday=260) -datetime.date(2002, 9, 17) -}}} - -But not in a leap year: -{{{ ->>> date(2000, 1, 1)+relativedelta(yearday=260) -datetime.date(2000, 9, 16) -}}} - -We can use the non-leap year day to ignore this: -{{{ ->>> date(2000, 1, 1)+relativedelta(nlyearday=260) -datetime.date(2000, 9, 17) -}}} - -=== rrule === -The rrule module offers a small, complete, and very fast, implementation -of the recurrence rules documented in the -[ftp://ftp.rfc-editor.org/in-notes/rfc2445.txt iCalendar RFC], including -support for caching of results. - -==== rrule type ==== -That's the base of the rrule operation. It accepts all the keywords -defined in the RFC as its constructor parameters (except {{{byday}}}, -which was renamed to {{{byweekday}}}) and more. The constructor -prototype is: -{{{ -rrule(freq) -}}} - -Where {{{freq}}} must be one of {{{YEARLY}}}, {{{MONTHLY}}}, -{{{WEEKLY}}}, {{{DAILY}}}, {{{HOURLY}}}, {{{MINUTELY}}}, -or {{{SECONDLY}}}. - -Additionally, it supports the following keyword arguments: - - cache:: - If given, it must be a boolean value specifying to enable - or disable caching of results. If you will use the same - {{{rrule}}} instance multiple times, enabling caching will - improve the performance considerably. - - dtstart:: - The recurrence start. Besides being the base for the - recurrence, missing parameters in the final recurrence - instances will also be extracted from this date. If not - given, {{{datetime.now()}}} will be used instead. - - interval:: - The interval between each {{{freq}}} iteration. For example, - when using {{{YEARLY}}}, an interval of {{{2}}} means - once every two years, but with {{{HOURLY}}}, it means - once every two hours. The default interval is {{{1}}}. - - wkst:: - The week start day. Must be one of the {{{MO}}}, {{{TU}}}, - {{{WE}}} constants, or an integer, specifying the first day - of the week. This will affect recurrences based on weekly - periods. The default week start is got from - {{{calendar.firstweekday()}}}, and may be modified by - {{{calendar.setfirstweekday()}}}. - - count:: - How many occurrences will be generated. - - until:: - If given, this must be a {{{datetime}}} instance, that will - specify the limit of the recurrence. If a recurrence instance - happens to be the same as the {{{datetime}}} instance given - in the {{{until}}} keyword, this will be the last occurrence. - - bysetpos:: - If given, it must be either an integer, or a sequence of - integers, positive or negative. Each given integer will - specify an occurrence number, corresponding to the nth - occurrence of the rule inside the frequency period. For - example, a {{{bysetpos}}} of {{{-1}}} if combined with a - {{{MONTHLY}}} frequency, and a {{{byweekday}}} of - {{{(MO, TU, WE, TH, FR)}}}, will result in the last work - day of every month. - - bymonth:: - If given, it must be either an integer, or a sequence of - integers, meaning the months to apply the recurrence to. - - bymonthday:: - If given, it must be either an integer, or a sequence of - integers, meaning the month days to apply the recurrence to. - - byyearday:: - If given, it must be either an integer, or a sequence of - integers, meaning the year days to apply the recurrence to. - - byweekno:: - If given, it must be either an integer, or a sequence of - integers, meaning the week numbers to apply the recurrence - to. Week numbers have the meaning described in ISO8601, - that is, the first week of the year is that containing at - least four days of the new year. - - byweekday:: - If given, it must be either an integer ({{{0 == MO}}}), a - sequence of integers, one of the weekday constants - ({{{MO}}}, {{{TU}}}, etc), or a sequence of these constants. - When given, these variables will define the weekdays where - the recurrence will be applied. It's also possible to use - an argument {{{n}}} for the weekday instances, which will - mean the {{{n}}}''th'' occurrence of this weekday in the - period. For example, with {{{MONTHLY}}}, or with - {{{YEARLY}}} and {{{BYMONTH}}}, using {{{FR(+1)}}} - in {{{byweekday}}} will specify the first friday of the - month where the recurrence happens. Notice that in the RFC - documentation, this is specified as {{{BYDAY}}}, but was - renamed to avoid the ambiguity of that keyword. - - byhour:: - If given, it must be either an integer, or a sequence of - integers, meaning the hours to apply the recurrence to. - - byminute:: - If given, it must be either an integer, or a sequence of - integers, meaning the minutes to apply the recurrence to. - - bysecond:: - If given, it must be either an integer, or a sequence of - integers, meaning the seconds to apply the recurrence to. - - byeaster:: - If given, it must be either an integer, or a sequence of - integers, positive or negative. Each integer will define - an offset from the Easter Sunday. Passing the offset - {{{0}}} to {{{byeaster}}} will yield the Easter Sunday - itself. This is an extension to the RFC specification. - -==== rrule methods ==== -The following methods are available in {{{rrule}}} instances: - - rrule.before(dt, inc=False):: - Returns the last recurrence before the given {{{datetime}}} - instance. The {{{inc}}} keyword defines what happens if - {{{dt}}} '''is''' an occurrence. With {{{inc == True}}}, - if {{{dt}}} itself is an occurrence, it will be returned. - - rrule.after(dt, inc=False):: - Returns the first recurrence after the given {{{datetime}}} - instance. The {{{inc}}} keyword defines what happens if - {{{dt}}} '''is''' an occurrence. With {{{inc == True}}}, - if {{{dt}}} itself is an occurrence, it will be returned. - - rrule.between(after, before, inc=False):: - Returns all the occurrences of the rrule between {{{after}}} - and {{{before}}}. The {{{inc}}} keyword defines what happens - if {{{after}}} and/or {{{before}}} are themselves occurrences. - With {{{inc == True}}}, they will be included in the list, - if they are found in the recurrence set. - - rrule.count():: - Returns the number of recurrences in this set. It will have - go trough the whole recurrence, if this hasn't been done - before. - -Besides these methods, {{{rrule}}} instances also support -the {{{__getitem__()}}} and {{{__contains__()}}} special methods, -meaning that these are valid expressions: -{{{ -rr = rrule(...) -if datetime(...) in rr: - ... -print rr[0] -print rr[-1] -print rr[1:2] -print rr[::-2] -}}} - -The getitem/slicing mechanism is smart enough to avoid getting the whole -recurrence set, if possible. - -==== Notes ==== - - * The rrule type has no {{{byday}}} keyword. The equivalent keyword - has been replaced by the {{{byweekday}}} keyword, to remove the - ambiguity present in the original keyword. - - * Unlike documented in the RFC, the starting datetime ({{{dtstart}}}) - is not the first recurrence instance, unless it does fit in the - specified rules. In a python module context, this behavior makes more - sense than otherwise. Notice that you can easily get the original - behavior by using a rruleset and adding the {{{dtstart}}} as an - {{{rdate}}} recurrence. - - * Unlike documented in the RFC, every keyword is valid on every - frequency (the RFC documents that {{{byweekno}}} is only valid - on yearly frequencies, for example). - - * In addition to the documented keywords, a {{{byeaster}}} keyword - was introduced, making it easy to compute recurrent events relative - to the Easter Sunday. - -==== rrule examples ==== -These examples were converted from the RFC. - -Prepare the environment. -{{{ ->>> from dateutil.rrule import * ->>> from dateutil.parser import * ->>> from datetime import * - ->>> import pprint ->>> import sys ->>> sys.displayhook = pprint.pprint -}}} - -Daily, for 10 occurrences. -{{{ ->>> list(rrule(DAILY, count=10, - dtstart=parse("19970902T090000"))) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 3, 9, 0), - datetime.datetime(1997, 9, 4, 9, 0), - datetime.datetime(1997, 9, 5, 9, 0), - datetime.datetime(1997, 9, 6, 9, 0), - datetime.datetime(1997, 9, 7, 9, 0), - datetime.datetime(1997, 9, 8, 9, 0), - datetime.datetime(1997, 9, 9, 9, 0), - datetime.datetime(1997, 9, 10, 9, 0), - datetime.datetime(1997, 9, 11, 9, 0)] -}}} - -Daily until December 24, 1997 -{{{ ->>> list(rrule(DAILY, - dtstart=parse("19970902T090000"), - until=parse("19971224T000000"))) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 3, 9, 0), - datetime.datetime(1997, 9, 4, 9, 0), - (...) - datetime.datetime(1997, 12, 21, 9, 0), - datetime.datetime(1997, 12, 22, 9, 0), - datetime.datetime(1997, 12, 23, 9, 0)] -}}} - -Every other day, 5 occurrences. -{{{ ->>> list(rrule(DAILY, interval=2, count=5, - dtstart=parse("19970902T090000"))) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 4, 9, 0), - datetime.datetime(1997, 9, 6, 9, 0), - datetime.datetime(1997, 9, 8, 9, 0), - datetime.datetime(1997, 9, 10, 9, 0)] -}}} - -Every 10 days, 5 occurrences. -{{{ ->>> list(rrule(DAILY, interval=10, count=5, - dtstart=parse("19970902T090000"))) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 12, 9, 0), - datetime.datetime(1997, 9, 22, 9, 0), - datetime.datetime(1997, 10, 2, 9, 0), - datetime.datetime(1997, 10, 12, 9, 0)] -}}} - -Everyday in January, for 3 years. -{{{ ->>> list(rrule(YEARLY, bymonth=1, byweekday=range(7), - dtstart=parse("19980101T090000"), - until=parse("20000131T090000"))) -[datetime.datetime(1998, 1, 1, 9, 0), - datetime.datetime(1998, 1, 2, 9, 0), - (...) - datetime.datetime(1998, 1, 30, 9, 0), - datetime.datetime(1998, 1, 31, 9, 0), - datetime.datetime(1999, 1, 1, 9, 0), - datetime.datetime(1999, 1, 2, 9, 0), - (...) - datetime.datetime(1999, 1, 30, 9, 0), - datetime.datetime(1999, 1, 31, 9, 0), - datetime.datetime(2000, 1, 1, 9, 0), - datetime.datetime(2000, 1, 2, 9, 0), - (...) - datetime.datetime(2000, 1, 29, 9, 0), - datetime.datetime(2000, 1, 31, 9, 0)] -}}} - -Same thing, in another way. -{{{ ->>> list(rrule(DAILY, bymonth=1, - dtstart=parse("19980101T090000"), - until=parse("20000131T090000"))) -(...) -}}} - -Weekly for 10 occurrences. -{{{ ->>> list(rrule(WEEKLY, count=10, - dtstart=parse("19970902T090000"))) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 9, 9, 0), - datetime.datetime(1997, 9, 16, 9, 0), - datetime.datetime(1997, 9, 23, 9, 0), - datetime.datetime(1997, 9, 30, 9, 0), - datetime.datetime(1997, 10, 7, 9, 0), - datetime.datetime(1997, 10, 14, 9, 0), - datetime.datetime(1997, 10, 21, 9, 0), - datetime.datetime(1997, 10, 28, 9, 0), - datetime.datetime(1997, 11, 4, 9, 0)] -}}} - -Every other week, 6 occurrences. -{{{ ->>> list(rrule(WEEKLY, interval=2, count=6, - dtstart=parse("19970902T090000"))) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 16, 9, 0), - datetime.datetime(1997, 9, 30, 9, 0), - datetime.datetime(1997, 10, 14, 9, 0), - datetime.datetime(1997, 10, 28, 9, 0), - datetime.datetime(1997, 11, 11, 9, 0)] -}}} - -Weekly on Tuesday and Thursday for 5 weeks. -{{{ ->>> list(rrule(WEEKLY, count=10, wkst=SU, byweekday=(TU,TH), - dtstart=parse("19970902T090000"))) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 4, 9, 0), - datetime.datetime(1997, 9, 9, 9, 0), - datetime.datetime(1997, 9, 11, 9, 0), - datetime.datetime(1997, 9, 16, 9, 0), - datetime.datetime(1997, 9, 18, 9, 0), - datetime.datetime(1997, 9, 23, 9, 0), - datetime.datetime(1997, 9, 25, 9, 0), - datetime.datetime(1997, 9, 30, 9, 0), - datetime.datetime(1997, 10, 2, 9, 0)] -}}} - -Every other week on Tuesday and Thursday, for 8 occurrences. -{{{ ->>> list(rrule(WEEKLY, interval=2, count=8, - wkst=SU, byweekday=(TU,TH), - dtstart=parse("19970902T090000"))) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 4, 9, 0), - datetime.datetime(1997, 9, 16, 9, 0), - datetime.datetime(1997, 9, 18, 9, 0), - datetime.datetime(1997, 9, 30, 9, 0), - datetime.datetime(1997, 10, 2, 9, 0), - datetime.datetime(1997, 10, 14, 9, 0), - datetime.datetime(1997, 10, 16, 9, 0)] -}}} - -Monthly on the 1st Friday for ten occurrences. -{{{ ->>> list(rrule(MONTHLY, count=10, byweekday=FR(1), - dtstart=parse("19970905T090000"))) -[datetime.datetime(1997, 9, 5, 9, 0), - datetime.datetime(1997, 10, 3, 9, 0), - datetime.datetime(1997, 11, 7, 9, 0), - datetime.datetime(1997, 12, 5, 9, 0), - datetime.datetime(1998, 1, 2, 9, 0), - datetime.datetime(1998, 2, 6, 9, 0), - datetime.datetime(1998, 3, 6, 9, 0), - datetime.datetime(1998, 4, 3, 9, 0), - datetime.datetime(1998, 5, 1, 9, 0), - datetime.datetime(1998, 6, 5, 9, 0)] -}}} - -Every other month on the 1st and last Sunday of the month for 10 occurrences. -{{{ ->>> list(rrule(MONTHLY, interval=2, count=10, - byweekday=(SU(1), SU(-1)), - dtstart=parse("19970907T090000"))) -[datetime.datetime(1997, 9, 7, 9, 0), - datetime.datetime(1997, 9, 28, 9, 0), - datetime.datetime(1997, 11, 2, 9, 0), - datetime.datetime(1997, 11, 30, 9, 0), - datetime.datetime(1998, 1, 4, 9, 0), - datetime.datetime(1998, 1, 25, 9, 0), - datetime.datetime(1998, 3, 1, 9, 0), - datetime.datetime(1998, 3, 29, 9, 0), - datetime.datetime(1998, 5, 3, 9, 0), - datetime.datetime(1998, 5, 31, 9, 0)] -}}} - -Monthly on the second to last Monday of the month for 6 months. -{{{ ->>> list(rrule(MONTHLY, count=6, byweekday=MO(-2), - dtstart=parse("19970922T090000"))) -[datetime.datetime(1997, 9, 22, 9, 0), - datetime.datetime(1997, 10, 20, 9, 0), - datetime.datetime(1997, 11, 17, 9, 0), - datetime.datetime(1997, 12, 22, 9, 0), - datetime.datetime(1998, 1, 19, 9, 0), - datetime.datetime(1998, 2, 16, 9, 0)] -}}} - -Monthly on the third to the last day of the month, for 6 months. -{{{ ->>> list(rrule(MONTHLY, count=6, bymonthday=-3, - dtstart=parse("19970928T090000"))) -[datetime.datetime(1997, 9, 28, 9, 0), - datetime.datetime(1997, 10, 29, 9, 0), - datetime.datetime(1997, 11, 28, 9, 0), - datetime.datetime(1997, 12, 29, 9, 0), - datetime.datetime(1998, 1, 29, 9, 0), - datetime.datetime(1998, 2, 26, 9, 0)] -}}} - -Monthly on the 2nd and 15th of the month for 5 occurrences. -{{{ ->>> list(rrule(MONTHLY, count=5, bymonthday=(2,15), - dtstart=parse("19970902T090000"))) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 15, 9, 0), - datetime.datetime(1997, 10, 2, 9, 0), - datetime.datetime(1997, 10, 15, 9, 0), - datetime.datetime(1997, 11, 2, 9, 0)] -}}} - -Monthly on the first and last day of the month for 3 occurrences. -{{{ ->>> list(rrule(MONTHLY, count=5, bymonthday=(-1,1,), - dtstart=parse("1997090 -2T090000"))) -[datetime.datetime(1997, 9, 30, 9, 0), - datetime.datetime(1997, 10, 1, 9, 0), - datetime.datetime(1997, 10, 31, 9, 0), - datetime.datetime(1997, 11, 1, 9, 0), - datetime.datetime(1997, 11, 30, 9, 0)] -}}} - -Every 18 months on the 10th thru 15th of the month for 10 occurrences. -{{{ ->>> list(rrule(MONTHLY, interval=18, count=10, - bymonthday=range(10,16), - dtstart=parse("19970910T090000"))) -[datetime.datetime(1997, 9, 10, 9, 0), - datetime.datetime(1997, 9, 11, 9, 0), - datetime.datetime(1997, 9, 12, 9, 0), - datetime.datetime(1997, 9, 13, 9, 0), - datetime.datetime(1997, 9, 14, 9, 0), - datetime.datetime(1997, 9, 15, 9, 0), - datetime.datetime(1999, 3, 10, 9, 0), - datetime.datetime(1999, 3, 11, 9, 0), - datetime.datetime(1999, 3, 12, 9, 0), - datetime.datetime(1999, 3, 13, 9, 0)] -}}} - -Every Tuesday, every other month, 6 occurences. -{{{ ->>> list(rrule(MONTHLY, interval=2, count=6, byweekday=TU, - dtstart=parse("19970902T090000"))) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 9, 9, 0), - datetime.datetime(1997, 9, 16, 9, 0), - datetime.datetime(1997, 9, 23, 9, 0), - datetime.datetime(1997, 9, 30, 9, 0), - datetime.datetime(1997, 11, 4, 9, 0)] -}}} - -Yearly in June and July for 10 occurrences. -{{{ ->>> list(rrule(YEARLY, count=4, bymonth=(6,7), - dtstart=parse("19970610T0900 -00"))) -[datetime.datetime(1997, 6, 10, 9, 0), - datetime.datetime(1997, 7, 10, 9, 0), - datetime.datetime(1998, 6, 10, 9, 0), - datetime.datetime(1998, 7, 10, 9, 0)] -}}} - -Every 3rd year on the 1st, 100th and 200th day for 4 occurrences. -{{{ ->>> list(rrule(YEARLY, count=4, interval=3, byyearday=(1,100,200), - dtstart=parse("19970101T090000"))) -[datetime.datetime(1997, 1, 1, 9, 0), - datetime.datetime(1997, 4, 10, 9, 0), - datetime.datetime(1997, 7, 19, 9, 0), - datetime.datetime(2000, 1, 1, 9, 0)] -}}} - -Every 20th Monday of the year, 3 occurrences. -{{{ ->>> list(rrule(YEARLY, count=3, byweekday=MO(20), - dtstart=parse("19970519T090000"))) -[datetime.datetime(1997, 5, 19, 9, 0), - datetime.datetime(1998, 5, 18, 9, 0), - datetime.datetime(1999, 5, 17, 9, 0)] -}}} - -Monday of week number 20 (where the default start of the week is Monday), -3 occurrences. -{{{ ->>> list(rrule(YEARLY, count=3, byweekno=20, byweekday=MO, - dtstart=parse("19970512T090000"))) -[datetime.datetime(1997, 5, 12, 9, 0), - datetime.datetime(1998, 5, 11, 9, 0), - datetime.datetime(1999, 5, 17, 9, 0)] -}}} - -The week number 1 may be in the last year. -{{{ ->>> list(rrule(WEEKLY, count=3, byweekno=1, byweekday=MO, - dtstart=parse("19970902T090000"))) -[datetime.datetime(1997, 12, 29, 9, 0), - datetime.datetime(1999, 1, 4, 9, 0), - datetime.datetime(2000, 1, 3, 9, 0)] -}}} - -And the week numbers greater than 51 may be in the next year. -{{{ ->>> list(rrule(WEEKLY, count=3, byweekno=52, byweekday=SU, - dtstart=parse("19970902T090000"))) -[datetime.datetime(1997, 12, 28, 9, 0), - datetime.datetime(1998, 12, 27, 9, 0), - datetime.datetime(2000, 1, 2, 9, 0)] -}}} - -Only some years have week number 53: -{{{ ->>> list(rrule(WEEKLY, count=3, byweekno=53, byweekday=MO, - dtstart=parse("19970902T090000"))) -[datetime.datetime(1998, 12, 28, 9, 0), - datetime.datetime(2004, 12, 27, 9, 0), - datetime.datetime(2009, 12, 28, 9, 0)] -}}} - -Every Friday the 13th, 4 occurrences. -{{{ ->>> list(rrule(YEARLY, count=4, byweekday=FR, bymonthday=13, - dtstart=parse("19970902T090000"))) -[datetime.datetime(1998, 2, 13, 9, 0), - datetime.datetime(1998, 3, 13, 9, 0), - datetime.datetime(1998, 11, 13, 9, 0), - datetime.datetime(1999, 8, 13, 9, 0)] -}}} - -Every four years, the first Tuesday after a Monday in November, -3 occurrences (U.S. Presidential Election day): -{{{ ->>> list(rrule(YEARLY, interval=4, count=3, bymonth=11, - byweekday=TU, bymonthday=(2,3,4,5,6,7,8), - dtstart=parse("19961105T090000"))) -[datetime.datetime(1996, 11, 5, 9, 0), - datetime.datetime(2000, 11, 7, 9, 0), - datetime.datetime(2004, 11, 2, 9, 0)] -}}} - -The 3rd instance into the month of one of Tuesday, Wednesday or -Thursday, for the next 3 months: -{{{ ->>> list(rrule(MONTHLY, count=3, byweekday=(TU,WE,TH), - bysetpos=3, dtstart=parse("19970904T090000"))) -[datetime.datetime(1997, 9, 4, 9, 0), - datetime.datetime(1997, 10, 7, 9, 0), - datetime.datetime(1997, 11, 6, 9, 0)] -}}} - -The 2nd to last weekday of the month, 3 occurrences. -{{{ ->>> list(rrule(MONTHLY, count=3, byweekday=(MO,TU,WE,TH,FR), - bysetpos=-2, dtstart=parse("19970929T090000"))) -[datetime.datetime(1997, 9, 29, 9, 0), - datetime.datetime(1997, 10, 30, 9, 0), - datetime.datetime(1997, 11, 27, 9, 0)] -}}} - -Every 3 hours from 9:00 AM to 5:00 PM on a specific day. -{{{ ->>> list(rrule(HOURLY, interval=3, - dtstart=parse("19970902T090000"), - until=parse("19970902T170000"))) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 2, 12, 0), - datetime.datetime(1997, 9, 2, 15, 0)] -}}} - -Every 15 minutes for 6 occurrences. -{{{ ->>> list(rrule(MINUTELY, interval=15, count=6, - dtstart=parse("19970902T090000"))) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 2, 9, 15), - datetime.datetime(1997, 9, 2, 9, 30), - datetime.datetime(1997, 9, 2, 9, 45), - datetime.datetime(1997, 9, 2, 10, 0), - datetime.datetime(1997, 9, 2, 10, 15)] -}}} - -Every hour and a half for 4 occurrences. -{{{ ->>> list(rrule(MINUTELY, interval=90, count=4, - dtstart=parse("19970902T090000"))) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 2, 10, 30), - datetime.datetime(1997, 9, 2, 12, 0), - datetime.datetime(1997, 9, 2, 13, 30)] -}}} - -Every 20 minutes from 9:00 AM to 4:40 PM for two days. -{{{ ->>> list(rrule(MINUTELY, interval=20, count=48, - byhour=range(9,17), byminute=(0,20,40), - dtstart=parse("19970902T090000"))) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 2, 9, 20), - (...) - datetime.datetime(1997, 9, 2, 16, 20), - datetime.datetime(1997, 9, 2, 16, 40), - datetime.datetime(1997, 9, 3, 9, 0), - datetime.datetime(1997, 9, 3, 9, 20), - (...) - datetime.datetime(1997, 9, 3, 16, 20), - datetime.datetime(1997, 9, 3, 16, 40)] -}}} - -An example where the days generated makes a difference because of {{{wkst}}}. -{{{ ->>> list(rrule(WEEKLY, interval=2, count=4, - byweekday=(TU,SU), wkst=MO, - dtstart=parse("19970805T090000"))) -[datetime.datetime(1997, 8, 5, 9, 0), - datetime.datetime(1997, 8, 10, 9, 0), - datetime.datetime(1997, 8, 19, 9, 0), - datetime.datetime(1997, 8, 24, 9, 0)] - ->>> list(rrule(WEEKLY, interval=2, count=4, - byweekday=(TU,SU), wkst=SU, - dtstart=parse("19970805T090000"))) -[datetime.datetime(1997, 8, 5, 9, 0), - datetime.datetime(1997, 8, 17, 9, 0), - datetime.datetime(1997, 8, 19, 9, 0), - datetime.datetime(1997, 8, 31, 9, 0)] -}}} - -==== rruleset type ==== -The {{{rruleset}}} type allows more complex recurrence setups, mixing -multiple rules, dates, exclusion rules, and exclusion dates. -The type constructor takes the following keyword arguments: - - cache:: - If True, caching of results will be enabled, improving performance - of multiple queries considerably. - -==== rruleset methods ==== -The following methods are available: - - rruleset.rrule(rrule):: - Include the given {{{rrule}}} instance in the recurrence set - generation. - - rruleset.rdate(dt):: - Include the given {{{datetime}}} instance in the recurrence - set generation. - - rruleset.exrule(rrule):: - Include the given {{{rrule}}} instance in the recurrence set - exclusion list. Dates which are part of the given recurrence - rules will not be generated, even if some inclusive {{{rrule}}} - or {{{rdate}}} matches them. - - rruleset.exdate(dt):: - Include the given {{{datetime}}} instance in the recurrence set - exclusion list. Dates included that way will not be generated, - even if some inclusive {{{rrule}}} or {{{rdate}}} matches them. - - rruleset.before(dt, inc=False):: - Returns the last recurrence before the given {{{datetime}}} - instance. The {{{inc}}} keyword defines what happens if - {{{dt}}} '''is''' an occurrence. With {{{inc == True}}}, - if {{{dt}}} itself is an occurrence, it will be returned. - - rruleset.after(dt, inc=False):: - Returns the first recurrence after the given {{{datetime}}} - instance. The {{{inc}}} keyword defines what happens if - {{{dt}}} '''is''' an occurrence. With {{{inc == True}}}, - if {{{dt}}} itself is an occurrence, it will be returned. - - rruleset.between(after, before, inc=False):: - Returns all the occurrences of the rrule between {{{after}}} - and {{{before}}}. The {{{inc}}} keyword defines what happens - if {{{after}}} and/or {{{before}}} are themselves occurrences. - With {{{inc == True}}}, they will be included in the list, - if they are found in the recurrence set. - - rruleset.count():: - Returns the number of recurrences in this set. It will have - go trough the whole recurrence, if this hasn't been done - before. - -Besides these methods, {{{rruleset}}} instances also support -the {{{__getitem__()}}} and {{{__contains__()}}} special methods, -meaning that these are valid expressions: -{{{ -set = rruleset(...) -if datetime(...) in set: - ... -print set[0] -print set[-1] -print set[1:2] -print set[::-2] -}}} - -The getitem/slicing mechanism is smart enough to avoid getting the whole -recurrence set, if possible. - -==== rruleset examples ==== -Daily, for 7 days, jumping Saturday and Sunday occurrences. -{{{ ->>> set = rruleset() ->>> set.rrule(rrule(DAILY, count=7, - dtstart=parse("19970902T090000"))) ->>> set.exrule(rrule(YEARLY, byweekday=(SA,SU), - dtstart=parse("19970902T090000"))) ->>> list(set) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 3, 9, 0), - datetime.datetime(1997, 9, 4, 9, 0), - datetime.datetime(1997, 9, 5, 9, 0), - datetime.datetime(1997, 9, 8, 9, 0)] -}}} - -Weekly, for 4 weeks, plus one time on day 7, and not on day 16. -{{{ ->>> set = rruleset() ->>> set.rrule(rrule(WEEKLY, count=4, - dtstart=parse("19970902T090000"))) ->>> set.rdate(datetime.datetime(1997, 9, 7, 9, 0)) ->>> set.exdate(datetime.datetime(1997, 9, 16, 9, 0)) ->>> list(set) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 7, 9, 0), - datetime.datetime(1997, 9, 9, 9, 0), - datetime.datetime(1997, 9, 23, 9, 0)] -}}} - -==== rrulestr() function ==== -The {{{rrulestr()}}} function is a parser for ''RFC-like'' syntaxes. -The function prototype is: -{{{ -rrulestr(str) -}}} - -The string passed as parameter may be a multiple line string, a -single line string, or just the {{{RRULE}}} property value. - -Additionally, it accepts the following keyword arguments: - - cache:: - If {{{True}}}, the {{{rruleset}}} or {{{rrule}}} created instance - will cache its results. Default is not to cache. - - dtstart:: - If given, it must be a {{{datetime}}} instance that will be used - when no {{{DTSTART}}} property is found in the parsed string. If - it is not given, and the property is not found, {{{datetime.now()}}} - will be used instead. - - unfold:: - If set to {{{True}}}, lines will be unfolded following the RFC - specification. It defaults to {{{False}}}, meaning that spaces - before every line will be stripped. - - forceset:: - If set to {{{True}}} a {{{rruleset}}} instance will be returned, - even if only a single rule is found. The default is to return an - {{{rrule}}} if possible, and an {{{rruleset}}} if necessary. - - compatible:: - If set to {{{True}}}, the parser will operate in RFC-compatible - mode. Right now it means that {{{unfold}}} will be turned on, - and if a {{{DTSTART}}} is found, it will be considered the first - recurrence instance, as documented in the RFC. - - ignoretz:: - If set to {{{True}}}, the date parser will ignore timezone - information available in the {{{DTSTART}}} property, or the - {{{UNTIL}}} attribute. - - tzinfos:: - If set, it will be passed to the datetime string parser to - resolve unknown timezone settings. For more information about - what could be used here, check the parser documentation. - -==== rrulestr() examples ==== - -Every 10 days, 5 occurrences. -{{{ ->>> list(rrulestr(""" -... DTSTART:19970902T090000 -... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5 -... """)) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 12, 9, 0), - datetime.datetime(1997, 9, 22, 9, 0), - datetime.datetime(1997, 10, 2, 9, 0), - datetime.datetime(1997, 10, 12, 9, 0)] -}}} - -Same thing, but passing only the {{{RRULE}}} value. -{{{ ->>> list(rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5", - dtstart=parse("19970902T090000"))) -[datetime.datetime(1997, 9, 2, 9, 0), - datetime.datetime(1997, 9, 12, 9, 0), - datetime.datetime(1997, 9, 22, 9, 0), - datetime.datetime(1997, 10, 2, 9, 0), - datetime.datetime(1997, 10, 12, 9, 0)] -}}} - -Notice that when using a single rule, it returns an -{{{rrule}}} instance, unless {{{forceset}}} was used. -{{{ ->>> rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5") -<dateutil.rrule.rrule instance at 0x30269f08> - ->>> rrulestr(""" -... DTSTART:19970902T090000 -... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5 -... """) -<dateutil.rrule.rrule instance at 0x302699e0> - ->>> rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5", forceset=True) -<dateutil.rrule.rruleset instance at 0x30269f08> -}}} - -But when an {{{rruleset}}} is needed, it is automatically used. -{{{ ->>> rrulestr(""" -... DTSTART:19970902T090000 -... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5 -... RRULE:FREQ=DAILY;INTERVAL=5;COUNT=3 -... """) -<dateutil.rrule.rruleset instance at 0x302699e0> -}}} - -=== parser === -This module offers a generic date/time string parser which is -able to parse most known formats to represent a date and/or -time. - -==== parse() function ==== -That's probably the only function you'll need from this module. -It offers you an interface to access the parser functionality and -extract a {{{datetime}}} type out of a string. - -The prototype of this function is: -{{{ -parse(timestr) -}}} - -Additionally, the following keyword arguments are available: - - default:: - If given, this must be a {{{datetime}}} instance. Any fields - missing in the parsed date will be copied from this instance. - The default value is the current date, at 00:00:00am. - - ignoretz:: - If this is true, even if a timezone is found in the string, - the parser will not use it. - - tzinfos:: - Using this keyword argument you may provide custom timezones - to the parser. If given, it must be either a dictionary with - the timezone abbreviation as key, or a function accepting a - timezone abbreviation and offset as argument. The dictionary - values and the function return must be a timezone offset - in seconds, a tzinfo subclass, or a string defining the - timezone (in the TZ environment variable format). - - dayfirst:: - This option allow one to change the precedence in which - days are parsed in date strings. The default is given in the - parserinfo instance (the default parserinfo has it set to - False). If {{{dayfirst}}} is False, the {{{MM-DD-YYYY}}} - format will have precedence over {{{DD-MM-YYYY}}} in an - ambiguous date. - - yearfirst:: - This option allow one to change the precedence in which - years are parsed in date strings. The default is given in - the parserinfo instance (the default parserinfo has it set - to False). If {{{yearfirst}}} is false, the {{{MM-DD-YY}}} - format will have precedence over {{{YY-MM-DD}}} in an - ambiguous date. - - fuzzy:: - If {{{fuzzy}}} is set to True, unknown tokens in the string - will be ignored. - - fuzzy_with_tokens:: - Similar to {{{fuzzy}}}, but will result a tuple of the normal - results and the skipped tokens. - - parserinfo:: - This parameter allows one to change how the string is parsed, - by using a different parserinfo class instance. Using it you - may, for example, intenationalize the parser strings, or make - it ignore additional words. - -==== Format precedence ==== -Whenever an ambiguous date is found, the {{{dayfirst}}} and -{{{yearfirst}}} parameters will control how the information -is processed. Here is the precedence in each case: - -If {{{dayfirst}}} is {{{False}}} and {{{yearfirst}}} is {{{False}}}, -(default, if no parameter is given): - - * {{{MM-DD-YY}}} - * {{{DD-MM-YY}}} - * {{{YY-MM-DD}}} - -If {{{dayfirst}}} is {{{True}}} and {{{yearfirst}}} is {{{False}}}: - - * {{{DD-MM-YY}}} - * {{{MM-DD-YY}}} - * {{{YY-MM-DD}}} - -If {{{dayfirst}}} is {{{False}}} and {{{yearfirst}}} is {{{True}}}: - - * {{{YY-MM-DD}}} - * {{{MM-DD-YY}}} - * {{{DD-MM-YY}}} - -If {{{dayfirst}}} is {{{True}}} and {{{yearfirst}}} is {{{True}}}: - - * {{{YY-MM-DD}}} - * {{{DD-MM-YY}}} - * {{{MM-DD-YY}}} - -==== Converting two digit years ==== -When a two digit year is found, it is processed considering -the current year, so that the computed year is never more -than 49 years after the current year, nor 50 years before the -current year. In other words, if we are in year 2003, and the -year 30 is found, it will be considered as 2030, but if the -year 60 is found, it will be considered 1960. - -==== Examples ==== -The following code will prepare the environment: -{{{ ->>> from dateutil.parser import * ->>> from dateutil.tz import * ->>> from datetime import * ->>> TZOFFSETS = {"BRST": -10800} ->>> BRSTTZ = tzoffset(-10800, "BRST") ->>> DEFAULT = datetime(2003, 9, 25) -}}} - -Some simple examples based on the {{{date}}} command, using the -{{{TZOFFSET}}} dictionary to provide the BRST timezone offset. -{{{ ->>> parse("Thu Sep 25 10:36:28 BRST 2003", tzinfos=TZOFFSETS) -datetime.datetime(2003, 9, 25, 10, 36, 28, - tzinfo=tzoffset('BRST', -10800)) - ->>> parse("2003 10:36:28 BRST 25 Sep Thu", tzinfos=TZOFFSETS) -datetime.datetime(2003, 9, 25, 10, 36, 28, - tzinfo=tzoffset('BRST', -10800)) -}}} - -Notice that since BRST is my local timezone, parsing it without -further timezone settings will yield a {{{tzlocal}}} timezone. -{{{ ->>> parse("Thu Sep 25 10:36:28 BRST 2003") -datetime.datetime(2003, 9, 25, 10, 36, 28, tzinfo=tzlocal()) -}}} - -We can also ask to ignore the timezone explicitly: -{{{ ->>> parse("Thu Sep 25 10:36:28 BRST 2003", ignoretz=True) -datetime.datetime(2003, 9, 25, 10, 36, 28) -}}} - -That's the same as processing a string without timezone: -{{{ ->>> parse("Thu Sep 25 10:36:28 2003") -datetime.datetime(2003, 9, 25, 10, 36, 28) -}}} - -Without the year, but passing our {{{DEFAULT}}} datetime to return -the same year, no mattering what year we currently are in: -{{{ ->>> parse("Thu Sep 25 10:36:28", default=DEFAULT) -datetime.datetime(2003, 9, 25, 10, 36, 28) -}}} - -Strip it further: -{{{ ->>> parse("Thu Sep 10:36:28", default=DEFAULT) -datetime.datetime(2003, 9, 25, 10, 36, 28) - ->>> parse("Thu 10:36:28", default=DEFAULT) -datetime.datetime(2003, 9, 25, 10, 36, 28) - ->>> parse("Thu 10:36", default=DEFAULT) -datetime.datetime(2003, 9, 25, 10, 36) - ->>> parse("10:36", default=DEFAULT) -datetime.datetime(2003, 9, 25, 10, 36) ->>> -}}} - -Strip in a different way: -{{{ ->>> parse("Thu Sep 25 2003") -datetime.datetime(2003, 9, 25, 0, 0) - ->>> parse("Sep 25 2003") -datetime.datetime(2003, 9, 25, 0, 0) - ->>> parse("Sep 2003", default=DEFAULT) -datetime.datetime(2003, 9, 25, 0, 0) - ->>> parse("Sep", default=DEFAULT) -datetime.datetime(2003, 9, 25, 0, 0) - ->>> parse("2003", default=DEFAULT) -datetime.datetime(2003, 9, 25, 0, 0) -}}} - -Another format, based on {{{date -R}}} (RFC822): -{{{ ->>> parse("Thu, 25 Sep 2003 10:49:41 -0300") -datetime.datetime(2003, 9, 25, 10, 49, 41, - tzinfo=tzoffset(None, -10800)) -}}} - -ISO format: -{{{ ->>> parse("2003-09-25T10:49:41.5-03:00") -datetime.datetime(2003, 9, 25, 10, 49, 41, 500000, - tzinfo=tzoffset(None, -10800)) -}}} - -Some variations: -{{{ ->>> parse("2003-09-25T10:49:41") -datetime.datetime(2003, 9, 25, 10, 49, 41) - ->>> parse("2003-09-25T10:49") -datetime.datetime(2003, 9, 25, 10, 49) - ->>> parse("2003-09-25T10") -datetime.datetime(2003, 9, 25, 10, 0) - ->>> parse("2003-09-25") -datetime.datetime(2003, 9, 25, 0, 0) -}}} - -ISO format, without separators: -{{{ ->>> parse("20030925T104941.5-0300") -datetime.datetime(2003, 9, 25, 10, 49, 41, 500000, - tzinfo=tzinfo=tzoffset(None, -10800)) - ->>> parse("20030925T104941-0300") -datetime.datetime(2003, 9, 25, 10, 49, 41, - tzinfo=tzoffset(None, -10800)) - ->>> parse("20030925T104941") -datetime.datetime(2003, 9, 25, 10, 49, 41) - ->>> parse("20030925T1049") -datetime.datetime(2003, 9, 25, 10, 49) - ->>> parse("20030925T10") -datetime.datetime(2003, 9, 25, 10, 0) - ->>> parse("20030925") -datetime.datetime(2003, 9, 25, 0, 0) -}}} - -Everything together. -{{{ ->>> parse("199709020900") -datetime.datetime(1997, 9, 2, 9, 0) ->>> parse("19970902090059") -datetime.datetime(1997, 9, 2, 9, 0, 59) -}}} - -Different date orderings: -{{{ ->>> parse("2003-09-25") -datetime.datetime(2003, 9, 25, 0, 0) - ->>> parse("2003-Sep-25") -datetime.datetime(2003, 9, 25, 0, 0) - ->>> parse("25-Sep-2003") -datetime.datetime(2003, 9, 25, 0, 0) - ->>> parse("Sep-25-2003") -datetime.datetime(2003, 9, 25, 0, 0) - ->>> parse("09-25-2003") -datetime.datetime(2003, 9, 25, 0, 0) - ->>> parse("25-09-2003") -datetime.datetime(2003, 9, 25, 0, 0) -}}} - -Check some ambiguous dates: -{{{ ->>> parse("10-09-2003") -datetime.datetime(2003, 10, 9, 0, 0) - ->>> parse("10-09-2003", dayfirst=True) -datetime.datetime(2003, 9, 10, 0, 0) - ->>> parse("10-09-03") -datetime.datetime(2003, 10, 9, 0, 0) - ->>> parse("10-09-03", yearfirst=True) -datetime.datetime(2010, 9, 3, 0, 0) -}}} - -Other date separators are allowed: -{{{ ->>> parse("2003.Sep.25") -datetime.datetime(2003, 9, 25, 0, 0) - ->>> parse("2003/09/25") -datetime.datetime(2003, 9, 25, 0, 0) -}}} - -Even with spaces: -{{{ ->>> parse("2003 Sep 25") -datetime.datetime(2003, 9, 25, 0, 0) - ->>> parse("2003 09 25") -datetime.datetime(2003, 9, 25, 0, 0) -}}} - -Hours with letters work: -{{{ ->>> parse("10h36m28.5s", default=DEFAULT) -datetime.datetime(2003, 9, 25, 10, 36, 28, 500000) - ->>> parse("01s02h03m", default=DEFAULT) -datetime.datetime(2003, 9, 25, 2, 3, 1) - ->>> parse("01h02m03", default=DEFAULT) -datetime.datetime(2003, 9, 3, 1, 2) - ->>> parse("01h02", default=DEFAULT) -datetime.datetime(2003, 9, 2, 1, 0) - ->>> parse("01h02s", default=DEFAULT) -datetime.datetime(2003, 9, 25, 1, 0, 2) -}}} - -With AM/PM: -{{{ ->>> parse("10h am", default=DEFAULT) -datetime.datetime(2003, 9, 25, 10, 0) - ->>> parse("10pm", default=DEFAULT) -datetime.datetime(2003, 9, 25, 22, 0) - ->>> parse("12:00am", default=DEFAULT) -datetime.datetime(2003, 9, 25, 0, 0) - ->>> parse("12pm", default=DEFAULT) -datetime.datetime(2003, 9, 25, 12, 0) -}}} - -Some special treating for ''pertain'' relations: -{{{ ->>> parse("Sep 03", default=DEFAULT) -datetime.datetime(2003, 9, 3, 0, 0) - ->>> parse("Sep of 03", default=DEFAULT) -datetime.datetime(2003, 9, 25, 0, 0) -}}} - -Fuzzy parsing: -{{{ ->>> s = "Today is 25 of September of 2003, exactly " \ -... "at 10:49:41 with timezone -03:00." ->>> parse(s, fuzzy=True) -datetime.datetime(2003, 9, 25, 10, 49, 41, - tzinfo=tzoffset(None, -10800)) -}}} - -Other random formats: -{{{ ->>> parse("Wed, July 10, '96") -datetime.datetime(1996, 7, 10, 0, 0) - ->>> parse("1996.07.10 AD at 15:08:56 PDT", ignoretz=True) -datetime.datetime(1996, 7, 10, 15, 8, 56) - ->>> parse("Tuesday, April 12, 1952 AD 3:30:42pm PST", ignoretz=True) -datetime.datetime(1952, 4, 12, 15, 30, 42) - ->>> parse("November 5, 1994, 8:15:30 am EST", ignoretz=True) -datetime.datetime(1994, 11, 5, 8, 15, 30) - ->>> parse("3rd of May 2001") -datetime.datetime(2001, 5, 3, 0, 0) - ->>> parse("5:50 A.M. on June 13, 1990") -datetime.datetime(1990, 6, 13, 5, 50) -}}} - -=== easter === -This module offers a generic easter computing method for -any given year, using Western, Orthodox or Julian algorithms. - -==== easter() function ==== -This method was ported from the work done by -[http://users.chariot.net.au/~gmarts/eastalg.htm GM Arts], -on top of the algorithm by -[http://www.tondering.dk/claus/calendar.html Claus Tondering], -which was based in part on the algorithm of Ouding (1940), -as quoted in "Explanatory Supplement to the Astronomical -Almanac", P. Kenneth Seidelmann, editor. - -This algorithm implements three different easter -calculation methods: - - 1. Original calculation in Julian calendar, valid in - dates after 326 AD - 1. Original method, with date converted to Gregorian - calendar, valid in years 1583 to 4099 - 1. Revised method, in Gregorian calendar, valid in - years 1583 to 4099 as well - -These methods are represented by the constants: -{{{ -EASTER_JULIAN = 1 -EASTER_ORTHODOX = 2 -EASTER_WESTERN = 3 -}}} - -The default method is method 3. - -=== tz === -This module offers timezone implementations subclassing -the abstract {{{datetime.tzinfo}}} type. There are -classes to handle [http://www.twinsun.com/tz/tz-link.htm tzfile] -format files (usually are in /etc/localtime, -/usr/share/zoneinfo, etc), TZ environment string (in all -known formats), given ranges (with help from relative -deltas), local machine timezone, fixed offset timezone, -and UTC timezone. - -==== tzutc type ==== -This type implements a basic UTC timezone. The constructor of this -type accepts no parameters. - -==== tzutc examples ==== -{{{ ->>> from datetime import * ->>> from dateutil.tz import * - ->>> datetime.now() -datetime.datetime(2003, 9, 27, 9, 40, 1, 521290) - ->>> datetime.now(tzutc()) -datetime.datetime(2003, 9, 27, 12, 40, 12, 156379, tzinfo=tzutc()) - ->>> datetime.now(tzutc()).tzname() -'UTC' -}}} - -==== tzoffset type ==== -This type implements a fixed offset timezone, with no -support to daylight saving times. Here is the prototype of the -type constructor: -{{{ -tzoffset(name, offset) -}}} - -The {{{name}}} parameter may be optionally set to {{{None}}}, and -{{{offset}}} must be given in seconds. - -==== tzoffset examples ==== -{{{ ->>> from datetime import * ->>> from dateutil.tz import * - ->>> datetime.now(tzoffset("BRST", -10800)) -datetime.datetime(2003, 9, 27, 9, 52, 43, 624904, - tzinfo=tzinfo=tzoffset('BRST', -10800)) - ->>> datetime.now(tzoffset("BRST", -10800)).tzname() -'BRST' - ->>> datetime.now(tzoffset("BRST", -10800)).astimezone(tzutc()) -datetime.datetime(2003, 9, 27, 12, 53, 11, 446419, - tzinfo=tzutc()) -}}} - -==== tzlocal type ==== -This type implements timezone settings as known by the -operating system. The constructor of this type accepts no -parameters. - -==== tzlocal examples ==== -{{{ ->>> from datetime import * ->>> from dateutil.tz import * - ->>> datetime.now(tzlocal()) -datetime.datetime(2003, 9, 27, 10, 1, 43, 673605, - tzinfo=tzlocal()) - ->>> datetime.now(tzlocal()).tzname() -'BRST' - ->>> datetime.now(tzlocal()).astimezone(tzoffset(None, 0)) -datetime.datetime(2003, 9, 27, 13, 3, 0, 11493, - tzinfo=tzoffset(None, 0)) -}}} - -==== tzstr type ==== -This type implements timezone settings extracted from a -string in known TZ environment variable formats. Here is the prototype -of the constructor: -{{{ -tzstr(str) -}}} - -==== tzstr examples ==== -Here are examples of the recognized formats: - - * {{{EST5EDT}}} - * {{{EST5EDT,4,0,6,7200,10,0,26,7200,3600}}} - * {{{EST5EDT,4,1,0,7200,10,-1,0,7200,3600}}} - * {{{EST5EDT4,M4.1.0/02:00:00,M10-5-0/02:00}}} - * {{{EST5EDT4,95/02:00:00,298/02:00}}} - * {{{EST5EDT4,J96/02:00:00,J299/02:00}}} - -Notice that if daylight information is not present, but a -daylight abbreviation was provided, {{{tzstr}}} will follow the -convention of using the first sunday of April to start daylight -saving, and the last sunday of October to end it. If start or -end time is not present, 2AM will be used, and if the daylight -offset is not present, the standard offset plus one hour will -be used. This convention is the same as used in the GNU libc. - -This also means that some of the above examples are exactly -equivalent, and all of these examples are equivalent -in the year of 2003. - -Here is the example mentioned in the -[http://www.python.org/doc/current/lib/module-time.html time module documentation]. -{{{ ->>> os.environ['TZ'] = 'EST+05EDT,M4.1.0,M10.5.0' ->>> time.tzset() ->>> time.strftime('%X %x %Z') -'02:07:36 05/08/03 EDT' ->>> os.environ['TZ'] = 'AEST-10AEDT-11,M10.5.0,M3.5.0' ->>> time.tzset() ->>> time.strftime('%X %x %Z') -'16:08:12 05/08/03 AEST' -}}} - -And here is an example showing the same information using {{{tzstr}}}, -without touching system settings. -{{{ ->>> tz1 = tzstr('EST+05EDT,M4.1.0,M10.5.0') ->>> tz2 = tzstr('AEST-10AEDT-11,M10.5.0,M3.5.0') ->>> dt = datetime(2003, 5, 8, 2, 7, 36, tzinfo=tz1) ->>> dt.strftime('%X %x %Z') -'02:07:36 05/08/03 EDT' ->>> dt.astimezone(tz2).strftime('%X %x %Z') -'16:07:36 05/08/03 AEST' -}}} - -Are these really equivalent? -{{{ ->>> tzstr('EST5EDT') == tzstr('EST5EDT,4,1,0,7200,10,-1,0,7200,3600') -True -}}} - -Check the daylight limit. -{{{ ->>> datetime(2003, 4, 6, 1, 59, tzinfo=tz).tzname() -'EST' ->>> datetime(2003, 4, 6, 2, 00, tzinfo=tz).tzname() -'EDT' ->>> datetime(2003, 10, 26, 0, 59, tzinfo=tz).tzname() -'EDT' ->>> datetime(2003, 10, 26, 1, 00, tzinfo=tz).tzname() -'EST' -}}} - -==== tzrange type ==== -This type offers the same functionality as the {{{tzstr}}} type, but -instead of timezone strings, information is passed using -{{{relativedelta}}}s which are applied to a datetime set to the first -day of the year. Here is the prototype of this type's constructor: -{{{ -tzrange(stdabbr, stdoffset=None, dstabbr=None, dstoffset=None, - start=None, end=None): -}}} - -Offsets must be given in seconds. Information not provided will be -set to the defaults, as explained in the {{{tzstr}}} section above. - -==== tzrange examples ==== -{{{ ->>> tzstr('EST5EDT') == tzrange("EST", -18000, "EDT") -True - ->>> from dateutil.relativedelta import * ->>> range1 = tzrange("EST", -18000, "EDT") ->>> range2 = tzrange("EST", -18000, "EDT", -14400, -... relativedelta(hours=+2, month=4, day=1, - weekday=SU(+1)), -... relativedelta(hours=+1, month=10, day=31, - weekday=SU(-1))) ->>> tzstr('EST5EDT') == range1 == range2 -True -}}} - -Notice a minor detail in the last example: while the DST should end -at 2AM, the delta will catch 1AM. That's because the daylight saving -time should end at 2AM standard time (the difference between STD and -DST is 1h in the given example) instead of the DST time. That's how -the {{{tzinfo}}} subtypes should deal with the extra hour that happens -when going back to the standard time. Check -[http://www.python.org/doc/current/lib/datetime-tzinfo.html tzinfo documentation] -for more information. - -==== tzfile type ==== -This type allows one to use tzfile(5) format timezone files to extract -current and historical zone information. Here is the type constructor -prototype: -{{{ -tzfile(fileobj) -}}} - -Where {{{fileobj}}} is either a filename or a file-like object with -a {{{read()}}} method. - -==== tzfile examples ==== -{{{ ->>> tz = tzfile("/etc/localtime") ->>> datetime.now(tz) -datetime.datetime(2003, 9, 27, 12, 3, 48, 392138, - tzinfo=tzfile('/etc/localtime')) - ->>> datetime.now(tz).astimezone(tzutc()) -datetime.datetime(2003, 9, 27, 15, 3, 53, 70863, - tzinfo=tzutc()) - ->>> datetime.now(tz).tzname() -'BRST' ->>> datetime(2003, 1, 1, tzinfo=tz).tzname() -'BRDT' -}}} - -Check the daylight limit. -{{{ ->>> tz = tzfile('/usr/share/zoneinfo/EST5EDT') ->>> datetime(2003, 4, 6, 1, 59, tzinfo=tz).tzname() -'EST' ->>> datetime(2003, 4, 6, 2, 00, tzinfo=tz).tzname() -'EDT' ->>> datetime(2003, 10, 26, 0, 59, tzinfo=tz).tzname() -'EDT' ->>> datetime(2003, 10, 26, 1, 00, tzinfo=tz).tzname() -'EST' -}}} - -==== tzical type ==== -This type is able to parse -[ftp://ftp.rfc-editor.org/in-notes/rfc2445.txt iCalendar] -style {{{VTIMEZONE}}} sessions into a Python timezone object. -The constuctor prototype is: -{{{ -tzical(fileobj) -}}} - -Where {{{fileobj}}} is either a filename or a file-like object with -a {{{read()}}} method. - -==== tzical methods ==== - - tzical.get(tzid=None):: - Since a single iCalendar file may contain more than one timezone, - you must ask for the timezone you want with this method. If there's - more than one timezone in the parsed file, you'll need to pass the - {{{tzid}}} parameter. Otherwise, leaving it empty will yield the only - available timezone. - -==== tzical examples ==== -Here is a sample file extracted from the RFC. This file defines -the {{{EST5EDT}}} timezone, and will be used in the following example. -{{{ -BEGIN:VTIMEZONE -TZID:US-Eastern -LAST-MODIFIED:19870101T000000Z -TZURL:http://zones.stds_r_us.net/tz/US-Eastern -BEGIN:STANDARD -DTSTART:19671029T020000 -RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 -TZOFFSETFROM:-0400 -TZOFFSETTO:-0500 -TZNAME:EST -END:STANDARD -BEGIN:DAYLIGHT -DTSTART:19870405T020000 -RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4 -TZOFFSETFROM:-0500 -TZOFFSETTO:-0400 -TZNAME:EDT -END:DAYLIGHT -END:VTIMEZONE -}}} - -And here is an example exploring a {{{tzical}}} type: -{{{ ->>> from dateutil.tz import *; from datetime import * - ->>> tz = tzical('EST5EDT.ics') ->>> tz.keys() -['US-Eastern'] - ->>> est = tz.get('US-Eastern') ->>> est -<tzicalvtz 'US-Eastern'> - ->>> datetime.now(est) -datetime.datetime(2003, 10, 6, 19, 44, 18, 667987, - tzinfo=<tzicalvtz 'US-Eastern'>) - ->>> est == tz.get() -True -}}} - -Let's check the daylight ranges, as usual: -{{{ ->>> datetime(2003, 4, 6, 1, 59, tzinfo=est).tzname() -'EST' ->>> datetime(2003, 4, 6, 2, 00, tzinfo=est).tzname() -'EDT' - ->>> datetime(2003, 10, 26, 0, 59, tzinfo=est).tzname() -'EDT' ->>> datetime(2003, 10, 26, 1, 00, tzinfo=est).tzname() -'EST' -}}} - -==== tzwin type ==== -This type offers access to internal registry-based Windows timezones. -The constuctor prototype is: -{{{ -tzwin(name) -}}} - -Where {{{name}}} is the timezone name. There's a static {{{tzwin.list()}}} -method to check the available names, - -==== tzwin methods ==== - - tzwin.display():: - This method returns the timezone extended name. - - tzwin.list():: - This static method lists all available timezone names. - -==== tzwin examples ==== -{{{ ->>> tz = tzwin("E. South America Standard Time") -}}} - -==== tzwinlocal type ==== -This type offers access to internal registry-based Windows timezones. -The constructor accepts no parameters, so the prototype is: -{{{ -tzwinlocal() -}}} - -==== tzwinlocal methods ==== - - tzwinlocal.display():: - This method returns the timezone extended name, and returns - {{{None}}} if one is not available. - -==== tzwinlocal examples ==== -{{{ ->>> tz = tzwinlocal() -}}} - -==== gettz() function ==== -This function is a helper that will try its best to get the right -timezone for your environment, or for the given string. The prototype -is as follows: -{{{ -gettz(name=None) -}}} - -If given, the parameter may be a filename, a path relative to the base -of the timezone information path (the base could be -{{{/usr/share/zoneinfo}}}, for example), a string timezone -specification, or a timezone abbreviation. If {{{name}}} is not given, -and the {{{TZ}}} environment variable is set, it's used instead. If the -parameter is not given, and {{{TZ}}} is not set, the default tzfile -paths will be tried. Then, if no timezone information is found, -an internal compiled database of timezones is used. When running -on Windows, the internal registry-based Windows timezones are also -considered. - -Example: -{{{ ->>> from dateutil.tz import * ->>> gettz() -tzfile('/etc/localtime') - ->>> gettz("America/Sao Paulo") -tzfile('/usr/share/zoneinfo/America/Sao_Paulo') - ->>> gettz("EST5EDT") -tzfile('/usr/share/zoneinfo/EST5EDT') - ->>> gettz("EST5") -tzstr('EST5') - ->>> gettz('BRST') -tzlocal() - ->>> os.environ["TZ"] = "America/Sao Paulo" ->>> gettz() -tzfile('/usr/share/zoneinfo/America/Sao_Paulo') - ->>> os.environ["TZ"] = "BRST" ->>> gettz() -tzlocal() - ->>> gettz("Unavailable") ->>> -}}} - -=== zoneinfo === -This module provides direct access to the internal compiled -database of timezones. The timezone data and the compiling tools -are obtained from the following project: - - http://www.twinsun.com/tz/tz-link.htm - -==== gettz() function ==== -This function will try to retrieve the given timezone information -from the internal compiled database, and will cache its results. - -Example: -{{{ ->>> from dateutil import zoneinfo ->>> zoneinfo.gettz("Brazil/East") -tzfile('Brazil/East') -}}} - - -== Building and releasing == -When you get the source, it does not contain the internal zoneinfo -database. To get (and update) the database, run the updatezinfo.py script. Make sure -that the zic command is in your path, and that you have network connectivity -to get the latest timezone information from IANA. If you have downloaded -the timezone data earlier, you can give the tarball as a parameter to -updatezinfo.py. - -After testing any changes, changing the version information in dateutil/__init__.py -and updating NEWS, a new release can be uploaded to PyPI with -{{{ -python setup.py sdist upload -}}} - - -== Testing == -dateutil has a comprehensive test suite, which can be run simply by running the -test.py script in the project root. Note that if you don't have the internal -zoneinfo database, some tests will fail. Apart from that, all tests should pass. - -To easily test dateutil against all supported Python versions, you can use -[[[http://tox.readthedocs.org/en/latest/ tox]]]. - -## vim:ft=moin diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..3d48ebf --- /dev/null +++ b/README.rst @@ -0,0 +1,106 @@ +dateutil - powerfull extensions to datetime +=========================================== +The `dateutil` module provides powerful extensions to +the standard `datetime` module, available in Python. + + +Download +======== +dateutil is available on PyPI +https://pypi.python.org/pypi/python-dateutil/ + +The documentation is hosted at: +https://dateutil.readthedocs.org/ + +Code +==== +https://github.com/dateutil/dateutil/ + +Features +======== + +* Computing of relative deltas (next month, next year, + next monday, last week of month, etc); +* Computing of relative deltas between two given + date and/or datetime objects; +* Computing of dates based on very flexible recurrence rules, + using a superset of the + [ftp://ftp.rfc-editor.org/in-notes/rfc2445.txt iCalendar] + specification. Parsing of RFC strings is supported as well. +* Generic parsing of dates in almost any string format; +* Timezone (tzinfo) implementations for tzfile(5) format + files (/etc/localtime, /usr/share/zoneinfo, etc), TZ + environment string (in all known formats), iCalendar + format files, given ranges (with help from relative deltas), + local machine timezone, fixed offset timezone, UTC timezone, + and Windows registry-based time zones. +* Internal up-to-date world timezone information based on + Olson's database. +* Computing of Easter Sunday dates for any given year, + using Western, Orthodox or Julian algorithms; +* More than 400 test cases. + +Quick example +============= +Here's a snapshot, just to give an idea about the power of the +package. For more examples, look at the documentation. + +Suppose you want to know how much time is left, in +years/months/days/etc, before the next easter happening on a +year with a Friday 13th in August, and you want to get today's +date out of the "date" unix system command. Here is the code: + +.. doctest:: readmeexample + + >>> from dateutil.relativedelta import * + >>> from dateutil.easter import * + >>> from dateutil.rrule import * + >>> from dateutil.parser import * + >>> from datetime import * + >>> now = parse("Sat Oct 11 17:13:46 UTC 2003") + >>> today = now.date() + >>> year = rrule(YEARLY,dtstart=now,bymonth=8,bymonthday=13,byweekday=FR)[0].year + >>> rdelta = relativedelta(easter(year), today) + >>> print("Today is: %s" % today) + Today is: 2003-10-11 + >>> print("Year with next Aug 13th on a Friday is: %s" % year) + Year with next Aug 13th on a Friday is: 2004 + >>> print("How far is the Easter of that year: %s" % rdelta) + How far is the Easter of that year: relativedelta(months=+6) + >>> print("And the Easter of that year is: %s" % (today+rdelta)) + And the Easter of that year is: 2004-04-11 + +Being exactly 6 months ahead was **really** a coincidence :) + + +Author +====== +The dateutil module was written by Gustavo Niemeyer <gustavo@niemeyer.net> +in 2003 + +It is maintained by: + +* Gustavo Niemeyer <gustavo@niemeyer.net> 2003-2013 +* Tomi Pieviläinen <tomi.pievilainen@iki.fi> 2013-2014 +* Yaron de Leeuw <me@jarond.net> 2014- + +Building and releasing +====================== +When you get the source, it does not contain the internal zoneinfo +database. To get (and update) the database, run the updatezinfo.py script. Make sure +that the zic command is in your path, and that you have network connectivity +to get the latest timezone information from IANA. If you have downloaded +the timezone data earlier, you can give the tarball as a parameter to +updatezinfo.py. + + +Testing +======= +dateutil has a comprehensive test suite, which can be run simply by running +`python setup.py test [-q]` in the project root. Note that if you don't have the internal +zoneinfo database, some tests will fail. Apart from that, all tests should pass. + +To easily test dateutil against all supported Python versions, you can use +`tox <https://tox.readthedocs.org/en/latest/>`_. + +All github pull requests are automatically tested using travis. diff --git a/dateutil/rrule.py b/dateutil/rrule.py index 91bdedf..6e886ec 100644 --- a/dateutil/rrule.py +++ b/dateutil/rrule.py @@ -925,11 +925,11 @@ class rruleset(rrulebase): self._exdate = [] def rrule(self, rrule): - """ Include the given :py:`rrule` instance in the recurrence set generation. """ + """ Include the given :py:class:`rrule` instance in the recurrence set generation. """ self._rrule.append(rrule) def rdate(self, rdate): - """ Include the given :py:`datetime` instance in the recurrence set generation. """ + """ Include the given :py:class:`datetime` instance in the recurrence set generation. """ self._rdate.append(rdate) def exrule(self, exrule): diff --git a/docs/examples.rst b/docs/examples.rst new file mode 100644 index 0000000..815e457 --- /dev/null +++ b/docs/examples.rst @@ -0,0 +1,1393 @@ +dateutil examples +================= + +.. contents:: + +relativedelta examples +---------------------- + +.. testsetup:: relativedelta + + from datetime import *; from dateutil.relativedelta import * + import calendar + NOW = datetime(2003, 9, 17, 20, 54, 47, 282310) + TODAY = date(2003, 9, 17) + +Let's begin our trip:: + + >>> from datetime import *; from dateutil.relativedelta import * + >>> import calendar + +Store some values:: + + >>> NOW = datetime.now() + >>> TODAY = date.today() + >>> NOW + datetime.datetime(2003, 9, 17, 20, 54, 47, 282310) + >>> TODAY + datetime.date(2003, 9, 17) + +Next month + +.. doctest:: relativedelta + + >>> NOW+relativedelta(months=+1) + datetime.datetime(2003, 10, 17, 20, 54, 47, 282310) + +Next month, plus one week. + +.. doctest:: relativedelta + + >>> NOW+relativedelta(months=+1, weeks=+1) + datetime.datetime(2003, 10, 24, 20, 54, 47, 282310) + +Next month, plus one week, at 10am. + +.. doctest:: relativedelta + + >>> TODAY+relativedelta(months=+1, weeks=+1, hour=10) + datetime.datetime(2003, 10, 24, 10, 0) + +Let's try the other way around. Notice that the +hour setting we get in the relativedelta is relative, +since it's a difference, and the weeks parameter +has gone. + +.. doctest:: relativedelta + + >>> relativedelta(datetime(2003, 10, 24, 10, 0), TODAY) + relativedelta(months=+1, days=+7, hours=+10) + +One month before one year. + +.. doctest:: relativedelta + + >>> NOW+relativedelta(years=+1, months=-1) + datetime.datetime(2004, 8, 17, 20, 54, 47, 282310) + +How does it handle months with different numbers of days? +Notice that adding one month will never cross the month +boundary. + +.. doctest:: relativedelta + + >>> date(2003,1,27)+relativedelta(months=+1) + datetime.date(2003, 2, 27) + >>> date(2003,1,31)+relativedelta(months=+1) + datetime.date(2003, 2, 28) + >>> date(2003,1,31)+relativedelta(months=+2) + datetime.date(2003, 3, 31) + +The logic for years is the same, even on leap years. + +.. doctest:: relativedelta + + >>> date(2000,2,28)+relativedelta(years=+1) + datetime.date(2001, 2, 28) + >>> date(2000,2,29)+relativedelta(years=+1) + datetime.date(2001, 2, 28) + + >>> date(1999,2,28)+relativedelta(years=+1) + datetime.date(2000, 2, 28) + >>> date(1999,3,1)+relativedelta(years=+1) + datetime.date(2000, 3, 1) + + >>> date(2001,2,28)+relativedelta(years=-1) + datetime.date(2000, 2, 28) + >>> date(2001,3,1)+relativedelta(years=-1) + datetime.date(2000, 3, 1) + +Next friday + +.. doctest:: relativedelta + + >>> TODAY+relativedelta(weekday=FR) + datetime.date(2003, 9, 19) + + >>> TODAY+relativedelta(weekday=calendar.FRIDAY) + datetime.date(2003, 9, 19) + +Last friday in this month. + +.. doctest:: relativedelta + + >>> TODAY+relativedelta(day=31, weekday=FR(-1)) + datetime.date(2003, 9, 26) + +Next wednesday (it's today!). + +.. doctest:: relativedelta + + >>> TODAY+relativedelta(weekday=WE(+1)) + datetime.date(2003, 9, 17) + +Next wednesday, but not today. + +.. doctest:: relativedelta + + >>> TODAY+relativedelta(days=+1, weekday=WE(+1)) + datetime.date(2003, 9, 24) + +Following +[http://www.cl.cam.ac.uk/~mgk25/iso-time.html ISO year week number notation] +find the first day of the 15th week of 1997. + +.. doctest:: relativedelta + + >>> datetime(1997,1,1)+relativedelta(day=4, weekday=MO(-1), weeks=+14) + datetime.datetime(1997, 4, 7, 0, 0) + +How long ago has the millennium changed? + +.. doctest:: relativedelta + + >>> relativedelta(NOW, date(2001,1,1)) + relativedelta(years=+2, months=+8, days=+16, + hours=+20, minutes=+54, seconds=+47, microseconds=+282310) + +How old is John? + +.. doctest:: relativedelta + + >>> johnbirthday = datetime(1978, 4, 5, 12, 0) + >>> relativedelta(NOW, johnbirthday) + relativedelta(years=+25, months=+5, days=+12, + hours=+8, minutes=+54, seconds=+47, microseconds=+282310) + +It works with dates too. + +.. doctest:: relativedelta + + >>> relativedelta(TODAY, johnbirthday) + relativedelta(years=+25, months=+5, days=+11, hours=+12) + +Obtain today's date using the yearday: + +.. doctest:: relativedelta + + >>> date(2003, 1, 1)+relativedelta(yearday=260) + datetime.date(2003, 9, 17) + +We can use today's date, since yearday should be absolute +in the given year: + +.. doctest:: relativedelta + + >>> TODAY+relativedelta(yearday=260) + datetime.date(2003, 9, 17) + +Last year it should be in the same day: + +.. doctest:: relativedelta + + >>> date(2002, 1, 1)+relativedelta(yearday=260) + datetime.date(2002, 9, 17) + +But not in a leap year: + +.. doctest:: relativedelta + + >>> date(2000, 1, 1)+relativedelta(yearday=260) + datetime.date(2000, 9, 16) + +We can use the non-leap year day to ignore this: + +.. doctest:: relativedelta + + >>> date(2000, 1, 1)+relativedelta(nlyearday=260) + datetime.date(2000, 9, 17) + +rrule examples +-------------- +These examples were converted from the RFC. + +Prepare the environment. + +.. testsetup:: rrule + + from dateutil.rrule import * + from dateutil.parser import * + from datetime import * + import pprint + import sys + sys.displayhook = pprint.pprint + +.. doctest:: rrule + + >>> from dateutil.rrule import * + >>> from dateutil.parser import * + >>> from datetime import * + + >>> import pprint + >>> import sys + >>> sys.displayhook = pprint.pprint + +Daily, for 10 occurrences. + +.. doctest:: rrule + + >>> list(rrule(DAILY, count=10, + dtstart=parse("19970902T090000"))) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 3, 9, 0), + datetime.datetime(1997, 9, 4, 9, 0), + datetime.datetime(1997, 9, 5, 9, 0), + datetime.datetime(1997, 9, 6, 9, 0), + datetime.datetime(1997, 9, 7, 9, 0), + datetime.datetime(1997, 9, 8, 9, 0), + datetime.datetime(1997, 9, 9, 9, 0), + datetime.datetime(1997, 9, 10, 9, 0), + datetime.datetime(1997, 9, 11, 9, 0)] + +Daily until December 24, 1997 + +.. doctest:: rrule + + >>> list(rrule(DAILY, + dtstart=parse("19970902T090000"), + until=parse("19971224T000000"))) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 3, 9, 0), + datetime.datetime(1997, 9, 4, 9, 0), + (...) + datetime.datetime(1997, 12, 21, 9, 0), + datetime.datetime(1997, 12, 22, 9, 0), + datetime.datetime(1997, 12, 23, 9, 0)] + +Every other day, 5 occurrences. + +.. doctest:: rrule + + >>> list(rrule(DAILY, interval=2, count=5, + dtstart=parse("19970902T090000"))) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 4, 9, 0), + datetime.datetime(1997, 9, 6, 9, 0), + datetime.datetime(1997, 9, 8, 9, 0), + datetime.datetime(1997, 9, 10, 9, 0)] + +Every 10 days, 5 occurrences. + +.. doctest:: rrule + + >>> list(rrule(DAILY, interval=10, count=5, + dtstart=parse("19970902T090000"))) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 12, 9, 0), + datetime.datetime(1997, 9, 22, 9, 0), + datetime.datetime(1997, 10, 2, 9, 0), + datetime.datetime(1997, 10, 12, 9, 0)] + +Everyday in January, for 3 years. + +.. doctest:: rrule + + >>> list(rrule(YEARLY, bymonth=1, byweekday=range(7), + dtstart=parse("19980101T090000"), + until=parse("20000131T090000"))) + [datetime.datetime(1998, 1, 1, 9, 0), + datetime.datetime(1998, 1, 2, 9, 0), + (...) + datetime.datetime(1998, 1, 30, 9, 0), + datetime.datetime(1998, 1, 31, 9, 0), + datetime.datetime(1999, 1, 1, 9, 0), + datetime.datetime(1999, 1, 2, 9, 0), + (...) + datetime.datetime(1999, 1, 30, 9, 0), + datetime.datetime(1999, 1, 31, 9, 0), + datetime.datetime(2000, 1, 1, 9, 0), + datetime.datetime(2000, 1, 2, 9, 0), + (...) + datetime.datetime(2000, 1, 29, 9, 0), + datetime.datetime(2000, 1, 31, 9, 0)] + +Same thing, in another way. + +.. doctest:: rrule + + >>> list(rrule(DAILY, bymonth=1, + dtstart=parse("19980101T090000"), + until=parse("20000131T090000"))) + (...) + +Weekly for 10 occurrences. + +.. doctest:: rrule + + >>> list(rrule(WEEKLY, count=10, + dtstart=parse("19970902T090000"))) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 9, 9, 0), + datetime.datetime(1997, 9, 16, 9, 0), + datetime.datetime(1997, 9, 23, 9, 0), + datetime.datetime(1997, 9, 30, 9, 0), + datetime.datetime(1997, 10, 7, 9, 0), + datetime.datetime(1997, 10, 14, 9, 0), + datetime.datetime(1997, 10, 21, 9, 0), + datetime.datetime(1997, 10, 28, 9, 0), + datetime.datetime(1997, 11, 4, 9, 0)] + +Every other week, 6 occurrences. + +.. doctest:: rrule + + >>> list(rrule(WEEKLY, interval=2, count=6, + dtstart=parse("19970902T090000"))) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 16, 9, 0), + datetime.datetime(1997, 9, 30, 9, 0), + datetime.datetime(1997, 10, 14, 9, 0), + datetime.datetime(1997, 10, 28, 9, 0), + datetime.datetime(1997, 11, 11, 9, 0)] + +Weekly on Tuesday and Thursday for 5 weeks. + +.. doctest:: rrule + + >>> list(rrule(WEEKLY, count=10, wkst=SU, byweekday=(TU,TH), + dtstart=parse("19970902T090000"))) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 4, 9, 0), + datetime.datetime(1997, 9, 9, 9, 0), + datetime.datetime(1997, 9, 11, 9, 0), + datetime.datetime(1997, 9, 16, 9, 0), + datetime.datetime(1997, 9, 18, 9, 0), + datetime.datetime(1997, 9, 23, 9, 0), + datetime.datetime(1997, 9, 25, 9, 0), + datetime.datetime(1997, 9, 30, 9, 0), + datetime.datetime(1997, 10, 2, 9, 0)] + +Every other week on Tuesday and Thursday, for 8 occurrences. + +.. doctest:: rrule + + >>> list(rrule(WEEKLY, interval=2, count=8, + wkst=SU, byweekday=(TU,TH), + dtstart=parse("19970902T090000"))) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 4, 9, 0), + datetime.datetime(1997, 9, 16, 9, 0), + datetime.datetime(1997, 9, 18, 9, 0), + datetime.datetime(1997, 9, 30, 9, 0), + datetime.datetime(1997, 10, 2, 9, 0), + datetime.datetime(1997, 10, 14, 9, 0), + datetime.datetime(1997, 10, 16, 9, 0)] + +Monthly on the 1st Friday for ten occurrences. + +.. doctest:: rrule + + >>> list(rrule(MONTHLY, count=10, byweekday=FR(1), + dtstart=parse("19970905T090000"))) + [datetime.datetime(1997, 9, 5, 9, 0), + datetime.datetime(1997, 10, 3, 9, 0), + datetime.datetime(1997, 11, 7, 9, 0), + datetime.datetime(1997, 12, 5, 9, 0), + datetime.datetime(1998, 1, 2, 9, 0), + datetime.datetime(1998, 2, 6, 9, 0), + datetime.datetime(1998, 3, 6, 9, 0), + datetime.datetime(1998, 4, 3, 9, 0), + datetime.datetime(1998, 5, 1, 9, 0), + datetime.datetime(1998, 6, 5, 9, 0)] + +Every other month on the 1st and last Sunday of the month for 10 occurrences. + +.. doctest:: rrule + + >>> list(rrule(MONTHLY, interval=2, count=10, + byweekday=(SU(1), SU(-1)), + dtstart=parse("19970907T090000"))) + [datetime.datetime(1997, 9, 7, 9, 0), + datetime.datetime(1997, 9, 28, 9, 0), + datetime.datetime(1997, 11, 2, 9, 0), + datetime.datetime(1997, 11, 30, 9, 0), + datetime.datetime(1998, 1, 4, 9, 0), + datetime.datetime(1998, 1, 25, 9, 0), + datetime.datetime(1998, 3, 1, 9, 0), + datetime.datetime(1998, 3, 29, 9, 0), + datetime.datetime(1998, 5, 3, 9, 0), + datetime.datetime(1998, 5, 31, 9, 0)] + +Monthly on the second to last Monday of the month for 6 months. + +.. doctest:: rrule + + >>> list(rrule(MONTHLY, count=6, byweekday=MO(-2), + dtstart=parse("19970922T090000"))) + [datetime.datetime(1997, 9, 22, 9, 0), + datetime.datetime(1997, 10, 20, 9, 0), + datetime.datetime(1997, 11, 17, 9, 0), + datetime.datetime(1997, 12, 22, 9, 0), + datetime.datetime(1998, 1, 19, 9, 0), + datetime.datetime(1998, 2, 16, 9, 0)] + + +Monthly on the third to the last day of the month, for 6 months. + +.. doctest:: rrule + + >>> list(rrule(MONTHLY, count=6, bymonthday=-3, + dtstart=parse("19970928T090000"))) + [datetime.datetime(1997, 9, 28, 9, 0), + datetime.datetime(1997, 10, 29, 9, 0), + datetime.datetime(1997, 11, 28, 9, 0), + datetime.datetime(1997, 12, 29, 9, 0), + datetime.datetime(1998, 1, 29, 9, 0), + datetime.datetime(1998, 2, 26, 9, 0)] + + +Monthly on the 2nd and 15th of the month for 5 occurrences. + +.. doctest:: rrule + + >>> list(rrule(MONTHLY, count=5, bymonthday=(2,15), + dtstart=parse("19970902T090000"))) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 15, 9, 0), + datetime.datetime(1997, 10, 2, 9, 0), + datetime.datetime(1997, 10, 15, 9, 0), + datetime.datetime(1997, 11, 2, 9, 0)] + + +Monthly on the first and last day of the month for 3 occurrences. + +.. doctest:: rrule + + >>> list(rrule(MONTHLY, count=5, bymonthday=(-1,1,), + dtstart=parse("1997090 + 2T090000"))) + [datetime.datetime(1997, 9, 30, 9, 0), + datetime.datetime(1997, 10, 1, 9, 0), + datetime.datetime(1997, 10, 31, 9, 0), + datetime.datetime(1997, 11, 1, 9, 0), + datetime.datetime(1997, 11, 30, 9, 0)] + + +Every 18 months on the 10th thru 15th of the month for 10 occurrences. + +.. doctest:: rrule + + >>> list(rrule(MONTHLY, interval=18, count=10, + bymonthday=range(10,16), + dtstart=parse("19970910T090000"))) + [datetime.datetime(1997, 9, 10, 9, 0), + datetime.datetime(1997, 9, 11, 9, 0), + datetime.datetime(1997, 9, 12, 9, 0), + datetime.datetime(1997, 9, 13, 9, 0), + datetime.datetime(1997, 9, 14, 9, 0), + datetime.datetime(1997, 9, 15, 9, 0), + datetime.datetime(1999, 3, 10, 9, 0), + datetime.datetime(1999, 3, 11, 9, 0), + datetime.datetime(1999, 3, 12, 9, 0), + datetime.datetime(1999, 3, 13, 9, 0)] + + +Every Tuesday, every other month, 6 occurences. + +.. doctest:: rrule + + >>> list(rrule(MONTHLY, interval=2, count=6, byweekday=TU, + dtstart=parse("19970902T090000"))) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 9, 9, 0), + datetime.datetime(1997, 9, 16, 9, 0), + datetime.datetime(1997, 9, 23, 9, 0), + datetime.datetime(1997, 9, 30, 9, 0), + datetime.datetime(1997, 11, 4, 9, 0)] + + +Yearly in June and July for 10 occurrences. + +.. doctest:: rrule + + >>> list(rrule(YEARLY, count=4, bymonth=(6,7), + dtstart=parse("19970610T0900 + 00"))) + [datetime.datetime(1997, 6, 10, 9, 0), + datetime.datetime(1997, 7, 10, 9, 0), + datetime.datetime(1998, 6, 10, 9, 0), + datetime.datetime(1998, 7, 10, 9, 0)] + + +Every 3rd year on the 1st, 100th and 200th day for 4 occurrences. + +.. doctest:: rrule + + >>> list(rrule(YEARLY, count=4, interval=3, byyearday=(1,100,200), + dtstart=parse("19970101T090000"))) + [datetime.datetime(1997, 1, 1, 9, 0), + datetime.datetime(1997, 4, 10, 9, 0), + datetime.datetime(1997, 7, 19, 9, 0), + datetime.datetime(2000, 1, 1, 9, 0)] + + +Every 20th Monday of the year, 3 occurrences. + +.. doctest:: rrule + + >>> list(rrule(YEARLY, count=3, byweekday=MO(20), + dtstart=parse("19970519T090000"))) + [datetime.datetime(1997, 5, 19, 9, 0), + datetime.datetime(1998, 5, 18, 9, 0), + datetime.datetime(1999, 5, 17, 9, 0)] + + +Monday of week number 20 (where the default start of the week is Monday), +3 occurrences. + +.. doctest:: rrule + + >>> list(rrule(YEARLY, count=3, byweekno=20, byweekday=MO, + dtstart=parse("19970512T090000"))) + [datetime.datetime(1997, 5, 12, 9, 0), + datetime.datetime(1998, 5, 11, 9, 0), + datetime.datetime(1999, 5, 17, 9, 0)] + + +The week number 1 may be in the last year. + +.. doctest:: rrule + + >>> list(rrule(WEEKLY, count=3, byweekno=1, byweekday=MO, + dtstart=parse("19970902T090000"))) + [datetime.datetime(1997, 12, 29, 9, 0), + datetime.datetime(1999, 1, 4, 9, 0), + datetime.datetime(2000, 1, 3, 9, 0)] + + +And the week numbers greater than 51 may be in the next year. + +.. doctest:: rrule + + >>> list(rrule(WEEKLY, count=3, byweekno=52, byweekday=SU, + dtstart=parse("19970902T090000"))) + [datetime.datetime(1997, 12, 28, 9, 0), + datetime.datetime(1998, 12, 27, 9, 0), + datetime.datetime(2000, 1, 2, 9, 0)] + + +Only some years have week number 53: + +.. doctest:: rrule + + >>> list(rrule(WEEKLY, count=3, byweekno=53, byweekday=MO, + dtstart=parse("19970902T090000"))) + [datetime.datetime(1998, 12, 28, 9, 0), + datetime.datetime(2004, 12, 27, 9, 0), + datetime.datetime(2009, 12, 28, 9, 0)] + + +Every Friday the 13th, 4 occurrences. + +.. doctest:: rrule + + >>> list(rrule(YEARLY, count=4, byweekday=FR, bymonthday=13, + dtstart=parse("19970902T090000"))) + [datetime.datetime(1998, 2, 13, 9, 0), + datetime.datetime(1998, 3, 13, 9, 0), + datetime.datetime(1998, 11, 13, 9, 0), + datetime.datetime(1999, 8, 13, 9, 0)] + + +Every four years, the first Tuesday after a Monday in November, +3 occurrences (U.S. Presidential Election day): + +.. doctest:: rrule + + >>> list(rrule(YEARLY, interval=4, count=3, bymonth=11, + byweekday=TU, bymonthday=(2,3,4,5,6,7,8), + dtstart=parse("19961105T090000"))) + [datetime.datetime(1996, 11, 5, 9, 0), + datetime.datetime(2000, 11, 7, 9, 0), + datetime.datetime(2004, 11, 2, 9, 0)] + + +The 3rd instance into the month of one of Tuesday, Wednesday or +Thursday, for the next 3 months: + +.. doctest:: rrule + + >>> list(rrule(MONTHLY, count=3, byweekday=(TU,WE,TH), + bysetpos=3, dtstart=parse("19970904T090000"))) + [datetime.datetime(1997, 9, 4, 9, 0), + datetime.datetime(1997, 10, 7, 9, 0), + datetime.datetime(1997, 11, 6, 9, 0)] + + +The 2nd to last weekday of the month, 3 occurrences. + +.. doctest:: rrule + + >>> list(rrule(MONTHLY, count=3, byweekday=(MO,TU,WE,TH,FR), + bysetpos=-2, dtstart=parse("19970929T090000"))) + [datetime.datetime(1997, 9, 29, 9, 0), + datetime.datetime(1997, 10, 30, 9, 0), + datetime.datetime(1997, 11, 27, 9, 0)] + + +Every 3 hours from 9:00 AM to 5:00 PM on a specific day. + +.. doctest:: rrule + + >>> list(rrule(HOURLY, interval=3, + dtstart=parse("19970902T090000"), + until=parse("19970902T170000"))) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 2, 12, 0), + datetime.datetime(1997, 9, 2, 15, 0)] + + +Every 15 minutes for 6 occurrences. + +.. doctest:: rrule + + >>> list(rrule(MINUTELY, interval=15, count=6, + dtstart=parse("19970902T090000"))) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 2, 9, 15), + datetime.datetime(1997, 9, 2, 9, 30), + datetime.datetime(1997, 9, 2, 9, 45), + datetime.datetime(1997, 9, 2, 10, 0), + datetime.datetime(1997, 9, 2, 10, 15)] + + +Every hour and a half for 4 occurrences. + +.. doctest:: rrule + + >>> list(rrule(MINUTELY, interval=90, count=4, + dtstart=parse("19970902T090000"))) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 2, 10, 30), + datetime.datetime(1997, 9, 2, 12, 0), + datetime.datetime(1997, 9, 2, 13, 30)] + + +Every 20 minutes from 9:00 AM to 4:40 PM for two days. + +.. doctest:: rrule + + >>> list(rrule(MINUTELY, interval=20, count=48, + byhour=range(9,17), byminute=(0,20,40), + dtstart=parse("19970902T090000"))) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 2, 9, 20), + (...) + datetime.datetime(1997, 9, 2, 16, 20), + datetime.datetime(1997, 9, 2, 16, 40), + datetime.datetime(1997, 9, 3, 9, 0), + datetime.datetime(1997, 9, 3, 9, 20), + (...) + datetime.datetime(1997, 9, 3, 16, 20), + datetime.datetime(1997, 9, 3, 16, 40)] + + +An example where the days generated makes a difference because of `wkst`. + +.. doctest:: rrule + + >>> list(rrule(WEEKLY, interval=2, count=4, + byweekday=(TU,SU), wkst=MO, + dtstart=parse("19970805T090000"))) + [datetime.datetime(1997, 8, 5, 9, 0), + datetime.datetime(1997, 8, 10, 9, 0), + datetime.datetime(1997, 8, 19, 9, 0), + datetime.datetime(1997, 8, 24, 9, 0)] + + >>> list(rrule(WEEKLY, interval=2, count=4, + byweekday=(TU,SU), wkst=SU, + dtstart=parse("19970805T090000"))) + [datetime.datetime(1997, 8, 5, 9, 0), + datetime.datetime(1997, 8, 17, 9, 0), + datetime.datetime(1997, 8, 19, 9, 0), + datetime.datetime(1997, 8, 31, 9, 0)] + + +rruleset examples +----------------- +Daily, for 7 days, jumping Saturday and Sunday occurrences. + +.. doctest:: rruleset + + >>> set = rruleset() + >>> set.rrule(rrule(DAILY, count=7, + dtstart=parse("19970902T090000"))) + >>> set.exrule(rrule(YEARLY, byweekday=(SA,SU), + dtstart=parse("19970902T090000"))) + >>> list(set) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 3, 9, 0), + datetime.datetime(1997, 9, 4, 9, 0), + datetime.datetime(1997, 9, 5, 9, 0), + datetime.datetime(1997, 9, 8, 9, 0)] + + +Weekly, for 4 weeks, plus one time on day 7, and not on day 16. + +.. doctest:: rruleset + + >>> set = rruleset() + >>> set.rrule(rrule(WEEKLY, count=4, + dtstart=parse("19970902T090000"))) + >>> set.rdate(datetime.datetime(1997, 9, 7, 9, 0)) + >>> set.exdate(datetime.datetime(1997, 9, 16, 9, 0)) + >>> list(set) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 7, 9, 0), + datetime.datetime(1997, 9, 9, 9, 0), + datetime.datetime(1997, 9, 23, 9, 0)] + + +rrulestr() examples +------------------- + +Every 10 days, 5 occurrences. + +.. doctest:: rrulestr + + >>> list(rrulestr(""" + ... DTSTART:19970902T090000 + ... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5 + ... """)) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 12, 9, 0), + datetime.datetime(1997, 9, 22, 9, 0), + datetime.datetime(1997, 10, 2, 9, 0), + datetime.datetime(1997, 10, 12, 9, 0)] + + +Same thing, but passing only the `RRULE` value. + +.. doctest:: rrulestr + + >>> list(rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5", + dtstart=parse("19970902T090000"))) + [datetime.datetime(1997, 9, 2, 9, 0), + datetime.datetime(1997, 9, 12, 9, 0), + datetime.datetime(1997, 9, 22, 9, 0), + datetime.datetime(1997, 10, 2, 9, 0), + datetime.datetime(1997, 10, 12, 9, 0)] + + +Notice that when using a single rule, it returns an +`rrule` instance, unless `forceset` was used. + +.. doctest:: rrulestr + + >>> rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5") + <dateutil.rrule.rrule instance at 0x30269f08> + + >>> rrulestr(""" + ... DTSTART:19970902T090000 + ... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5 + ... """) + <dateutil.rrule.rrule instance at 0x302699e0> + + >>> rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5", forceset=True) + <dateutil.rrule.rruleset instance at 0x30269f08> + + +But when an `rruleset` is needed, it is automatically used. + +.. doctest:: rrulestr + + >>> rrulestr(""" + ... DTSTART:19970902T090000 + ... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5 + ... RRULE:FREQ=DAILY;INTERVAL=5;COUNT=3 + ... """) + <dateutil.rrule.rruleset instance at 0x302699e0> + + +parse examples +----------- +The following code will prepare the environment: + +.. doctest:: tz + + >>> from dateutil.parser import * + >>> from dateutil.tz import * + >>> from datetime import * + >>> TZOFFSETS = {"BRST": -10800} + >>> BRSTTZ = tzoffset(-10800, "BRST") + >>> DEFAULT = datetime(2003, 9, 25) + + +Some simple examples based on the `date` command, using the +`ZOFFSET` dictionary to provide the BRST timezone offset. + +.. doctest:: tz + + >>> parse("Thu Sep 25 10:36:28 BRST 2003", tzinfos=TZOFFSETS) + datetime.datetime(2003, 9, 25, 10, 36, 28, + tzinfo=tzoffset('BRST', -10800)) + + >>> parse("2003 10:36:28 BRST 25 Sep Thu", tzinfos=TZOFFSETS) + datetime.datetime(2003, 9, 25, 10, 36, 28, + tzinfo=tzoffset('BRST', -10800)) + + +Notice that since BRST is my local timezone, parsing it without +further timezone settings will yield a `tzlocal` timezone. + +.. doctest:: tz + + >>> parse("Thu Sep 25 10:36:28 BRST 2003") + datetime.datetime(2003, 9, 25, 10, 36, 28, tzinfo=tzlocal()) + + +We can also ask to ignore the timezone explicitly: + +.. doctest:: tz + + >>> parse("Thu Sep 25 10:36:28 BRST 2003", ignoretz=True) + datetime.datetime(2003, 9, 25, 10, 36, 28) + + +That's the same as processing a string without timezone: + +.. doctest:: tz + + >>> parse("Thu Sep 25 10:36:28 2003") + datetime.datetime(2003, 9, 25, 10, 36, 28) + + +Without the year, but passing our `DEFAULT` datetime to return +the same year, no mattering what year we currently are in: + +.. doctest:: tz + + >>> parse("Thu Sep 25 10:36:28", default=DEFAULT) + datetime.datetime(2003, 9, 25, 10, 36, 28) + + +Strip it further: + +.. doctest:: tz + + >>> parse("Thu Sep 10:36:28", default=DEFAULT) + datetime.datetime(2003, 9, 25, 10, 36, 28) + + >>> parse("Thu 10:36:28", default=DEFAULT) + datetime.datetime(2003, 9, 25, 10, 36, 28) + + >>> parse("Thu 10:36", default=DEFAULT) + datetime.datetime(2003, 9, 25, 10, 36) + + >>> parse("10:36", default=DEFAULT) + datetime.datetime(2003, 9, 25, 10, 36) + >>> + + +Strip in a different way: + +.. doctest:: tz + + >>> parse("Thu Sep 25 2003") + datetime.datetime(2003, 9, 25, 0, 0) + + >>> parse("Sep 25 2003") + datetime.datetime(2003, 9, 25, 0, 0) + + >>> parse("Sep 2003", default=DEFAULT) + datetime.datetime(2003, 9, 25, 0, 0) + + >>> parse("Sep", default=DEFAULT) + datetime.datetime(2003, 9, 25, 0, 0) + + >>> parse("2003", default=DEFAULT) + datetime.datetime(2003, 9, 25, 0, 0) + + +Another format, based on `date -R` (RFC822): + +.. doctest:: tz + + >>> parse("Thu, 25 Sep 2003 10:49:41 -0300") + datetime.datetime(2003, 9, 25, 10, 49, 41, + tzinfo=tzoffset(None, -10800)) + + +ISO format: + +.. doctest:: tz + + >>> parse("2003-09-25T10:49:41.5-03:00") + datetime.datetime(2003, 9, 25, 10, 49, 41, 500000, + tzinfo=tzoffset(None, -10800)) + + +Some variations: + +.. doctest:: tz + + >>> parse("2003-09-25T10:49:41") + datetime.datetime(2003, 9, 25, 10, 49, 41) + + >>> parse("2003-09-25T10:49") + datetime.datetime(2003, 9, 25, 10, 49) + + >>> parse("2003-09-25T10") + datetime.datetime(2003, 9, 25, 10, 0) + + >>> parse("2003-09-25") + datetime.datetime(2003, 9, 25, 0, 0) + + +ISO format, without separators: + +.. doctest:: tz + + >>> parse("20030925T104941.5-0300") + datetime.datetime(2003, 9, 25, 10, 49, 41, 500000, + tzinfo=tzinfo=tzoffset(None, -10800)) + + >>> parse("20030925T104941-0300") + datetime.datetime(2003, 9, 25, 10, 49, 41, + tzinfo=tzoffset(None, -10800)) + + >>> parse("20030925T104941") + datetime.datetime(2003, 9, 25, 10, 49, 41) + + >>> parse("20030925T1049") + datetime.datetime(2003, 9, 25, 10, 49) + + >>> parse("20030925T10") + datetime.datetime(2003, 9, 25, 10, 0) + + >>> parse("20030925") + datetime.datetime(2003, 9, 25, 0, 0) + + +Everything together. + +.. doctest:: tz + + >>> parse("199709020900") + datetime.datetime(1997, 9, 2, 9, 0) + >>> parse("19970902090059") + datetime.datetime(1997, 9, 2, 9, 0, 59) + + +Different date orderings: + +.. doctest:: tz + + >>> parse("2003-09-25") + datetime.datetime(2003, 9, 25, 0, 0) + + >>> parse("2003-Sep-25") + datetime.datetime(2003, 9, 25, 0, 0) + + >>> parse("25-Sep-2003") + datetime.datetime(2003, 9, 25, 0, 0) + + >>> parse("Sep-25-2003") + datetime.datetime(2003, 9, 25, 0, 0) + + >>> parse("09-25-2003") + datetime.datetime(2003, 9, 25, 0, 0) + + >>> parse("25-09-2003") + datetime.datetime(2003, 9, 25, 0, 0) + + +Check some ambiguous dates: + +.. doctest:: tz + + >>> parse("10-09-2003") + datetime.datetime(2003, 10, 9, 0, 0) + + >>> parse("10-09-2003", dayfirst=True) + datetime.datetime(2003, 9, 10, 0, 0) + + >>> parse("10-09-03") + datetime.datetime(2003, 10, 9, 0, 0) + + >>> parse("10-09-03", yearfirst=True) + datetime.datetime(2010, 9, 3, 0, 0) + + +Other date separators are allowed: + +.. doctest:: tz + + >>> parse("2003.Sep.25") + datetime.datetime(2003, 9, 25, 0, 0) + + >>> parse("2003/09/25") + datetime.datetime(2003, 9, 25, 0, 0) + + +Even with spaces: + +.. doctest:: tz + + >>> parse("2003 Sep 25") + datetime.datetime(2003, 9, 25, 0, 0) + + >>> parse("2003 09 25") + datetime.datetime(2003, 9, 25, 0, 0) + + +Hours with letters work: + +.. doctest:: tz + + >>> parse("10h36m28.5s", default=DEFAULT) + datetime.datetime(2003, 9, 25, 10, 36, 28, 500000) + + >>> parse("01s02h03m", default=DEFAULT) + datetime.datetime(2003, 9, 25, 2, 3, 1) + + >>> parse("01h02m03", default=DEFAULT) + datetime.datetime(2003, 9, 3, 1, 2) + + >>> parse("01h02", default=DEFAULT) + datetime.datetime(2003, 9, 2, 1, 0) + + >>> parse("01h02s", default=DEFAULT) + datetime.datetime(2003, 9, 25, 1, 0, 2) + + +With AM/PM: + +.. doctest:: tz + + >>> parse("10h am", default=DEFAULT) + datetime.datetime(2003, 9, 25, 10, 0) + + >>> parse("10pm", default=DEFAULT) + datetime.datetime(2003, 9, 25, 22, 0) + + >>> parse("12:00am", default=DEFAULT) + datetime.datetime(2003, 9, 25, 0, 0) + + >>> parse("12pm", default=DEFAULT) + datetime.datetime(2003, 9, 25, 12, 0) + + +Some special treating for ''pertain'' relations: + +.. doctest:: tz + + >>> parse("Sep 03", default=DEFAULT) + datetime.datetime(2003, 9, 3, 0, 0) + + >>> parse("Sep of 03", default=DEFAULT) + datetime.datetime(2003, 9, 25, 0, 0) + + +Fuzzy parsing: + +.. doctest:: tz + + >>> s = "Today is 25 of September of 2003, exactly " \ + ... "at 10:49:41 with timezone -03:00." + >>> parse(s, fuzzy=True) + datetime.datetime(2003, 9, 25, 10, 49, 41, + tzinfo=tzoffset(None, -10800)) + + +Other random formats: + +.. doctest:: tz + + >>> parse("Wed, July 10, '96") + datetime.datetime(1996, 7, 10, 0, 0) + + >>> parse("1996.07.10 AD at 15:08:56 PDT", ignoretz=True) + datetime.datetime(1996, 7, 10, 15, 8, 56) + + >>> parse("Tuesday, April 12, 1952 AD 3:30:42pm PST", ignoretz=True) + datetime.datetime(1952, 4, 12, 15, 30, 42) + + >>> parse("November 5, 1994, 8:15:30 am EST", ignoretz=True) + datetime.datetime(1994, 11, 5, 8, 15, 30) + + >>> parse("3rd of May 2001") + datetime.datetime(2001, 5, 3, 0, 0) + + >>> parse("5:50 A.M. on June 13, 1990") + datetime.datetime(1990, 6, 13, 5, 50) + + +tzutc examples +-------------- + +.. doctest:: tzutc + + >>> from datetime import * + >>> from dateutil.tz import * + + >>> datetime.now() + datetime.datetime(2003, 9, 27, 9, 40, 1, 521290) + + >>> datetime.now(tzutc()) + datetime.datetime(2003, 9, 27, 12, 40, 12, 156379, tzinfo=tzutc()) + + >>> datetime.now(tzutc()).tzname() + 'UTC' + + +tzoffset examples +----------------- + +.. doctest:: tzoffset + + >>> from datetime import * + >>> from dateutil.tz import * + + >>> datetime.now(tzoffset("BRST", -10800)) + datetime.datetime(2003, 9, 27, 9, 52, 43, 624904, + tzinfo=tzinfo=tzoffset('BRST', -10800)) + + >>> datetime.now(tzoffset("BRST", -10800)).tzname() + 'BRST' + + >>> datetime.now(tzoffset("BRST", -10800)).astimezone(tzutc()) + datetime.datetime(2003, 9, 27, 12, 53, 11, 446419, + tzinfo=tzutc()) + + +tzlocal examples +---------------- + +.. doctest:: tzlocal + + >>> from datetime import * + >>> from dateutil.tz import * + + >>> datetime.now(tzlocal()) + datetime.datetime(2003, 9, 27, 10, 1, 43, 673605, + tzinfo=tzlocal()) + + >>> datetime.now(tzlocal()).tzname() + 'BRST' + + >>> datetime.now(tzlocal()).astimezone(tzoffset(None, 0)) + datetime.datetime(2003, 9, 27, 13, 3, 0, 11493, + tzinfo=tzoffset(None, 0)) + + +tzstr examples +-------------- +Here are examples of the recognized formats: + + * `EST5EDT` + * `EST5EDT,4,0,6,7200,10,0,26,7200,3600` + * `EST5EDT,4,1,0,7200,10,-1,0,7200,3600` + * `EST5EDT4,M4.1.0/02:00:00,M10-5-0/02:00` + * `EST5EDT4,95/02:00:00,298/02:00` + * `EST5EDT4,J96/02:00:00,J299/02:00` + +Notice that if daylight information is not present, but a +daylight abbreviation was provided, `tzstr` will follow the +convention of using the first sunday of April to start daylight +saving, and the last sunday of October to end it. If start or +end time is not present, 2AM will be used, and if the daylight +offset is not present, the standard offset plus one hour will +be used. This convention is the same as used in the GNU libc. + +This also means that some of the above examples are exactly +equivalent, and all of these examples are equivalent +in the year of 2003. + +Here is the example mentioned in the + +[http://www.python.org/doc/current/lib/module-time.html time module documentation]. + + +.. doctest:: tzstr + + >>> os.environ['TZ'] = 'EST+05EDT,M4.1.0,M10.5.0' + >>> time.tzset() + >>> time.strftime('%X %x %Z') + '02:07:36 05/08/03 EDT' + >>> os.environ['TZ'] = 'AEST-10AEDT-11,M10.5.0,M3.5.0' + >>> time.tzset() + >>> time.strftime('%X %x %Z') + '16:08:12 05/08/03 AEST' + + +And here is an example showing the same information using `tzstr`, +without touching system settings. + +.. doctest:: tzstr + + >>> tz1 = tzstr('EST+05EDT,M4.1.0,M10.5.0') + >>> tz2 = tzstr('AEST-10AEDT-11,M10.5.0,M3.5.0') + >>> dt = datetime(2003, 5, 8, 2, 7, 36, tzinfo=tz1) + >>> dt.strftime('%X %x %Z') + '02:07:36 05/08/03 EDT' + >>> dt.astimezone(tz2).strftime('%X %x %Z') + '16:07:36 05/08/03 AEST' + + +Are these really equivalent? + +.. doctest:: tzstr + + >>> tzstr('EST5EDT') == tzstr('EST5EDT,4,1,0,7200,10,-1,0,7200,3600') + True + + +Check the daylight limit. + +.. doctest:: tzstr + + >>> datetime(2003, 4, 6, 1, 59, tzinfo=tz).tzname() + 'EST' + >>> datetime(2003, 4, 6, 2, 00, tzinfo=tz).tzname() + 'EDT' + >>> datetime(2003, 10, 26, 0, 59, tzinfo=tz).tzname() + 'EDT' + >>> datetime(2003, 10, 26, 1, 00, tzinfo=tz).tzname() + 'EST' + + +tzrange examples +---------------- + +.. doctest:: tzrange + + >>> tzstr('EST5EDT') == tzrange("EST", -18000, "EDT") + True + + >>> from dateutil.relativedelta import * + >>> range1 = tzrange("EST", -18000, "EDT") + >>> range2 = tzrange("EST", -18000, "EDT", -14400, + ... relativedelta(hours=+2, month=4, day=1, + weekday=SU(+1)), + ... relativedelta(hours=+1, month=10, day=31, + weekday=SU(-1))) + >>> tzstr('EST5EDT') == range1 == range2 + True + + +Notice a minor detail in the last example: while the DST should end +at 2AM, the delta will catch 1AM. That's because the daylight saving +time should end at 2AM standard time (the difference between STD and +DST is 1h in the given example) instead of the DST time. That's how +the `tzinfo` subtypes should deal with the extra hour that happens +when going back to the standard time. Check + +[http://www.python.org/doc/current/lib/datetime-tzinfo.html tzinfo documentation] + +for more information. + +tzfile examples +--------------- + +.. doctest:: tzfile + + >>> tz = tzfile("/etc/localtime") + >>> datetime.now(tz) + datetime.datetime(2003, 9, 27, 12, 3, 48, 392138, + tzinfo=tzfile('/etc/localtime')) + + >>> datetime.now(tz).astimezone(tzutc()) + datetime.datetime(2003, 9, 27, 15, 3, 53, 70863, + tzinfo=tzutc()) + + >>> datetime.now(tz).tzname() + 'BRST' + >>> datetime(2003, 1, 1, tzinfo=tz).tzname() + 'BRDT' + + +Check the daylight limit. + +.. doctest:: tzfile + + >>> tz = tzfile('/usr/share/zoneinfo/EST5EDT') + >>> datetime(2003, 4, 6, 1, 59, tzinfo=tz).tzname() + 'EST' + >>> datetime(2003, 4, 6, 2, 00, tzinfo=tz).tzname() + 'EDT' + >>> datetime(2003, 10, 26, 0, 59, tzinfo=tz).tzname() + 'EDT' + >>> datetime(2003, 10, 26, 1, 00, tzinfo=tz).tzname() + 'EST' + + +tzical examples +--------------- +Here is a sample file extracted from the RFC. This file defines +the `EST5EDT` timezone, and will be used in the following example. + + BEGIN:VTIMEZONE + TZID:US-Eastern + LAST-MODIFIED:19870101T000000Z + TZURL:http://zones.stds_r_us.net/tz/US-Eastern + BEGIN:STANDARD + DTSTART:19671029T020000 + RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 + TZOFFSETFROM:-0400 + TZOFFSETTO:-0500 + TZNAME:EST + END:STANDARD + BEGIN:DAYLIGHT + DTSTART:19870405T020000 + RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4 + TZOFFSETFROM:-0500 + TZOFFSETTO:-0400 + TZNAME:EDT + END:DAYLIGHT + END:VTIMEZONE + +And here is an example exploring a `tzical` type: + +.. doctest:: tzfile + + >>> from dateutil.tz import *; from datetime import * + + >>> tz = tzical('EST5EDT.ics') + >>> tz.keys() + ['US-Eastern'] + + >>> est = tz.get('US-Eastern') + >>> est + <tzicalvtz 'US-Eastern'> + + >>> datetime.now(est) + datetime.datetime(2003, 10, 6, 19, 44, 18, 667987, + tzinfo=<tzicalvtz 'US-Eastern'>) + + >>> est == tz.get() + True + + +Let's check the daylight ranges, as usual: + +.. doctest:: tzfile + + >>> datetime(2003, 4, 6, 1, 59, tzinfo=est).tzname() + 'EST' + >>> datetime(2003, 4, 6, 2, 00, tzinfo=est).tzname() + 'EDT' + + >>> datetime(2003, 10, 26, 0, 59, tzinfo=est).tzname() + 'EDT' + >>> datetime(2003, 10, 26, 1, 00, tzinfo=est).tzname() + 'EST' + + +tzwin examples +-------------- + +.. doctest:: tzwin + + >>> tz = tzwin("E. South America Standard Time") + + +tzwinlocal examples +------------------- + + +.. doctest:: tzwinlocal + + >>> tz = tzwinlocal() + +# vim:ts=4:sw=4:et diff --git a/docs/index.rst b/docs/index.rst index 4d8f560..5d252f6 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,9 +3,11 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to dateutil's documentation! -==================================== +.. include:: ../README.rst + +Documentation +============= Contents: .. toctree:: @@ -18,6 +20,7 @@ Contents: rrule tz zoneinfo + examples Indices and tables ================== |