带有 UTC 支持/时区问题的 Django 开放时间
Posted
技术标签:
【中文标题】带有 UTC 支持/时区问题的 Django 开放时间【英文标题】:Django Opening Hours With UTC Support/Timezone Issue 【发布时间】:2021-04-10 17:09:50 【问题描述】:我有一个 Django 应用程序,用户可以在其中设置商店。我最近添加了支持开放时间的功能,遵循此线程上的建议 - Business Opening hours in Django。我的模型如下所示:
class LocationHours(SafeDeleteModel):
location = models.ForeignKey(Location, related_name="hours", on_delete=models.CASCADE)
weekday = models.IntegerField(choices=WEEKDAYS, blank=False, null=False)
start_time = models.TimeField(blank=False, null=False, help_text="Opening time (00:00 format)")
end_time = models.TimeField(blank=False, null=False, help_text="Closing time (00:00 format)")
class Meta:
ordering = ('weekday', 'start_time')
unique_together = ('location', 'weekday', 'start_time', 'end_time')
verbose_name_plural = "Location hours"
流程是这样的 - 这些时间由最终用户以表格形式输入,因此假定为本地时间,我的应用程序中使用的大多数日期时间/时间都是 UTC。我最初需要经常比较这两者,我想我可以找出每个位置对象的时区,然后每当我将某些东西与这些 OpenHours 进行比较时,我就可以使用给定的时间和 tz(在关联的 Location 对象上)计算 UTC 时间,然后它只是一个常规的日期时间比较。
我编写了以下函数来尝试解决这个问题:
def is_dt_within_location_hours(location, dt):
# see if time falls within hours
hours = location.hours
if hours.count() > 0:
for hour in hours.all():
dt = dt.astimezone(hour.location.timezone)
if dt.weekday() == hour.weekday:
if hour.start_time < dt.time() < hour.end_time:
return True
return False
else: # this location has no hours
return True
我认为这可行,但有一些问题。
主要问题是 - 当最初制作或编辑 Location 对象时,我查找它所在的时区(使用 timezonefinder 包)并将其存储在 Location
对象中(使用 TimeZoneField
)那时。也就是说,据我所知,它不会自动更新 DST 或类似的东西。每次调用上述函数时,我都可以计算出时区,但是我将所述函数调用了很多,因此从资源方面来说,我想说这不是一个选项。
我想我可以找到一种方法来找出本地时间在他们创建一个 OpeningHours 对象的那一刻,这样我就可以转换为 UTC 并保存它,但我不知道这样做的好方法。
我现在在想,我可能需要放弃我的整个解决方案并从头开始,但任何建议都非常有帮助,我已经为此苦苦挣扎了一段时间。
【问题讨论】:
【参考方案1】:你做对了。
您担心在记录 Location
和进行计算之间时区偏移量会发生变化(与 DST 一样)。但是时区(由“美国/芝加哥”之类的名称表示)不仅仅是一个偏移量,它是一组用于计算历史上任何时间点的本地时间的规则。因此,无论您何时记录时区名称,它都会做正确的事情。
关于您发布的代码的其他一些注释:
您可能想让LocationHours
仅在location
和weekeday
上独一无二,除非您故意尝试在同一工作日允许同一地点的多个营业时间。
您的is_dt_within_location_hours()
效率很低。您无需每次都获取所有 LocationHours
对象并重新计算工作日。相反,首先计算本地时间,然后过滤 location.hours
以仅包含该工作日的 LocationHours
对象。
【讨论】:
以上是关于带有 UTC 支持/时区问题的 Django 开放时间的主要内容,如果未能解决你的问题,请参考以下文章
查询 Django 模型时,如何将 Django 中的 DateTimeField 从 UTC 转换为最终用户的时区(通常是 PST)?