无法比较naive和aware的datetime.now() <= challenge.datetime_end

358 投票
16 回答
432195 浏览
提问于 2025-04-17 18:29

我正在尝试用比较运算符来比较当前的日期和时间与模型中指定的日期和时间:

if challenge.datetime_start <= datetime.now() <= challenge.datetime_end:

但是脚本出错了,错误信息是:

TypeError: can't compare offset-naive and offset-aware datetimes

模型的样子是这样的:

class Fundraising_Challenge(models.Model):
    name = models.CharField(max_length=100)
    datetime_start = models.DateTimeField()
    datetime_end = models.DateTimeField()

我还在使用django,它会使用本地的日期和时间。

我一直找不到django对于DateTimeField()使用的格式。它是“天真”的还是“有意识”的?我该如何让datetime.now()识别本地的日期和时间呢?

16 个回答

136

一行代码解决方案

if timezone_aware_var <= datetime.datetime.now(timezone_aware_var.tzinfo):
    pass #some code

解释版本

# Timezone info of your timezone aware variable
timezone = your_timezone_aware_variable.tzinfo

# Current datetime for the timezone of your variable
now_in_timezone = datetime.datetime.now(timezone)

# Now you can do a fair comparison, both datetime variables have the same time zone
if your_timezone_aware_variable <= now_in_timezone:
    pass #some code

总结

你需要给你的 now() 时间加上时区信息。
不过,你必须加上和参考变量相同的时区,这就是我为什么先读取 tzinfo 属性的原因。

172

datetime.datetime.now 这个函数获取的时间是没有时区信息的。

Django 提供了一个工具来处理这个问题,但需要用到 pytz 这个库。

from django.utils import timezone
now = timezone.now()

你应该可以把 nowchallenge.datetime_start 进行比较。

314

在Python中,默认情况下,datetime对象是naive的,也就是说它不包含时区信息。因此,你需要确保两个datetime对象要么都是naive的,要么都是带有时区信息的aware对象。你可以通过以下方式来做到这一点:

import datetime
import pytz

utc=pytz.UTC

challenge.datetime_start = utc.localize(challenge.datetime_start) 
challenge.datetime_end = utc.localize(challenge.datetime_end) 
# now both the datetime objects are aware, and you can compare them

注意:如果tzinfo已经设置了,这样做会引发一个ValueError错误。如果你不确定这一点,可以直接使用

start_time = challenge.datetime_start.replace(tzinfo=utc)
end_time = challenge.datetime_end.replace(tzinfo=utc)

顺便提一下,你可以用以下方法将UNIX时间戳格式化为带有时区信息的datetime.datetime对象

d = datetime.datetime.utcfromtimestamp(int(unix_timestamp))
d_with_tz = datetime.datetime(
    year=d.year,
    month=d.month,
    day=d.day,
    hour=d.hour,
    minute=d.minute,
    second=d.second,
    tzinfo=pytz.UTC)

撰写回答