我正在做一些SQL选择查询,并希望将我的UTC日期时间列转换为本地时间,以便在我的查询结果中显示为本地时间。注意,我不希望通过代码进行这种转换,而是当我对我的数据库进行手动和随机SQL查询时。
当前回答
您必须重新格式化字符串以及转换为正确的时间。在这种情况下,我需要祖鲁时间。
Declare @Date datetime;
Declare @DateString varchar(50);
set @Date = GETDATE();
declare @ZuluTime datetime;
Declare @DateFrom varchar (50);
Declare @DateTo varchar (50);
set @ZuluTime = DATEADD(second, DATEDIFF(second, GETDATE(), GETUTCDATE()), @Date);
set @DateString = FORMAT(@ZuluTime, 'yyyy-MM-ddThh:mm:ssZ', 'en-US' )
select @DateString;
其他回答
没有一种简单的方法能以正确而通用的方式做到这一点。
首先,必须理解偏移量取决于所讨论的日期、时区和夏令时。 GetDate()-GetUTCDate只提供今天服务器TZ的偏移量,这是不相关的。
我只见过两种有效的解决方案,我已经搜索了很多。
1)一个自定义SQL函数,包含几个基本数据表,如每个TZ的时区和夏令时规则。 工作,但不是很优雅。我不能发布,因为我没有代码。
编辑:下面是这个方法的一个例子 https://gist.github.com/drumsta/16b79cee6bc195cd89c8
2)添加一个.net程序集到db, .net可以很容易地做到这一点。这工作得很好,但缺点是你需要在服务器级配置几个参数,配置很容易被破坏,例如,如果你恢复数据库。 我使用这个方法,但我不能张贴它,因为我没有自己的代码。
我有代码执行UTC到本地和本地到UTC时间,允许使用这样的代码进行转换
DECLARE @usersTimezone VARCHAR(32)='Europe/London'
DECLARE @utcDT DATETIME=GetUTCDate()
DECLARE @userDT DATETIME=[dbo].[funcUTCtoLocal](@utcDT, @usersTimezone)
and
DECLARE @usersTimezone VARCHAR(32)='Europe/London'
DECLARE @userDT DATETIME=GetDate()
DECLARE @utcDT DATETIME=[dbo].[funcLocaltoUTC](@userDT, @usersTimezone)
这些函数可以支持NodaTime提供的IANA/TZDB中的全部或一部分时区-请参阅https://nodatime.org/TimeZones上的完整列表
请注意,我的用例意味着我只需要一个“当前”窗口,允许在大约+/- 5年的范围内转换时间。这意味着,如果您需要很宽的时间段,我使用的方法可能不适合您,因为它在给定日期范围内为每个时区间隔生成代码的方式不同。
该项目位于GitHub: https://github.com/elliveny/SQLServerTimeConversion
这将生成如下示例所示的SQL函数代码
如果您将数据存储为UTC日期在数据库中,您可以做一些简单的事情
select
[MyUtcDate] + getdate() - getutcdate()
from [dbo].[mytable]
这是从服务器的角度来看,它总是本地的,你不会笨拙地使用AT TIME ZONE '你的时区名称', 如果您的数据库像客户端安装一样被移动到另一个时区,那么硬编码的时区可能会让您感到困扰。
我发现当有大量数据时,一次性函数的方法太慢了。因此,我通过连接到一个允许计算小时差的表函数来实现它,它基本上是带有小时偏移量的datetime分段。一年是4行。这个表格函数
dbo.fn_getTimeZoneOffsets('3/1/2007 7:00am', '11/5/2007 9:00am', 'EPT')
将返回这个表:
startTime endTime offset isHr2
3/1/07 7:00 3/11/07 6:59 -5 0
3/11/07 7:00 11/4/07 6:59 -4 0
11/4/07 7:00 11/4/07 7:59 -5 1
11/4/07 8:00 11/5/07 9:00 -5 0
它确实考虑了夏时制。下面是它如何使用的示例,完整的博客文章在这里。
select mt.startTime as startUTC,
dateadd(hh, tzStart.offset, mt.startTime) as startLocal,
tzStart.isHr2
from MyTable mt
inner join dbo.fn_getTimeZoneOffsets(@startViewUTC, @endViewUTC, @timeZone) tzStart
on mt.startTime between tzStart.startTime and tzStart.endTime
最简单的答案并不总是在底部,但这一次是,并且可以在上面的评论中看到。 使用您自己的“AT TIME ZONE”来捕获列/数据字段的TzOffset,而不是当前的SYSDATETIME。 在下面的数据中,2个查询,一个关于feb数据(DST是关闭的,在阿姆斯特丹的冬天)+1差异 第二次查询阿姆斯特丹4月份的数据,所以+2小时的差异。
select top 2 month(receiveTimeUTC) as MonthInWinterOrSpring
, receiveTimeUTC
, CONVERT(datetime, SWITCHOFFSET(CONVERT(datetimeoffset, receiveTimeUTC), DATENAME(TzOffset, SYSDATETIMEOFFSET()))) as LocalTimeWrongNoDST
, CONVERT(datetime, SWITCHOFFSET(CONVERT(datetimeoffset, receiveTimeUTC), DATENAME(TzOffset, receiveTimeUTC AT TIME ZONE 'Central European Standard Time' ))) as LocalTimeWithDST
from sensordetails order by id
select top 2 month(receiveTimeUTC) as MonthInWinterOrSpring, receiveTimeUTC
, CONVERT(datetime, SWITCHOFFSET(CONVERT(datetimeoffset, receiveTimeUTC), DATENAME(TzOffset, SYSDATETIMEOFFSET()))) as LocalTimeWrongNoDST
, CONVERT(datetime, SWITCHOFFSET(CONVERT(datetimeoffset, receiveTimeUTC), DATENAME(TzOffset, receiveTimeUTC AT TIME ZONE 'Central European Standard Time' ))) as LocalTimeWithDST
from sensordetails order by id desc
结果:
所以这是一个T-SQL (SQL Server Answer),不需要函数的storedproc。
推荐文章
- 如何在Ruby On Rails中使用NuoDB手动执行SQL命令
- 查询JSON类型内的数组元素
- 确定记录是否存在的最快方法
- 获得PostgreSQL数据库中当前连接数的正确查询
- 在SQL选择语句Order By 1的目的是什么?
- 从现有模式生成表关系图(SQL Server)
- 我如何循环通过一组记录在SQL Server?
- 数据库和模式的区别
- 如何在SQL Server中一次更改多个列
- 如何从命令行通过mysql运行一个查询?
- 外键约束可能导致循环或多条级联路径?
- 使用LIMIT/OFFSET运行查询,还可以获得总行数
- 当恢复sql时,psql无效命令\N
- 货币应该使用哪种数据类型?
- 如何选择每一行的列值不是独特的