python relativedelta中的非确定性行为

时间:2014-10-19 14:26:10

标签: python datetime eve

我想在另一个约会日期前七天获得约会时间。

所以我在控制台做的事情:

import datetime
from dateutil.relativedelta import relativedelta

dt = datetime.date(2014, 10, 18)
dt_minus_one_week = datetime.date(2014, 10, 18) - relativedelta(days=7)

结果如预期的那样datetime.date(2014, 10, 11)。但是,我正在运行一个webservice(使用eve,但我认为这不重要)应用程序很长一段时间,然后当我调用该方法获得一周的旧日期时,我得到datetime.date(2014, 10, 10)。代码与上面完全相同。

如果我重新启动应用程序,日期就是我的预期。为什么会这样?相对是不确定的吗?有没有办法重置"它可以让我再次获得正确的价值吗?

3 个答案:

答案 0 :(得分:3)

从评论中对你的功能的描述,你已经踩到了一个普通的蟒蛇“地雷”。

def get_d_minus_one_pacific_local_date():
    return datetime.datetime.now(
            pytz.timezone('US/Pacific')).date() - relativedelta(days=1)

def get_relative_date(init=get_d_minus_one_pacific_local_date(), *args, **kwargs):
    return init + datetime.timedelta(*args, **kwargs)

# ...
get_relative_date(days=-7)

init定义中设置get_relative_date的默认值时,不会再次重新计算。因此,当第二天到来时,它将使用函数定义时获得的值。

请参阅:https://stackoverflow.com/a/530768/632706

答案 1 :(得分:1)

如果你只处理几天,我会使用datetime模块。

import datetime

old_date = datetime.date(2014, 10, 18)

new_date = old_date - datetime.timedelta(days=7)

输出为datetime.date(2014, 10, 11)。我稍微使用了timedelta,并且避免了日期不准确的问题。

答案 2 :(得分:1)

假设Web服务器设置在美国/夏威夷时区和当前时间 当地时间是2014-10-17的晚上11点。然后

In [57]: datetime.datetime(2014, 10, 17, 23, 0, 0, tzinfo=pytz.timezone('US/Pacific')).date()
Out[57]: datetime.date(2014, 10, 17)

但是,美国/太平洋地区目前的时间是

In [44]: now = datetime.datetime(2014, 10, 17, 23, 0, 0)

In [45]: hawaii = pytz.timezone('US/Hawaii')

In [46]: pacific = pytz.timezone('US/Pacific')

In [47]: pacific.normalize(hawaii.localize(now).astimezone(pacific)).date()
Out[47]: datetime.date(2014, 10, 18)

这会导致您看到的症状。

简而言之,您几乎从不想直接构建时区感知日期时间 将它提供给tzinfo:

datetime.datetime.now(pytz.timezone('US/Pacific')).date()

如果您使用的是pytz,请使用pytz timezone的localize方法:

tzone.localize(naive_date)

顺便说一下,

datetime.datetime.now(pytz.timezone('US/Pacific')).date()

总是等同于

datetime.datetime.now().date()

datetime.date.today()

datetime.datetime.now(pytz.timezone('US/Pacific'))与...相同 tzinfo设置为datetime.datetime.now()的{​​{1}},但是 如果你然后调用pytz.timezone('US/Pacific')方法,那么tzinfo无关紧要,因为你得到的只是年,月和日。