2017-02-14 3 views
0

Для магазина, я хотел бы открыть время открытия и закрытия магазина по местному времени для данного магазина. Пример:Местное время запроса

Магазин1 открывается в 8.00 (t1) и закрывается в 16.00 (t2) по местному времени. Shop1 находится в Европе/Лондоне (tz).

Магазин2 открывается в 8.00 и закрывается в 16.00 по местному времени. Shop2 находится в Европе/Копенгагене.

Вопрос: Как я могу в определенный момент выбрать магазины, которые открыты? Мне нужно принять во внимание DST: в этом примере летом время открытия Shop1 будет 08: 00 + 01: 00, время открытия Shop2 будет 08: 00 + 02: 00, а зимой это будет 08: 00 + 00: 00 для Shop1 и 08: 00 + 01: 00 для Shop2.

Будет выбран из таблицы со многими строками, поэтому мне нужно, чтобы это было проиндексировано.

Использование Django + PostgreSQL.

ответ

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.

+0

Это очень здорово. Я пытался что-то сделать, но не мог понять, как это сделать. Любое понимание стоимости расчета местного времени?Какие индексы мне нужно добавить, чтобы это быстро выполнялось для ~ 1 миллиона строк? – toucan

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" 
    
  • Комментируйте и отфильтровать ваш QuerySet с 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» "-" 3:00" .

Смежные вопросы