我已经通过使用 DATEADD 和 DATEDIFF 以及 GETDATE() 和 GETUTCDATE() 的解决方案回答了这个问题,类似于原始问题中给出的示例,但从那时起我发现了 datetimeoffset 数据类型 added in SQL Server 2008。这会存储一个日期时间和一个时区偏移量。
如何使用此类型取决于您是否要更改现有数据的数据类型。如果您不想更改任何内容,以下语句将返回本地时间为午夜的 datetime 类型:
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())