Отправка ежечасных уведомлений пользователям с учетом таймзоны

Всем привет! пишу небольшой проект, и хочу встроить туда ежечасную отправку уведомлений пользователям в заданных им границах и с учетом введенной временной зоны. В качестве базы используется Postgres, в качестве бэкенда golang. Пользователь вводит свою временную зону в формате числа, она сохраняется в базу(с умножением на -1, иначе работает некорректно) в текстовую ячейку(тут можно число преобразовывать в что-то вроде Europe/Berlin, но это не принципиально на мой взгляд). после этого пользователь вводит начало и конец временного промежутка в своем часовом поясе, в который он хочет получать уведомления(ввести необходимо только часы), все это сохраняется в базу. каждый час запускается ждоба, которая выбирает всех пользователей, которым нужно отправить уведомление. схема базы и запрос прилагаю:

users
+----+----+-------+-----+
| id | tz | start | end |
+----+----+-------+-----+
|  1 | -3 |    10 |  20 |
|  2 |  5 |     8 |  22 |
+----+----+-------+-----+
select * from users where start <= (select date_part('hour', (select (NOW() AT TIME zone "tz") from users))) and 
end >= (select date_part('hour', (select (NOW() AT TIME zone "tz") from users)))

это работает, но выглядит довольно громоздко. может быть есть вариант сделать запрос аккуратнее или изначально иначе организовать хранение данных? буду рад любым идеям и предложениям!


Ответы (1 шт):

Автор решения: Alexander Pavlov

Если ты сделаешь хранение Europe/Berlin, то это автоматически решит проблему нецелых смещений и летнего времени.

create table tbl (
  tz text,
  start_h int,
  end_h int
);

insert into tbl (tz, start_h, end_h)
  values ('America/Los_Angeles', 8, 16);
insert into tbl (tz, start_h, end_h)
  values ('Europe/Berlin', 8, 16);


with current_hour as (
  SELECT 
    name tz, 
    date_part('hour', now() at time zone name) as h 
  FROM 
    pg_timezone_names
)
select 
    *
from 
   tbl 
   inner join current_hour using (tz)
where 
   current_hour.h between start_h and end_h

Причём список поддерживаемых таймзон прямо у Постгриса можно взять

select * FROM pg_timezone_names
→ Ссылка