繁体   English   中英

getmtime() 与 datetime.now():

[英]getmtime() vs datetime.now():

此代码每年在时钟转换的晚上(欧洲中部夏令时间到欧洲中部时间)打印一次错误警告:

import os
import datetime

now = datetime.datetime.now()
age = now - datetime.datetime.fromtimestamp(os.path.getmtime(file_name))
if (age.seconds + age.days * 24 * 3600) < -180:
    print('WARN: file has timestap from future?: %s' % age)

即使在每年一小时的时钟轮班期间,如何使此代码工作?

更新

我只关心年龄,而不关心日期时间。

通过从本地时间切换到 UTC 时间,可以轻松改进发布的片段。 UTC 没有夏季(夏令时)时间变化。 只需替换这两个日期时间函数now() -> utcnow() ( docs ) 和fromtimestamp() -> utcfromtimestamp() ( docs )。

但是,如果唯一预期的 output 是以秒为单位的文件年龄,我们可以直接使用时间戳(距“纪元”的秒数)而无需任何转换:

import time
import os.path

...
age = time.time() - os.path.getmtime(file_name)

您的两个日期时间对象都是“天真的”,这意味着他们不知道 DST。 datetime.now()返回您的机器运行的当前时间,其中可能包括 DST。 datetime.fromtimestamp(os.path.getmtime())也是如此。

#1 -本地化您的日期时间对象可能是一种选择; 就像是

from datetime import datetime
import tzlocal
now_aware = tzlocal.get_localzone().localize(datetime.now())
file_mtime = datetime.fromtimestamp(os.path.getmtime(file))
# assuming the file was created on a machine in the same timezone (!):
file_mtime_aware = now_aware.tzinfo.localize(file_mtime)
age = now_aware - file_mtime_aware

#2 -另一种选择,使用 UTC 转换和datetime

now = datetime.utcnow()
age = now - datetime.utcfromtimestamp(os.path.getmtime(file_name))
if (age.seconds + age.days * 24 * 3600) < -180:
    print(f'WARN: file has timestamp from future?: {age} s')

#3 -正如VPfB在他的回答中指出的那样, os.path.getmtime返回一个 UTC 时间戳(检查os module docstime module docs )。 因此,最简单的解决方案可能是首先跳过转换为datetime并仅使用 UTC 时间戳; 例如,将当前的 UTC 时间戳记为time.time()

使用时区可能会让你发疯......但是那里有一些很好的资源,例如这个 medium post

您的问题是您在不了解时区的情况下获得时间。 因此,当时钟更改时,您将结束比较时钟更改之前的一个时间戳和时钟更改之后的另一个时间戳,而您的代码看不到这一点。

相反,您应该让您的 datetime 对象基于特定的时区,这样您就不会遇到时钟变化的问题,我建议使用 pytz 模块来帮助您解决这个问题。 您可以在此答案中看到可用时区列表: Is there a list of Pytz Timezones?

这是一个简单的代码示例,说明如何使用时区感知对象执行此操作:

import os
from datetime import datetime
import pytz


def get_datetime_now(timezone):
    """
    Returns timezone aware datetime object for right now
    """
    if timezone not in pytz.all_timezones:
        return None
    tz = pytz.timezone(timezone)
    dt = datetime.now().astimezone()
    return dt.astimezone(tz)


def timestamp_to_datetime(timestamp, timezone):
    """
    Returns a datetime object from a timestamp
    """
    if timezone not in pytz.all_timezones:
        return None
    tz = pytz.timezone(timezone)
    dt = datetime.fromtimestamp(timestamp).astimezone()
    return dt.astimezone(tz)


timezone = 'CET'

file_timestamp = os.path.getmtime(file_name)

now = get_datetime_now(timezone)
file_datetime = timestamp_to_datetime(file_timestamp, timezone)
age = now - file_datetime

if (age.seconds + age.days * 24 * 3600) < -180:
    print('WARN: file has timestap from future?: %s' % age)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM