对于一家商店,我希望在当地时间为该商店存储开放和关闭时间。示例:
Shop1在8.00(t1)开盘,当地时间16.00(t2)关闭。 Shop1位于Europe / London(tz)。
Shop2在8.00开门,当地时间16.00关闭。 Shop2位于欧洲/哥本哈根。
问题:我如何在特定时间选择开放的商店?我需要考虑夏令时:在夏天的这个例子中,Shop1的开放时间是08:00 + 01:00,Shop2的开放时间是08:00 + 02:00,而冬天,这将是08: Shop1为00 + 00:00,Shop2为00:00 + 01:00。
将从包含许多行的表中进行选择,因此我需要将其编入索引。
使用Django + PostgreSQL。
答案 0 :(得分:1)
很酷的问题。继续Andomar's answer above,假设您正在使用"意外"处理几个时区。夏令时日期范围,一个选项将是:
将时区保存在CharField
,以及opens
中的closes
和TimeField
:
class Shop(models.Model):
tz = models.CharField(max_length=200)
opens = models.TimeField()
closes = models.TimeField()
Shop.objects.create(opens="8:00", closes="19:00", tz="Europe/Moscow")
Shop.objects.create(opens="8:00", closes="19:00", tz="Europe/Berlin")
Shop.objects.create(opens="8:00", closes="19:00", tz="UTC")
Shop.objects.create(opens="8:00", closes="19:00", tz="Asia/Jerusalem")
Shop.objects.create(opens="8:00", closes="19:00", tz="Europe/London")
Shop.objects.create(opens="8:00", closes="19:00", tz="Europe/Copenhagen")
计算"现在"作为UTC:
now_utc = "10:30"
使用RawSQL注释和过滤您的查询集:
qs = Shop.objects.annotate(is_open=RawSQL("(%s::time at time zone tz)::time between opens and closes", (now_utc,))).filter(is_open=True)
另一个解决方案是查询每个时区的数据库:
# pseudocode
for tz in all_timezones:
now_local = convert_to_timezone(now, tz) # beware - this might fail when DST is currently changing!
shops = Shop.objects.filter(tz=tz, opens__lte=now_local, closes__gte=now_local)
如果您index_together
字段(tz
,opens
,closes
),则查询应使用索引。但是,这并不意味着您的查询会更快。
请记住,您必须在两个记录中保持午夜的开放时间" 22:00" - " 00:00"和" 00:00" - " 03:00"而不是" 22:00" - " 03:00"。
答案 1 :(得分:0)
Postgres支持使用at time zone
语法将时间转换为本地时间。例如,要查找新西兰的当前时间:
select (current_timestamp at time zone 'NZDT')::time;
您可以使用它来选择在10:00开放的商店:
where ('10:00'::time at time zone time_zone)::time
between opens and closes
其中time_zone
是商店的时区,opens
开启时间,closes
关闭时间。 Full example at regtester.com.