dateutil示例

相对elta示例

我们开始旅行吧:

>>> from datetime import *; from dateutil.relativedelta import *
>>> import calendar

存储一些值:

>>> NOW = datetime.now()
>>> TODAY = date.today()
>>> NOW
datetime.datetime(2003, 9, 17, 20, 54, 47, 282310)
>>> TODAY
datetime.date(2003, 9, 17)

下个月

>>> NOW+relativedelta(months=+1)
datetime.datetime(2003, 10, 17, 20, 54, 47, 282310)

下个月再加上一周。

>>> NOW+relativedelta(months=+1, weeks=+1)
datetime.datetime(2003, 10, 24, 20, 54, 47, 282310)

下个月再加上一周,上午10点。

>>> TODAY+relativedelta(months=+1, weeks=+1, hour=10)
datetime.datetime(2003, 10, 24, 10, 0)

这是另一个使用绝对相对增量的例子。注意使用了year和month(都是单数形式),这使得值 替换 而不是对它们执行算术运算。

>>> NOW+relativedelta(year=1, month=1)
datetime.datetime(1, 1, 17, 20, 54, 47, 282310)

我们换个角度试试吧。请注意,我们在relativedelta中得到的小时设置是相对的,因为这是一个差异,而weeks参数已经消失了。

>>> relativedelta(datetime(2003, 10, 24, 10, 0), TODAY)
relativedelta(months=+1, days=+7, hours=+10)

一年前一个月。

>>> NOW+relativedelta(years=+1, months=-1)
datetime.datetime(2004, 8, 17, 20, 54, 47, 282310)

它如何处理不同天数的月份?请注意,添加一个月永远不会跨越月份边界。

>>> 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)

多年的逻辑是一样的,即使是在闰年。

>>> 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)

下星期五

>>> TODAY+relativedelta(weekday=FR)
datetime.date(2003, 9, 19)

>>> TODAY+relativedelta(weekday=calendar.FRIDAY)
datetime.date(2003, 9, 19)

这个月的上周五。

>>> TODAY+relativedelta(day=31, weekday=FR(-1))
datetime.date(2003, 9, 26)

下星期三(就是今天!)。

>>> TODAY+relativedelta(weekday=WE(+1))
datetime.date(2003, 9, 17)

下星期三,但不是今天。

>>> TODAY+relativedelta(days=+1, weekday=WE(+1))
datetime.date(2003, 9, 24)

跟随 ISO year week number notation 找到1997年第15周的第一天。

>>> datetime(1997,1,1)+relativedelta(day=4, weekday=MO(-1), weeks=+14)
datetime.datetime(1997, 4, 7, 0, 0)

千年变了多久了?

>>> relativedelta(NOW, date(2001,1,1))
relativedelta(years=+2, months=+8, days=+16,
              hours=+20, minutes=+54, seconds=+47, microseconds=+282310)

约翰多大了?

>>> 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)

它也适用于约会。

>>> relativedelta(TODAY, johnbirthday)
relativedelta(years=+25, months=+5, days=+11, hours=+12)

使用年份获取今天的日期:

>>> date(2003, 1, 1)+relativedelta(yearday=260)
datetime.date(2003, 9, 17)

我们可以使用今天的日期,因为在给定的年份中,yearday应该是绝对的:

>>> TODAY+relativedelta(yearday=260)
datetime.date(2003, 9, 17)

去年应该是同一天:

>>> date(2002, 1, 1)+relativedelta(yearday=260)
datetime.date(2002, 9, 17)

但不是闰年:

>>> date(2000, 1, 1)+relativedelta(yearday=260)
datetime.date(2000, 9, 16)

我们可以用非闰年来忽略这一点:

>>> date(2000, 1, 1)+relativedelta(nlyearday=260)
datetime.date(2000, 9, 17)

rrule示例

这些示例是从RFC转换而来的。

准备好环境。

>>> from dateutil.rrule import *
>>> from dateutil.parser import *
>>> from datetime import *

>>> import pprint
>>> import sys
>>> sys.displayhook = pprint.pprint

每天10次。

 >>> 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)]

1997年12月24日前每天

 >>> 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)]

每隔一天发生5次。

 >>> 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)]

每10天发生5次。

 >>> 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)]

一月份的每一天,连续三年。

 >>> 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, 30, 9, 0),
  datetime.datetime(2000, 1, 31, 9, 0)]

同样的事情,在另一方面。

 >>> list(rrule(DAILY, bymonth=1,
 ...            dtstart=parse("19980101T090000"),
 ...            until=parse("20000131T090000")))
 [datetime.datetime(1998, 1, 1, 9, 0),
  ...
  datetime.datetime(2000, 1, 31, 9, 0)]

