2013-08-27 82 views
2

我有這樣的查詢:轉換日期時間爲UTC值MSSQL

SELECT table.a, table.b, table.c from Table table 

我怎麼能投「table.b」 UTC時間只需添加CAST到查詢?

SELECT 
    table.a, 
    **%CAST_TO_UTC_FUNCTION to table.b%**, 
    table.c 
from Table table 

我無法單獨投射它並聲明局部變量。

+0

[此答案](http://stackoverflow.com/a/4118416/390819)可help – GolfWolf

+0

'table.b'的原始數據類型是什麼? –

+0

@AdrianWragg(datetime,not null) –

回答

6

你可以寫你的查詢,如下所示:

SELECT 
    table.a, 
    dateAdd(
    second, 
    dateDiff(second, getDate(), getUtcDate()), 
    table.b) as b_converted_to_UTC, 
    table.c 
from Table table 

b列中的值轉換爲UTC,通過增加這些值,目前當地的日期(getDate())之間存在的tmie差和UTC日期(getUtcDate())。

爲了上面的查詢工作,必須滿足以下條件:

  • 存儲在b列中的日期(S)必須在當地時間
  • 服務器日期/時間段應表示正確配置
+2

這假定*當前*偏移量適用於所有數據。如果時區有夏時制,那麼這將無法持續工作。 –

+1

@MattJohnson是真的。我可以從我的經驗告訴你,最好避免在SQL中做時髦的時區翻譯。通常最好將日期存儲爲UTC,並在客戶端/表示層上轉換時區。 – GolfWolf

+0

是的 - 確切地說。 SQL不是這類事情的最佳地方。 –

1

我通過創建一個存儲日期範圍和當前UTC偏移量的臨時表來解決此問題。 下面是部分解決方案,適用於美國從2007年開始,適用於觀察DST的地區。 可以2007. 之前容易地修改以用於年請參閱溶液的端部爲一個示例用法

-- GET UTC for time in US for region that observe Daylight Saving Time (meaning will not work for part of Arizona and Hawaii) 
DECLARE 
    @DSTStartDay datetime = '2007-03-1 02:00:00', 
    @DSTEndDay datetime = '2007-11-1 02:00:00', 
    @i int = 0, 
    @currDate datetime, 
    @offset int 

DECLARE  
    @DST TABLE (StartDate datetime, EndDate datetime, DSTOffset int) 

-- Insert into @DST DSTOffset of 0 if not DST date range, and -1 if DST date as temporary offset value 
-- Then when we get Time Zone Offset, we can update DSTOffset to actual current offset (hours)   
WHILE @i < 20 
BEGIN 
    INSERT @DST  
    SELECT DATEADD(d, 
        15 - CASE DATEPART(dw, @DSTStartDay) 
         WHEN 1 THEN 8 
         ELSE DATEPART(dw, @DSTStartDay) 
         END, 
        @DSTStartDay), 
      DATEADD(d, 
        8 - CASE DATEPART(dw, @DSTEndDay) 
         WHEN 1 THEN 8 
         ELSE DATEPART(dw, @DSTEndDay) 
         END, 
         @DSTEndDay), 
      -1; 

     SET @DSTStartDay = DATEADD(yy,1,@DSTStartDay)  

    INSERT @DST  
    SELECT DATEADD(d, 
        8 - CASE DATEPART(dw, @DSTEndDay) 
         WHEN 1 THEN 8 
         ELSE DATEPART(dw, @DSTEndDay) 
         END, 
        @DSTEndDay), 
      DATEADD(d, 
        15 - CASE DATEPART(dw, @DSTStartDay) 
         WHEN 1 THEN 8 
         ELSE DATEPART(dw, @DSTStartDay) 
         END, 
        @DSTStartDay), 
      0;   

    SET @DSTEndDay = DATEADD(yy,1,@DSTEndDay)  

    SET @i = @i + 1 
END 

-- Get temporary offset for current date 
SET @currDate = GETDATE() 
SELECT @Offset = DSTOffset FROM @DST 
WHERE StartDate < @currDate AND EndDate >= @currDate 

-- Calculate Time Zone Offset (ignore DST) and update DSTOffset in @DST table from temporary to actual offset 
SET @Offset = DATEDIFF(hh, GETDATE(), GETUTCDATE()) - @Offset 
UPDATE @DST 
SET DSTOffset = DSTOffset + @Offset 

--SELECT * FROM @DST - look at the table 

--Sample usage 
DECLARE @myDateNoDST datetime = '2014-03-08 06:00', 
     @myDateWithDST datetime = '2014-03-09 06:00' 

SELECT @myDateNoDST LocalDateNoDST, 
     (SELECT DATEADD(hh,DSTOffset,@myDateNoDST) FROM @DST d WHERE StartDate < @myDateNoDST AND EndDate >= @myDateNoDST) UTCDateNoDST, 
     @myDateWithDST LocalDateWithDST, 
     (SELECT DATEADD(hh,DSTOffset,@myDateWithDST) FROM @DST d WHERE StartDate < @myDateWithDST AND EndDate >= @myDateWithDST) UTCDateWithDST