查找两个日期时间之间是否相隔24小时

20

我有以下的方法:

# last_updated is a datetime() object, representing the last time this program ran
def time_diff(last_updated):
    day_period = last_updated.replace(day=last_updated.day + 1, 
                                      hour=1,
                                      minute=0,  
                                      second=0,
                                      microsecond=0)
    delta_time = day_period - last_updated
    hours = delta_time.seconds // 3600
    # make sure a period of 24hrs have passed before shuffling
    if hours >= 24:
        print "hello"
    else:
        print "do nothing"

我想知道在Python中如何判断是否已经过去了24小时自last_updated,该怎么做?


1
最后更新的格式是什么? - Padraic Cunningham
last_updated是什么?它是本地时间吗?您想要找出是否已经过去了超过24小时,还是下一天的当前时间更大,例如,last_updated=11月1日,晚上7点,而当前时间是11月2日,下午6:30(已经超过24小时,但是6:30 PM小于7 PM)(在纽约)。 - jfs
@PadraicCunningham 我已经更新了问题... last_updated 是一个 datetime(),它告诉我们程序上次更新的时间。现在我只需要知道自从 last_updated(从现在开始)以来是否已经过去了24小时。 - cybertextron
@J.F.Sebastian请查看对PadraicCunningham的评论。 - cybertextron
时区是什么?你能获取last_updated的UTC时间或Unix时间戳吗?你可以使用第三方模块吗?你需要支持Windows吗?如果你的代码每年会有一两个小时的错误,你介意吗? - jfs
2个回答

26
如果last_updated是代表UTC时间的无时区日期时间对象:
from datetime import datetime, timedelta

if (datetime.utcnow() - last_updated) > timedelta(hours=24): 
    # more than 24 hours passed

如果 last_updated 是本地时间(不带时区信息的日期时间对象):

import time

DAY = 86400
now = time.time()
then = time.mktime(last_updated.timetuple())
if (now - then) > DAY:
    # more than 24 hours passed
如果last_updated是模糊时间,例如在许多时区一年中的一次夏令时转换期间,则mktime()返回错误结果(例如,误差为一小时)的机会是50/50。time.mktime()还可能失败,如果C time库在给定平台上没有使用历史时区数据库,并且与现在相比,本地时区的UTC偏移在last_updated时间不同。这可能适用于去年所有时区的三分之一以上。Linux、OS X和最近版本的Windows都有tz数据库。要注意的是,如果在last_updated时间UTC偏移不同(在许多时区可能会出现),编写datetime.now() - last_updated(类似于UTC情况)可能会很诱人,但保证在所有平台上失败。基于mktime()的解决方案可以在某些平台上利用tz数据库,因此它可以处理UTC偏移的任何更改。对于可移植性,您可以安装tz数据库。Python中的pytz模块提供它。tzlocal可以返回与当地时区相应的pytz时区:
from datetime import datetime, timedelta
from tzlocal import get_localzone # $ pip install tzlocal

tz = get_localzone() # local timezone
then = tz.normalize(tz.localize(last_updated)) # make it timezone-aware
now = datetime.now(tz) # timezone-aware current time in the local timezone
if (now - then) > timedelta(hours=24):
    # more than 24 hours passed

即使过去的UTC偏移量不同,它也能正常工作。但是它无法(以及time.mktime())修复有歧义的时间(tz.localize()默认选择is_dst=False的时间)。调用tz.normalize()来调整不存在的时间,例如那些对应于DST转换的开始时间(它不应该影响结果)。

以上代码假定last_updated是一个naive datetime对象(没有关联时区信息)。如果last_updated是一个aware datetime对象,则很容易将其转换为UTC:

from datetime import datetime, timedelta

then_in_utc = last_updated.replace(tzinfo=None) - last_updated.utcoffset()
if (datetime.utcnow() - then_in_utc) > timedelta(hours=24):
    # more than 24 hours passed

一般提示:现在您应该明白为什么人们建议使用UTC时间并仅在显示时使用本地时间。


2

为了澄清一些事情,因为我不认为我们都使用time Python库。当您使用datetime时,这在Django中是非常常见的做法,如果您像这样进行比较:

if (now - then) > DAY:

it will hugely fail. This is because you can't compare datetime.timedelta to int.

The solution to this is to convert your objects to seconds.
For example:

from datetime import datetime

then = datetime_object
now = datetime.now()

if (now - then).total_seconds() > NUMBER_OF_SECONDS:
    # do something

Hope I helped out whoever faced issues on that.
Cheers


  1. 注意:我的答案中的 timedelta(1)
  2. 注意:我的答案中提到了关于 datetime.now() 的问题,以及为什么不应该使用它。
  3. Django 对应于我答案中最后一个代码示例,使用带时区的日期时间对象(简单情况)-- 确保 USE_TZ=True 并使用 timezone.now() 代替 datetime.now()
- jfs
2
当然,你的答案是100%正确和有价值的,我只是想指出在需要时使用total_seconds()。顺便说一下,我完全同意使用timezone.now() - Kostas Livieratos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接