2

我有这些模型:

class Interval(models.Model):
    from_time = models.TimeField(auto_now_add=False)
    to_time = models.TimeField(auto_now_add=False)

class CheckIn(models.Model):
    date_time = models.DateTimeField(auto_now_add=True)
    interval = models.ForeignKey(Interval, on_delete=models.SET_NULL)

主要目标是:

创建a 时CheckIn,代码应检查它是否在给定的时间间隔内。我需要比较这两者并返回它们的%H:%M:%S格式差异。

到目前为止我所做的:

CheckIn由于在保存之前我有不同的场景如何处理给定的内容,因此我正在使用pre_save信号并且时间比较是这些场景的一部分。这是一个伪:

@receiver(pre_save, sender=CheckIn)
def set_action_state(sender, instance, **kwargs):
    if something:
       ...
       if another:
          ...
       else:
          ...
    else:
        # instance.date_time.time() is 13:56:56.568860 (2 hours behind, it should be 15 instead of 13)
        # instance.interval.from_time is 15:07:40
        if instance.date_time.time() < instance.interval.from_time:
            # this returns True when it's meant to return False

instance.date_time是一个时区感知日期,因为我可以打印它tzinfo返回UTC而不是 Europe/SofiaTIME_ZONE的设置,我不知道为什么。

所以我手动尝试通过以下方式设置它tz

tz = pytz.timezone('Europe/Sofia')
dt1 = instance.date_time.replace(tzinfo=tz)
print(dt1.tzinfo) # which is the correct Europe/Sofia
print(dt1) # which is 13:56:56.568860, again 2 hours behind even with different timezone.

我尝试的第二件事是转换instance.interval.from_time为有意识的日期时间,然后比较两个日期time()

def time_to_datetime(date, time):
    return make_aware(datetime.datetime.combine(date, time))

dt2 = time_to_datetime(dt1.date(), instance.interval.from_time)
print(dt2.tzinfo) #this returns 'Europe/Sofia'
print(dt2) #this is 15:07:40

现在两者dt1dt2知道,但比较它们仍然没有运气。这是完整的代码:

tz = pytz.timezone('Europe/Sofia')
dt1 = instance.date_time.replace(tzinfo=tz)
dt2 = time_to_datetime(dt1.date(), instance.interval.from_time)
print(dt1.time() < dt2.time()) # this is True
print(dt1.tzinfo) # 'Europe/Sofia'
print(dt2.tzinfo) # 'Europe/Sofia'
print(dt1.time()) # 13:56:56.568860
print(dt1.time()) # 15:07:40

dt1即使两个日期时间都知道正确的时区,我如何才能获得正确的时间并使这种比较正常工作?

编辑:我有USE_TZ = True我的设置。

4

2 回答 2

1

Django 对 Python 代码中的日期时间的时区不做任何保证。这是因为 1) 时区主要与用户交互相关(这就是activate()影响表单和模板的原因)和 2) Python 比较操作是时区感知的,因此特定时区不会影响结果。

当然,一个不支持时区的操作是从日期时间中提取时间并将其与另一个时间进行比较。因此,您必须手动将日期时间转换为正确的时区。你有正确的想法,但replace()做的方式不对。(而不是仅仅转换到另一个时区,它改变了实际的时间。)

相反,请执行以下操作:

from django.utils.timezone import localtime

if localtime(instance.date_time).time() < instance.interval.from_time:
    pass
于 2019-01-18T22:37:15.327 回答
0

我做了一些谷歌搜索,发现 django 打算始终以UTC格式保存在模型中,但在从 db 检索期间转换为设置设置的 TIME_ZONE。链接。所以我想UTC在预保存实例中它的格式有可能。我可能是错的,因为我对此没有具体的深入了解。

我认为这种比较需要实时进行。因此,现在使用用户 TIME_ZONE 与间隔 from_time 进行比较是非常安全的。所以我的建议

import pytz
import datetime


tz = pytz.timezone('Europe/Sofia')
curtime = tz.localize(datetime.datetime.now())

并转换这行代码

  if instance.date_time.time() < instance.interval.from_time:
            # this returns True when it's meant to return False

   if curtime < instance.interval.from_time:
            # I hope this return False now
于 2019-01-18T16:14:01.983 回答