【问题标题】:Query local time查询当地时间
【发布时间】:2017-02-14 16:09:52
【问题描述】:

对于一家商店,我想要该商店在当地时间的开店和关店时间。示例:

Shop1 于当地时间 8:00 (t1) 营业,并于当地时间 16:00 (t2) 关闭。 Shop1 位于欧洲/伦敦 (tz)。

Shop2 于当地时间 8 点开门,16 点关门。 Shop2 位于欧洲/哥本哈根。

问题:我如何在特定时间选择营业的商店?我需要考虑 DST:在这个例子中,夏季的 Shop1 开放时间为 08:00+01:00,Shop2 的开放时间为 08:00+02:00,而冬季则为 08: Shop1 为 00+00:00,Shop2 为 08:00+01:00。

将从包含许多行的表中进行选择,因此我需要对其进行索引。

使用 Django + PostgreSQL。

【问题讨论】:

    标签: django postgresql timezone


    【解决方案1】:

    很酷的问题。继续Andomar's answer above,假设您正在处理一些具有“意外”夏令时日期范围的时区,一种选择是:

    • 将时区保存在CharField 中,将openscloses 保存在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 字段(tzopenscloses),则查询应使用索引。但是,这并不意味着您的查询会更快。

    请记住,您必须将午夜前后的营业时间保留在“22:00”-“00:00”和“00:00”-“03:00”这两条记录中,而不是“22:00” -“03:00”。

    【讨论】:

      【解决方案2】:

      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.

      【讨论】:

      • 这很酷。我正在尝试一些事情,但无法弄清楚如何使这项工作。对本地时间计算的成本有任何见解吗?我需要添加哪些索引才能使其快速执行约 100 万行?
      猜你喜欢
      • 2011-11-25
      • 1970-01-01
      • 2011-01-16
      • 1970-01-01
      • 2021-05-14
      • 1970-01-01
      • 2017-11-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多