每周10次。

 >>> 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)]

每隔一周,发生6次。

 >>> 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)]

每周二和周四各一次,持续5周。

 >>> 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)]

每隔一周的周二和周四,共发生8次。

 >>> 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)]

每月第一个星期五发生10次。

 >>> 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)]

每隔一个月的第一个星期天和最后一个星期天发生10次。

 >>> 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)]

每月的第二至最后一个星期一,为期6个月。

 >>> 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)]

每月的第三天到最后一天,为期6个月。

 >>> 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)]

每月2号和15号发生5次。

 >>> 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)]

每月的第一天和最后一天发生3次。

 >>> list(rrule(MONTHLY, count=5, bymonthday=(-1,1,),
 ...            dtstart=parse("19970902T090000")))
 [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)]

每18个月10日至15日发生10次。

 >>> 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)]

每周二,每隔一个月,发生6次。

 >>> 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)]

每年6月和7月发生10次。

 >>> list(rrule(YEARLY, count=4, bymonth=(6,7),
 ...            dtstart=parse("19970610T090000")))
 [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)]

每三年第1天、第100天和第200天发生4次。

 >>> 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)]

每年的第20个星期一,发生3次。

 >>> 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)]

第20周的星期一(其中默认的星期一开始是星期一),发生3次。

 >>> 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)]

第1周可能在去年。

 >>> 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)]

而周数大于51的可能是明年。

 >>> 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)]

只有一些年份有第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)]

每周五13号,4次。

 >>> 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)]

每四年,即11月星期一后的第一个星期二,发生3次(美国总统选举日):

 >>> 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)]

在接下来的3个月内,星期二、星期三或星期四中的一个月内的第三个实例:

 >>> 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)]

每月的第二个工作日到最后一个工作日,发生3次。

 >>> 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)]

每3小时从上午9:00到下午5:00。

 >>> 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)]

每15分钟发生6次。

 >>> 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)]

每小时半发生4次。

 >>> 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)]

每20分钟从上午9:00到下午4:40,连续两天。

 >>> 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)]

一个示例,其中生成的天数因 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示例

每天,连续7天,星期六和星期天跳跃。

 >>> 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)]

每周,持续4周,第7天加一次,而不是第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()示例

每10天发生5次。

 >>> 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)]

同样的事情,但是只传递 RRULE 价值。

 >>> 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)]

注意,当使用单个规则时,它返回一个 rrule 实例,除非 forceset 使用。

 >>> rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5")
 <dateutil.rrule.rrule object at 0x...>

 >>> rrulestr("""
 ... DTSTART:19970902T090000
 ... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5
 ... """)
 <dateutil.rrule.rrule object at 0x...>

 >>> rrulestr("FREQ=DAILY;INTERVAL=10;COUNT=5", forceset=True)
 <dateutil.rrule.rruleset object at 0x...>

但是当一个 rruleset 如果需要,则自动使用。

 >>> rrulestr("""
 ... DTSTART:19970902T090000
 ... RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5
 ... RRULE:FREQ=DAILY;INTERVAL=5;COUNT=3
 ... """)
 <dateutil.rrule.rruleset object at 0x...>

解析示例

以下代码将准备环境:

>>> from dateutil.parser import *
>>> from dateutil.tz import *
>>> from datetime import *
>>> TZOFFSETS = {"BRST": -10800}
>>> BRSTTZ = tzoffset("BRST", -10800)
>>> DEFAULT = datetime(2003, 9, 25)

基于 date 命令,使用 ZOFFSET 提供BRST时区偏移量的字典。

>>> 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))

请注意,由于BRST是我的本地时区,解析它而不进一步设置时区将生成一个 tzlocal 时区。

>>> parse("Thu Sep 25 10:36:28 BRST 2003")
datetime.datetime(2003, 9, 25, 10, 36, 28, tzinfo=tzlocal())

我们也可以要求明确忽略时区:

>>> parse("Thu Sep 25 10:36:28 BRST 2003", ignoretz=True)
datetime.datetime(2003, 9, 25, 10, 36, 28)

这与处理不带时区的字符串相同:

>>> parse("Thu Sep 25 10:36:28 2003")
datetime.datetime(2003, 9, 25, 10, 36, 28)

没有年头,却过了我们的 DEFAULT datetime返回同一年,不管我们现在是哪一年:

>>> parse("Thu Sep 25 10:36:28", default=DEFAULT)
datetime.datetime(2003, 9, 25, 10, 36, 28)

进一步剥离:

>>> 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)

以不同的方式剥离:

>>> 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)

另一种格式,基于 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格式:

 >>> parse("2003-09-25T10:49:41.5-03:00")
 datetime.datetime(2003, 9, 25, 10, 49, 41, 500000,
           tzinfo=tzoffset(None, -10800))

