2011-09-26 30 views
2

我有一個數據庫(SQL Server 2005,但我認爲我的問題更一般)與GMT時間戳事件。出於多種原因,我需要能夠根據用戶的當地時間查詢和彙總數據。例如,當地時間下午五點到七點之間發生了多少事件? DST真的讓我在這一個循環上投擲。當地時間查詢事件

我想過試圖維護所有時區/ dst規則的表。然後,我可以加入我的活動表格,將結果限制爲用戶的時區/ dst信息。因此,對於我的例子查詢看起來是這樣的:

select count(e.ID) 
from events e 
    join dst d on e.timeGMT between d.startGMT and d.endGMT 
where [email protected] 
    and dbo.getTime(dateadd(ss, d.offsetSec, e.timeGMT)) between '17:00' and '19:00' 

這DST表似乎將更有可能成爲一個維護的噩夢。那麼,任何人都有更好的選擇?

UPDATE 嗯,好像是對我的問題有些混亂,所以我將提供一些示例數據...

首先,請注意,DST在美國02:00本地時間結束11月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. 我解析時區信息數據庫(亦稱區信息,IANA時區或奧爾森數據庫,可here),輸出所有GMT的列表偏移的變化,爲我擔心歲月的所有區域。
  2. 將列表插入臨時表中。
  3. 使用臨時表爲每個GMT的每個區域建立時間範圍。

回答

0

嘛,只是一個小想法,你可能要考慮:

而是在查詢過程中你的錶轉換(S)的數據,則可以反向邏輯,而是轉換用戶的本地時間範圍參數格林威治標準時間,然後在格林威治標準時間做一切如果您希望返回當地時間的結果,那麼您可以在該點再次進行轉換。

這是否是有效的解決方案取決於您的查詢的性質。

+0

雖然我一般同意你的觀點,我覺得你在這裏失蹤了問題的關鍵所在。你如何處理多個DST班次?要求用戶在DST開始/結束時記得嗎? – chezy525

0

在這種情況下,如果我們從前面調用此過程,我們通常會在當前GMT時間內傳遞,對於.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

這仍然錯過了在多個DST班次的本地時間查詢事件。 – chezy525

+0

在上述情況下,由於您需要在當地時間下午5點和7點之間的事件,我會將這些時間從前端轉換爲相應的gmt時間,然後將其傳遞給過程。 所以在數據庫中,你只需要檢查它是否在這些gmt時間之間 –

+0

我的第一個評論依然存在。如果事件具有跨越一個或多個DST移位的完整日期時間值,則每個對應的DST移位都需要存在GMT調整。這不包括這種情況。 – chezy525