我正在做一些SQL选择查询,并希望将我的UTC日期时间列转换为本地时间,以便在我的查询结果中显示为本地时间。注意,我不希望通过代码进行这种转换,而是当我对我的数据库进行手动和随机SQL查询时。
当前回答
该函数将UTC时间转换为EST时间,并进行DST调整。你可以在这个函数中更改你设计的时区名称,或者从注册表中获取:
Create Function fnConvertUTCTimetoESTTime(
@UTCTime as datetime
)
returns datetime
as
begin
return convert(datetime, convert(varchar(23), @UTCTime AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time', 121), 121)
end
go
select dbo.fnConvertUTCTimetoESTTime ('2020-3-8 5:00:00.000')
, dbo.fnConvertUTCTimetoESTTime ('2020-3-8 6:00:00.000')
, dbo.fnConvertUTCTimetoESTTime ('2020-3-8 7:00:00.000')
, dbo.fnConvertUTCTimetoESTTime ('2020-3-8 8:00:00.000')
--returns 0:00am, 1:00am, 3:00am, 4:00am
select dbo.fnConvertUTCTimetoESTTime ('2020-11-1 4:00:00.000')
, dbo.fnConvertUTCTimetoESTTime ('2020-11-1 5:00:00.000')
, dbo.fnConvertUTCTimetoESTTime ('2020-11-1 6:00:00.000')
, dbo.fnConvertUTCTimetoESTTime ('2020-11-1 7:00:00.000')
--returns 0:00am, 1:00am, 1:00am, 2:00am
请注意,您不能只是返回“@UTCTime AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard TIME '”作为结果,因为该结果实际上是EST格式的UTC时间(当您比较这个“假”EST时间或将其包含在order子句中时,它将被转换回UTC时间)。
其他回答
作为一个警告-如果你要使用以下(注意毫秒而不是分钟):
SELECT DATEADD(ms, DATEDIFF(ms, GETUTCDATE(), GETDATE()), MyTable.UtcColumn)
AS ColumnInLocalTime
FROM MyTable
请记住,DATEDIFF部分并不总是返回相同的数字。所以不要用它来将DateTimes精确到毫秒。
第一个功能:配置为意大利时区(+1,+2),切换日期:3月和10月的最后一个星期天,返回当前时区与datetime的差值作为参数。
Returns:
current timezone < parameter timezone ==> +1
current timezone > parameter timezone ==> -1
else 0
代码是:
CREATE FUNCTION [dbo].[UF_ADJUST_OFFSET]
(
@dt_utc datetime2(7)
)
RETURNS INT
AS
BEGIN
declare @month int,
@year int,
@current_offset int,
@offset_since int,
@offset int,
@yearmonth varchar(8),
@changeoffsetdate datetime2(7)
declare @lastweek table(giorno datetime2(7))
select @current_offset = DATEDIFF(hh, GETUTCDATE(), GETDATE())
select @month = datepart(month, @dt_utc)
if @month < 3 or @month > 10 Begin Set @offset_since = 1 Goto JMP End
if @month > 3 and @month < 10 Begin Set @offset_since = 2 Goto JMP End
--If i'm here is march or october
select @year = datepart(yyyy, @dt_utc)
if @month = 3
Begin
Set @yearmonth = cast(@year as varchar) + '-03-'
Insert Into @lastweek Values(@yearmonth + '31 03:00:00.000000'),(@yearmonth + '30 03:00:00.000000'),(@yearmonth + '29 03:00:00.000000'),(@yearmonth + '28 03:00:00.000000'),
(@yearmonth + '27 03:00:00.000000'),(@yearmonth + '26 03:00:00.000000'),(@yearmonth + '25 03:00:00.000000')
--Last week of march
Select @changeoffsetdate = giorno From @lastweek Where datepart(weekday, giorno) = 1
if @dt_utc < @changeoffsetdate
Begin
Set @offset_since = 1
End Else Begin
Set @offset_since = 2
End
End
if @month = 10
Begin
Set @yearmonth = cast(@year as varchar) + '-10-'
Insert Into @lastweek Values(@yearmonth + '31 03:00:00.000000'),(@yearmonth + '30 03:00:00.000000'),(@yearmonth + '29 03:00:00.000000'),(@yearmonth + '28 03:00:00.000000'),
(@yearmonth + '27 03:00:00.000000'),(@yearmonth + '26 03:00:00.000000'),(@yearmonth + '25 03:00:00.000000')
--Last week of october
Select @changeoffsetdate = giorno From @lastweek Where datepart(weekday, giorno) = 1
if @dt_utc > @changeoffsetdate
Begin
Set @offset_since = 1
End Else Begin
Set @offset_since = 2
End
End
JMP:
if @current_offset < @offset_since Begin
Set @offset = 1
End Else if @current_offset > @offset_since Set @offset = -1 Else Set @offset = 0
Return @offset
END
然后是转换日期的函数
CREATE FUNCTION [dbo].[UF_CONVERT]
(
@dt_utc datetime2(7)
)
RETURNS datetime
AS
BEGIN
declare @offset int
Select @offset = dbo.UF_ADJUST_OFFSET(@dt_utc)
if @dt_utc >= '9999-12-31 22:59:59.9999999'
set @dt_utc = '9999-12-31 23:59:59.9999999'
Else
set @dt_utc = (SELECT DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), GETDATE()), @dt_utc) )
if @offset <> 0
Set @dt_utc = dateadd(hh, @offset, @dt_utc)
RETURN @dt_utc
END
对于Azure SQL和@@Version >= SQL Server 2016用户,下面是一个使用AT TIME ZONE的简单函数。
CREATE FUNCTION [dbo].[Global_Convert_UTCTimeTo_LocalTime]
(
@LocalTimeZone VARCHAR(50),
@UTCDateTime DATETIME
)
RETURNS DATETIME
AS
BEGIN
DECLARE @ConvertedDateTime DATETIME;
SELECT @ConvertedDateTime = @UTCDateTime AT TIME ZONE 'UTC' AT TIME ZONE @LocalTimeZone
RETURN @ConvertedDateTime
END
GO
对于@LocalTimeZone可以采用的值类型,请转到此链接或转到KEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones
我没有发现任何这些示例有助于将日期时间存储为UTC到指定时区(不是服务器的时区,因为Azure SQL数据库以UTC运行)中的日期时间。我是这样处理的。它并不优雅,但它很简单,无需维护其他表就能给出正确答案:
select CONVERT(datetime, SWITCHOFFSET(dateTimeField, DATEPART(TZOFFSET,
dateTimeField AT TIME ZONE 'Eastern Standard Time')))
这样就可以获得与夏令时同步的服务器时间
declare @dt datetime
set @dt = getutcdate() -- GMT equivalent
sysdatetimeoffset会考虑夏令时
select [InputTime] = @dt
, [LocalTime2] = dateadd(mi, datediff(mi, sysdatetimeoffset(),getdate()), @dt)
推荐文章
- 如何在Ruby On Rails中使用NuoDB手动执行SQL命令
- 查询JSON类型内的数组元素
- 确定记录是否存在的最快方法
- 获得PostgreSQL数据库中当前连接数的正确查询
- 在SQL选择语句Order By 1的目的是什么?
- 从现有模式生成表关系图(SQL Server)
- 我如何循环通过一组记录在SQL Server?
- 数据库和模式的区别
- 如何在SQL Server中一次更改多个列
- 如何从命令行通过mysql运行一个查询?
- 外键约束可能导致循环或多条级联路径?
- 使用LIMIT/OFFSET运行查询,还可以获得总行数
- 当恢复sql时,psql无效命令\N
- 货币应该使用哪种数据类型?
- 如何选择每一行的列值不是独特的