如何在SQL Server中插入带时区的UTC时间?PostgreSQL转SQL Server问题
SQL Server 中插入带UTC时区的 datetimeoffset 数据
问题核心
你在PostgreSQL中可以通过now() at time zone 'utc'向timestamp with time zone类型字段插入带UTC时区标记的时间,但在SQL Server中使用GETUTCDATE() AT TIME ZONE 'UTC'插入datetimeoffset(7)字段时,误以为没有时区信息,尝试用字符串拼接的方式实现——这其实是错误的做法。
正确实现方式
方式1:用GETUTCDATE()转换为带UTC时区的datetimeoffset
GETUTCDATE()返回UTC时间的datetime类型,结合AT TIME ZONE 'UTC'会将该时间标记为UTC时区(偏移+00:00),插入后的数据是带完整时区信息的:
CREATE TABLE Test1(tz [datetimeoffset](7)) INSERT INTO Test1 SELECT GETUTCDATE() AT TIME ZONE 'UTC'
如果查询时看不到时区信息,可能是客户端显示设置的问题,可以用格式化函数查看完整内容:
SELECT FORMAT(tz, 'yyyy-MM-dd HH:mm:ss.fffffff zzz') AS tz_with_timezone FROM Test1
方式2:用SYSDATETIMEOFFSET()转换为UTC时区
SYSDATETIMEOFFSET()返回服务器本地时区的datetimeoffset,通过AT TIME ZONE 'UTC'可以直接转换为UTC时区的时间:
INSERT INTO Test1 SELECT SYSDATETIMEOFFSET() AT TIME ZONE 'UTC'
这个语句会自动把本地时区时间转成UTC时间,并带上+00:00的时区标记。
方式3:直接构造UTC时区的datetimeoffset
通过DATETIMEOFFSETFROMPARTS函数直接构造UTC时间(偏移为0):
INSERT INTO Test1 SELECT DATETIMEOFFSETFROMPARTS( YEAR(GETUTCDATE()), MONTH(GETUTCDATE()), DAY(GETUTCDATE()), HOUR(GETUTCDATE()), MINUTE(GETUTCDATE()), SECOND(GETUTCDATE()), DATEPART(MICROSECOND, GETUTCDATE()), 0, 0, 7 )
你的拼接方法为什么错误
你写的语句:
Select cast(left(SYSDATETIMEOFFSET() AT TIME ZONE 'UTC',28) + DATENAME(TZOFFSET, SYSDATETIMEOFFSET()) as [datetimeoffset](7))
存在两个关键问题:
SYSDATETIMEOFFSET() AT TIME ZONE 'UTC'本身已经是正确的UTC时间(带+00:00偏移),不需要额外拼接。- 你截取UTC时间的前28位后,加上了原本地时区的偏移(比如
+08:00),最终得到的是UTC时间值 + 本地时区偏移,这会导致时间值和时区不匹配,完全不符合需求。
内容的提问来源于stack exchange,提问作者Rchoudhary
相关产品推荐
相关产品推荐

