我有一个日期时间值。
该日期时间值可能位于任何时区,例如“东部标准时间”或“印度标准时间”。
我想在SQL中将该日期时间值转换为UTC时区。
这里的时区值将作为给定参数。
我也可以使用C#代码实现此目标。但是我需要SQL查询。
有人能告诉我如何转换吗?
我有一个日期时间值。
该日期时间值可能位于任何时区,例如“东部标准时间”或“印度标准时间”。
我想在SQL中将该日期时间值转换为UTC时区。
这里的时区值将作为给定参数。
我也可以使用C#代码实现此目标。但是我需要SQL查询。
有人能告诉我如何转换吗?
时区和时区偏移是两个不同的概念。如果使用夏令时,一个时区可以有不同的偏移量。 SQL Server在最新版本2016中添加了时区支持。
你的问题有两部分 - 如何将datetime
值转换为带有偏移/时区的值,然后如何将该值转换为UTC时间。
在SQL Server 2014之前的版本中,您需要事先确定本地时区的正确偏移量,例如使用C#代码。一旦您拥有它,就可以使用TODATETIMEOFFSET将datetime
转换为具有特定偏移量的`datetimeoffset:
select TODATETIMEOFFSET(GETDATE(),'02:00')
或者select TODATETIMEOFFSET(GETDATE(),120)
这将返回一个带有原始时间和指定偏移量的datetimeoffset
值。
切换到另一个偏移量(例如UTC)可通过SWITCHOFFSET函数执行。
select SWITCHOFFSET(@someDateTimeOffset,0)
您可以将它们组合起来使用
select SWITCHOFFSET(TODATETIMEOFFSET(GETDATE(),120),0)
偏移量可以作为参数传递。假设您的字段名为SomeTime
,您可以编写:
select SWITCHOFFSET(TODATETIMEOFFSET(SomeTime,@offsetInMinutes),0)
在SQL Server 2016中,您可以使用时区名称。但是您仍然需要进行双重转换,首先转换为本地时区,然后再转换为UTC:
SELECT (getdate() at time zone 'Central Europe Standard Time') AT TIME ZONE 'UTC'
第一个AT TIMEZONE
返回一个带有+2:00
偏移量的datetimeoffset
,第二个将其转换为UTC。
注意
如果您使用datetimeoffset
类型而不是datetime
,则可能可以避免所有转换。 SQL Server允许对具有不同偏移量的值进行比较、过滤、计算等操作,因此您无需进行任何查询转换。在客户端方面,.NET有等效的DateTimeOffset
类型,因此您无需在客户端代码中进行任何转换。
TODATETIMEOFFSET(GETDATE(),120)
今天返回60分钟,但过去将返回120分钟(由于夏令时)。请注意,本回答中提到的时间是使用协调世界时(UTC)表示的。 - Salman Adatetimeoffset
时,DST 才会起作用,因为您需要知道要使用的实际偏移值。一旦您有了偏移量,就会切换偏移量而不是时区。至于 AT TIME ZONE
,它确实考虑了 DST。如果您在冬季和夏季尝试相同的时间,您将获得不同的偏移量。 - Panagiotis KanavosSELECT (cast('2019-03-11 11:13' as datetime) at time zone 'Central Europe Standard Time')
返回 2019-03-11 11:13:00.000 +01:00
,但是 2019-06-11
返回 2019-06-11 11:13:00.000 +02:00
。 - Panagiotis Kanavos如果你正在使用 SQL Server 2016,则可以使用新的 AT TIME ZONE
子句:
SELECT SalesOrderID, OrderDate,
OrderDate AT TIME ZONE 'Eastern Standard Time' AS OrderDate_TimeZoneEST,
OrderDate AT TIME ZONE 'Eastern Standard Time'
AT TIME ZONE 'UTC' AS OrderDate_TimeZoneUTC
FROM Sales.SalesOrderHeader;
要将一个时区转换为另一个时区,请使用 AT TIME ZONE 命令,
例如,如果你有一个名为 Book 的表,其中存储了以 UTC 为单位的 purchasedTime,并且你想知道在 EST 时区的时间。
Select bookName , CONVERT(datetime,purchasedTime) AT TIME ZONE 'UTC' AT TIME ZONE 'US Eastern Standard Time' as purchaseTimeInEST from Book;
如果您使用的是早于SQL Server 2012
版本的数据库,请使用以下查询语句,它对我很有效。
DECLARE @localdate DATETIME = '2020-01-10 05:30';
Declare @DateDiff bigint =Datediff(minute, Getdate(),Getutcdate() ) --GetDate -current datetime of local
--Declare @DateDiff bigint =-330 --you ca declare timezone different in minutes also
SELECT @localdate AS LocalDate, Dateadd(minute, @DateDiff, @localdate) AS UTCConvertedDate;
使用时区名称转换时区,可以执行以下操作:
找到服务器时区和您的时区之间的分钟数。-- Change to your time zone name
declare @TimezoneName varchar(max) = 'New Zealand Standard Time'
declare @timezoneOffset bigint = Datediff( MINUTE, getdate() at time zone @TimezoneName, getdate() )
SWITCHOFFSET
可以将日期时间转换为您所在的时区。getdate()
为'2020-04-16 04:47:25.640'
时,
您将得到'2020-04-16 16:47:25.640 +12:00'
(NZT时区为+12)。select SWITCHOFFSET(getdate(), @timezoneOffset)
此方法可在SQL Server 2016及以上版本中使用。
GETDATE()
会返回本地时间。这将为具有不同设置的服务器返回不同的结果。在任何默认时区为 UTC 的云服务器上,它肯定会失败。更加理由是通过使用 DateTimeOffset
来避免转换。 - Panagiotis Kanavos
datetimeoffset
不需要进行任何转换,这样不是更好吗? - Panagiotis Kanavos