2011-05-19 254 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() 
相关问题