2013-03-11 86 views
24

我有一个使用这个调用来获取昨天的日期YYYY-MM-DD格式的python脚本:获取昨日在Python中,DST安全的日期

str(date.today() - timedelta(days=1))) 

它工作的大部分时间,但是当脚本今天早上跑了2013-03-11 0:35 CDT它返回"2013-03-09"而不是"2013-03-10"

大概是夏令时(从昨天开始)是怪罪。我猜想timedelta(days=1)实施的方式是24小时扣除,并且在2013-03-11 0:35 CDT之前的24小时是2013-03-09 23:35 CST,这导致了"2013-03-09"的结果。

那么什么是一个很好的DST安全的方式来获取昨天的日期在python中?

更新: bukzor指出我的代码应该正常工作后,我回到脚本并确定它没有被使用。它设置了默认值,但是一个包装器外壳脚本明确地设置了日期。所以这个bug是在shell脚本中,而不是python脚本。

+2

这样的问题只会发生在具有timezeone意识的datetime对象上,而date.today()不是。对象究竟是如何实例化的? – bukzor 2013-03-11 17:38:07

+0

@bukzor你是对的。事实证明,一个shell脚本正在通过不好的日期,看到我上面的更新。 – 2013-03-11 18:09:01

+0

这个问题应该关闭; OP声称他的错误在别处。 – 2013-11-05 16:04:29

回答

39
datetime.date.fromordinal(datetime.date.today().toordinal()-1) 
9

我无法重现您的问题在python2.7或python3.2:

>>> import datetime 
>>> today = datetime.date(2013, 3, 11) 
>>> print today 
2013-03-11 
>>> day = datetime.timedelta(days=1) 
>>> print today - day 
2013-03-10 

在我看来,这已经是一个“夏令安全的最简单的实现“yesterday()功能。

+0

您是否在尝试此操作之前将系统时间设置为2013-03-11 0:35?在夏令时开始的午夜后1小时内会遇到问题 - 当天只有23小时。 – tdelaney 2013-03-11 17:52:33

+0

@tdelaney:设置系统时间是一个迂回的方式来获得相同的结果。在这两种情况下,你都会得到一个“naive”datetime.date对象。 – bukzor 2013-03-11 21:45:12

+0

@tdelaney:代码的工作原理是因为它使用* naive *'date'对象。它正确地打印本地日期,但它没有告诉我们相对于UTC的实际时间:[它可能是不明确的,甚至不存在的时间](http://stackoverflow.com/a/29832960/4279)(例如,那里是巴西的时区,午夜有DST转换)。特别是,utc偏移量可能在今天和今天是不同的。您需要tz数据库[查找相应的UTC时间(例如,表示为意识到的日期时间对象)](http://stackoverflow.com/a/15345272/4279)。 – jfs 2015-04-23 23:55:23

7

你会得到2013-03-10如果使用幼稚datetime对象,知道什么时区(DST和特别):

from datetime import datetime, timedelta 

dt_naive = datetime(2013, 3, 11, 0, 35) 
print((dt_naive - timedelta(days=1)).date()) # ignores DST 
# -> 2013-03-10 

2013-03-09是正确的,如果你有兴趣是什么日起24小时前。

import pytz # $ pip install pytz 

local_tz = pytz.timezone("America/Chicago") # specify your local timezone 
dt = local_tz.localize(dt_naive, is_dst=None) # raise if dt_naive is ambiguous 
yesterday = local_tz.normalize(dt - timedelta(days=1)).date() 
print(yesterday) 
# -> 2013-03-09 

注:.date()带时区信息,所以你会再次得到2013-03-10

print(dt.date() - timedelta(days=1)) 
# -> 2013-03-10 

以昨日获得特别是时区:

from datetime import datetime, time, timedelta 
import pytz # $ pip install pytz 

tz = pytz.timezone("America/Chicago") 
yesterday = datetime.now(tz).date() - timedelta(days=1) 

# to add timezone info back (to get yesterday's midnight) 
midnight = tz.localize(datetime.combine(yesterday, time(0, 0)), is_dst=None) 

通过剥离时区信息可能会失败昨天获得如果时区在这段时间内缺少天数。然后,此方法会在给定时区内产生不存在的日期(tz.localize()会产生错误)。