我已经提供了一个使用DATEADD和DATEDIFF与GETDATE()和GETUTCDATE()解决方案的答案,类似于原问题中给出的示例,但自那以后我发现
datetimeoffset数据类型
在SQL Server 2008中添加。它存储带有时区偏移量的日期时间。
如何使用此类型取决于您是否要更改现有数据的数据类型。如果您不想更改任何内容,则以下语句将返回具有午夜本地时间的日期时间类型:
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())
DATEDIFF(hour, GETUTCDATE(), GETDATE())
,以获得正确的结果。但是我尝试运行了大约100次,至少得到了正确的时间。 - Michael Goldshteyn