一些变化:

>>> 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格式,无分隔符:

 >>> parse("20030925T104941.5-0300")
 datetime.datetime(2003, 9, 25, 10, 49, 41, 500000,
                   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)

一切都在一起。

>>> parse("199709020900")
datetime.datetime(1997, 9, 2, 9, 0)
>>> parse("19970902090059")
datetime.datetime(1997, 9, 2, 9, 0, 59)

不同日期顺序:

>>> 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)

检查一些不明确的日期:

>>> 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)

允许使用其他日期分隔符:

>>> parse("2003.Sep.25")
datetime.datetime(2003, 9, 25, 0, 0)

>>> parse("2003/09/25")
datetime.datetime(2003, 9, 25, 0, 0)

即使有空格:

>>> parse("2003 Sep 25")
datetime.datetime(2003, 9, 25, 0, 0)

>>> parse("2003 09 25")
datetime.datetime(2003, 9, 25, 0, 0)

字母工作时间:

>>> 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, 25, 1, 2, 3)

>>> parse("01h02", default=DEFAULT)
datetime.datetime(2003, 9, 25, 1, 2)

>>> parse("01h02s", default=DEFAULT)
datetime.datetime(2003, 9, 25, 1, 0, 2)

上午/下午:

>>> 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)

“属于”关系的一些特殊待遇:

>>> 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)

模糊解析:

 >>> 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))

其他随机格式:

>>> 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)

使用自定义parserinfo重写parserinfo

>>> from dateutil.parser import parse, parserinfo
>>> class CustomParserInfo(parserinfo):
...     # e.g. edit a property of parserinfo to allow a custom 12 hour format
...     AMPM = [("am", "a", "xm"), ("pm", "p")]
>>> parse('2018-06-08 12:06:58 XM', parserinfo=CustomParserInfo())
datetime.datetime(2018, 6, 8, 0, 6, 58)

tzutc示例

>>> from datetime import *
>>> from dateutil import tz

>>> datetime.now()
datetime.datetime(2003, 9, 27, 9, 40, 1, 521290)

>>> datetime.now(tz.UTC)
datetime.datetime(2003, 9, 27, 12, 40, 12, 156379, tzinfo=tzutc())

>>> datetime.now(tz.UTC).tzname()
'UTC'

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(UTC)
 datetime.datetime(2003, 9, 27, 12, 53, 11, 446419,
           tzinfo=tzutc())

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示例

以下是可识别格式的示例:

  • EST5EDT

  • 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

请注意,如果日光信息不存在,但提供了日光缩写, tzstr 将遵循4月的第一个星期天开始夏令时,10月的最后一个星期日结束夏令时的惯例。如果开始时间或结束时间不存在,将使用凌晨2点,如果不存在日光偏移,则将使用标准偏移加上一小时。此约定与GNU libc中使用的相同。

这也意味着上面的一些例子是完全等价的,而且所有这些例子在2003年都是等价的。

下面是

[https://docs.python.org/3/library/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'

下面是一个例子,用 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'

这些真的是对等的吗?

>>> tzstr('EST5EDT') == tzstr('EST5EDT,M4.1.0,M10.5.0')
True

检查日光限制。

>>> tz = tzstr('EST+05EDT,M4.1.0,M10.5.0')
>>> 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, 2, 00, tzinfo=tz).tzname()
'EST'

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

注意最后一个例子中的一个小细节:虽然DST应该在凌晨2点结束,但是delta将捕捉到凌晨1点。这是因为夏令时应该在标准时间凌晨2点结束(在给定示例中,标准时间和夏令时的差值为1小时),而不是夏令时。这就是为什么 tzinfo 子类型应该处理返回标准时间时发生的额外小时数。检查

[https://docs.python.org/3/library/datetime.html#datetime.tzinfo tzinfo documentation]

更多信息。

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(UTC)
 datetime.datetime(2003, 9, 27, 15, 3, 53, 70863,
           tzinfo=tzutc())

 >>> datetime.now(tz).tzname()
 'BRST'
 >>> datetime(2003, 1, 1, tzinfo=tz).tzname()
 'BRDT'

检查日光限制。

>>> 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'

典型例子

下面是从RFC中提取的示例文件。此文件定义 EST5EDT 时区,和将在下面的示例中使用。

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

下面是一个探索 tzical 类型:

>>> from dateutil.tz import *; from datetime import *

>>> tz = tzical('samples/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

像往常一样检查日光范围:

>>> 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示例

>>> tz = tzwin("E. South America Standard Time")

tzwinlocal示例

>>> tz = tzwinlocal()

# vim:ts=4:sw=4:et