我有以下查询,它将今天的午夜值(UTC)计算为日期时间:
SELECT CONVERT(DATE,GETDATE())+(GETDATE()-GETUTCDATE())
结果:2011-11-03 19:00:00.000
(2011年11月4日GMT-5)
不仅如此,有时还会返回以下值:
2011-11-03 19:00:00.003
2011-11-03 19:00:00.007
2011-11-03 19:00:00.010
......,这是错误的!
必须有更好的方法来做到这一点。
答案 0 :(得分:3)
我已经使用DATEADD和DATEDIFF与GETDATE()和GETUTCDATE()解决了这个问题,类似于原始问题中给出的示例,但从那时起我发现了datetimeoffset数据类型{{ 3}}。这会存储日期时间以及时区偏移量。
如何使用此类型取决于您是否要更改现有数据的数据类型。如果您不想更改任何内容,以下语句将返回当地时间午夜的日期时间类型:
SELECT CONVERT(datetime, SWITCHOFFSET(CONVERT(datetimeoffset,
CONVERT(date, GETDATE())),
DATENAME(TzOffset, SYSDATETIMEOFFSET())))
您还可以使用以下方式将任何UTC时间转换为本地时间:
SELECT CONVERT(datetime, SWITCHOFFSET(CONVERT(datetimeoffset,
@myutctime,
DATENAME(TzOffset, SYSDATETIMEOFFSET())))
datetimeoffset类型仅适用于SQL2008及更高版本。如果您需要使用2005及以下版本执行此操作,您可以使用类似于原始问题中的解决方案,但更改为考虑到GETDATE() - GETUTCDATE()
不是原子操作并且可能涉及毫秒差异的事实在两者执行之间。
SELECT DATEADD(minute,
DATEDIFF(minute, GETUTCDATE(), GETDATE()),
CONVERT(datetime, CONVERT(date, GETDATE())))
这将花费GETDATE()
和GETUTCDATE()
之间的分钟数,并将它们添加到当地的午夜时间。不幸的是,您必须从日期转换回日期时间,因为如果您给它一个日期,DATEADD
将无法使用分钟。我建议将其包装到用户定义的函数中,使其看起来不那么冗长,例如。
CREATE FUNCTION dbo.MidnightASUTC(@dt as datetime)
RETURNS datetime
AS
BEGIN
RETURN DATEADD(minute,
DATEDIFF(minute, GETUTCDATE(), GETDATE()),
CONVERT(datetime, CONVERT(date, @dt)))
END
SELECT dbo.MidnightAsUTC(GETDATE())
答案 1 :(得分:0)
对于您所描述的特定场景(“今天的午夜值(UTC)作为日期时间”),程序化方法很有意义,但如果您需要将其扩展到另一个问题(午夜是什么时候)这个夏天的UTC?),您可能想要使用日历表(以解决夏令时等问题)。