2011-05-19 150 views
10

我有一個插入過程作爲其中一個值通過GETDATE(),因爲每個插入插入時也存儲。這是託管在使用GMT的SQL Azure上。如何將GMT(UTC)datetime轉換爲本地日期時間?

現在,當我收到消息時,我在他們的時間戳列中爲每個人存儲了GMT日期,如何將此日期轉換爲當地的datetime,無論您身處何處?

謝謝。

+2

做了服務器時間的變化?你可以檢查一下嗎? – 2011-05-19 20:46:14

+0

嗯,它在SQL Azure上運行。我將如何檢查? – slandau 2011-05-19 20:46:41

+0

你不能簡單地做一個「SELECT GETDATE()GO」,看看它是否符合你的期望? – Mat 2011-05-19 20:48:32

回答

10

你可以做這樣的事情:

declare @InputUtcDateTime datetime2 = '2011-05-20 06:30:18' 

declare @LocalDateTime datetime2 = dateadd(minute, datepart(TZoffset, sysdatetimeoffset()), @InputUtcDateTime) 
print @LocalDateTime 

declare @InputUtcDateTime datetime2 = '2011-05-20 06:30:18' 

declare @LocalDateTime datetime2 = dateadd(minute, datediff(minute, sysutcdatetime(), sysdatetime()), @InputUtcDateTime) 
print @LocalDateTime 
+28

這兩個都是不正確的。它們依賴於假設當前本地時區的偏移量與輸入UTC日期引用的本地時區偏移量相同。 由於本地時區可能會受到DST的影響,因此過去的偏移量可能會與當前不同。 – wasabi 2012-05-24 22:27:26

+3

@wasabi +1 - 你對這種方法的侷限性是正確的。但我不同意這是不正確的。這取決於你想要達到的目標。 – 2012-05-25 21:13:27

+6

在給定任意輸入時間的情況下,試圖獲得當地時區的正確時間? – wasabi 2012-06-26 18:00:17

1

對於MST作爲一個例子......考慮到每個DTM被存儲在格林尼治標準時間已經,它簡化了的東西..

SWITCHOFFSET(CONVERT(DATETIMEOFFSET, [ColumnName]), '-07:00') 

現在,如果您的本地日期/時間不是GMT/UTC,您可能需要使用以下...

SWITCHOFFSET(TODATETIMEOFFSET([ColumnName], datepart(tz,sysdatetimeoffset())),'+00:00') 

下面是故障。

  • SWITCHOFFSET - 將DateTimeOffset值轉換爲不同的時區,同時保留偏移量。
  • TODATETIMEOFFSET - 將DateTime值轉換爲指定時區的DateTimeOffset值。
  • DATEPART - 在這種情況下獲取本地日期時間的時區部分。
  • '+00:00' - 目標偏移量,在第二個示例中是UTC/GMT目標,從本地...前一個示例是MST。

注意/警告:我不相信這會佔用夏令時,這可能是您的問題。如果絕對保存不是必需的,您可能只需添加一個輔助列,並進行粗略轉換並安全地前進。

您可能想將邏輯抽象爲一個函數調用,以便說明DST的保留情況......但這不應該太過困難。

0

這是一個對歷史數據有效的函數。我寫了英國夏令時 - 不幸的是發生在三月和十月的最後一個星期天,使得邏輯有點複雜。

基本上硬編碼的日期部分01/03正在尋找3月份的最後一個星期日,而01/10正在尋找10月份的最後一個星期日(這是時鐘前進和返回的時間)。注意:如果您的服務器正在使用美國的日期,請將這兩個日期部分反轉到03/01和10/01 !!!!

所以你給它一個UTC日期,它會自動判斷一個歷史日期是BST還是GMT。在大數據集上使用並不是最好的選擇,但它是一個解決方案。

運行此腳本以創建該函數並在您的選擇中調用它內聯。SQL 2008對用戶定義的函數有一個問題,看起來,它在代碼下放置了一條紅線,但只要您使用dbo前綴(SELECT dbo.UTCConvert(yourdate)來運行它),它仍然運行它。

CREATE FUNCTION [dbo].[UTCConvert] 
(

    @p1 datetime 
) 
RETURNS datetime 
AS 
BEGIN 

    DECLARE @Result datetime 


RETURN CASE 
WHEN 
@p1 > 
(DATEADD(day,DATEDIFF(day,'19000107',DATEADD(month,DATEDIFF(MONTH,0,'01/03/' + CAST(DATEPART(year,@p1) as CHAR)),30))/7*7,'19000107')) 
AND 
@p1< 
(DATEADD(day,DATEDIFF(day,'19000107',DATEADD(month,DATEDIFF(MONTH,0,'01/10/' + CAST(DATEPART(year,@p1) as CHAR)),30))/7*7,'19000107')) 
THEN (DATEADD(HH, 1, @p1)) 
ELSE @p1 
END 
END 
+0

如果您的服務器使用原生美國日期,因爲它位於美國,那麼您很可能會遇到更嚴重的問題。如果你正在看這個問題,可能性很大,你至少要在夏令時適用的一個地方存儲日期。這意味着至少你必須擔心在換班日期2007年的變化。您可能不得不擔心多個時區,可能是亞利桑那州,甚至可能是納瓦霍族。您真的想要在SQL Server中存儲UTC或datetimeoffset,並在業務層中進行日期數學計算。 – MattW 2015-10-13 20:44:36

5

除了夏令問題,爲什麼不簡化與:

yourDateTime - getutcdate() + getdate() 
相關問題