25

我有一个 python 脚本,它使用此调用以 YYYY-MM-DD 格式获取昨天的日期:

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

它大部分时间都可以工作,但是今天早上运行脚本时,2013-03-11 0:35 CDT它返回"2013-03-09"而不是"2013-03-10".

据推测,夏令时(昨天开始)是罪魁祸首。我猜想timedelta(days=1)实现的方式是减去 24 小时,而 24 小时前2013-03-11 0:35 CDT2013-03-09 23:35 CST,这导致了"2013-03-09".

那么在 python 中获取昨天日期的 DST 安全的好方法是什么?

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

4

3 回答 3

39
datetime.date.fromordinal(datetime.date.today().toordinal()-1)
于 2013-03-11T17:29:28.937 回答
10

我无法在 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()功能的最简单实现了。

于 2013-03-11T17:42:30.460 回答
7

如果您使用对时区(尤其是 DST)一无所知的2013-03-10天真对象,您会得到:datetime

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()引发错误)。

于 2013-03-11T17:54:05.940 回答