Запрос событий по местному времени - PullRequest
2 голосов
/ 26 сентября 2011

У меня есть база данных (SQL Server 2005, но я думаю, что мой вопрос более общий) с событиями с меткой времени по Гринвичу.По ряду причин мне нужно иметь возможность запрашивать и агрегировать данные на основе местного времени пользователя.Например, сколько событий произошло между 17:00 и 19:00 по местному времени?DST действительно заставляет меня зацикливаться на этом.

Я думал о попытке сохранить таблицу всех правил часовых поясов / dst.Затем я мог бы присоединить к этому свою таблицу событий, ограничив результаты информацией о часовом поясе / dst для пользователя.Таким образом, запрос для моего примера будет выглядеть примерно так:

select count(e.ID)
from events e
  join dst d on e.timeGMT between d.startGMT and d.endGMT
where d.region=@userRegion
  and dbo.getTime(dateadd(ss, d.offsetSec, e.timeGMT)) between '17:00' and '19:00'

Эта таблица dst выглядит так, как будто она скорее всего станет кошмаром обслуживания.Итак, у кого-нибудь есть лучший вариант?

ОБНОВЛЕНИЕ Что ж, похоже, возникла путаница в моем вопросе, поэтому я предоставлю некоторые примеры данных ...

Во-первых, обратите внимание, что летнее время заканчивается в США в 02:00 по местному времени в воскресенье, 6 ноября.

Учитывая следующую таблицу событий

create table events(ID int, timeGMT datetime)

insert into events(ID, timeGMT)
select  1, '2011-11-04 20:00' union --16:00 EDT
select  2, '2011-11-04 20:15' union --16:15 EDT
select  3, '2011-11-04 20:30' union --16:30 EDT
select  4, '2011-11-04 20:45' union --16:45 EDT
select  5, '2011-11-04 21:00' union --17:00 EDT
select  6, '2011-11-04 21:15' union --17:15 EDT
select  7, '2011-11-04 21:30' union --17:30 EDT
select  8, '2011-11-04 21:45' union --17:45 EDT
select  9, '2011-11-04 22:00' union --18:00 EDT
select 10, '2011-11-04 22:15' union --18:15 EDT
select 11, '2011-11-04 22:30' union --18:30 EDT
select 12, '2011-11-04 22:45' union --18:45 EDT
select 13, '2011-11-04 23:00' union --19:00 EDT
select 14, '2011-11-06 20:00' union --15:00 EST
select 15, '2011-11-06 20:15' union --15:15 EST
select 16, '2011-11-06 20:30' union --15:30 EST
select 17, '2011-11-06 20:45' union --15:45 EST
select 18, '2011-11-06 21:00' union --16:00 EST
select 19, '2011-11-06 21:15' union --16:15 EST
select 20, '2011-11-06 21:30' union --16:30 EST
select 21, '2011-11-06 21:45' union --16:45 EST
select 22, '2011-11-06 22:00' union --17:00 EST
select 23, '2011-11-06 22:15' union --17:15 EST
select 24, '2011-11-06 22:30' union --17:30 EST
select 25, '2011-11-06 22:45' union --17:45 EST
select 26, '2011-11-06 23:00'       --18:00 EST

Я ищу хорошийСпособ получения следующих результатов.Предполагая местное время начала 17:00, местное время окончания 18:00 и местный часовой пояс США-Пасха, все предоставлено.

 ID | timeGMT
----|------------------
  5 | 2011-11-04 21:00
  6 | 2011-11-04 21:15
  7 | 2011-11-04 21:30
  8 | 2011-11-04 21:45
  9 | 2011-11-04 22:00
 22 | 2011-11-06 22:00
 23 | 2011-11-06 22:15
 24 | 2011-11-06 22:30
 25 | 2011-11-06 22:45
 26 | 2011-11-06 23:00

Я также хочу, чтобы это работало для любого реального набораправил DST и всех часовых поясов.Включая тот факт, что реальный набор данных охватывает несколько лет, и, следовательно, несколько сдвигов DST.

ОБНОВЛЕНИЕ 2 Я в основном реализовал решение, которое я первоначально обрисовал, но я также создал некоторыекод для существенного сокращения необходимых операций обслуживания.

  1. Я анализирую базу данных tz (она же. zoneinfo, часовой пояс IANA или базу данных Olson, доступна здесь ), выводя списоквсе смещения по Гринвичу, для всех зон за годы, о которых мне нужно беспокоиться.
  2. Вставьте список в временную таблицу.
  3. Используйте временную таблицу для построения временных диапазонов для каждой зоны для каждойСмещение по Гринвичу:

Ответы [ 2 ]

0 голосов
/ 31 октября 2011

В таких ситуациях, если мы вызываем эту процедуру с начала, мы обычно передаем текущее время по Гринвичу, в случае .net мы используем System.DateTime.UtcNow, а затем сравниваем данные, используя этот подход, мы не делаемнеобходимо выполнить преобразование даты и времени на сервере sql.

Отредактировано:

    declare @table table(eventName Varchar(50), [time] time)
    insert into @table(eventName, [time]) Values ('event 1', '03:30')
    insert into @table(eventName, [time]) Values ('event 1', '04:00')
    insert into @table(eventName, [time]) Values ('event 2', '04:20')
    insert into @table(eventName, [time]) Values ('event 3', '05:20')
    insert into @table(eventName, [time]) Values ('event 3', '07:20')

    select * from @table

    -- assuming ur local time is +1 GMT
    declare 
        @timeFromLocal time = '05:00',
        @timeToLocal time = '07:00',
        @timeFromGMT time,
        @timeToGMT time,
        @Offset int = -1

    /*I prefer doing the following conversion from the front end where the time reflects the users time zone*/
    set @timeFromGMT = DATEADD(Hour, @Offset, @timeFromLocal)
    set @timeToGMT = DATEADD(Hour, @Offset, @timeToLocal)

    select * from @table Where [time] between @timeFromGMT and @timeToGMT
0 голосов
/ 26 сентября 2011

Ну, просто небольшая идея, которую вы можете рассмотреть:

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

Будет ли это эффективное решение или нет, будет зависеть от характера ваших запросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...