转换为我的时区 - SQL Server

Posted

技术标签:

【中文标题】转换为我的时区 - SQL Server【英文标题】:Convert to my time zone - SQL Server 【发布时间】:2018-01-23 12:13:57 【问题描述】:

有人可以帮我吗?

我有一个源数据,它位于另一个国家/地区的另一台服务器中,当我将其发送到我的 B.I 暂存区时,我想将其转换为我的时区,但我的 SQL Server 版本是 2014 年。

我无法使用 AT TIME ZONE SQL Server 功能。 有没有其他方法可以在不修复如下硬编码值的情况下做到这一点?

下面的结果并没有解决我的问题,因为它的硬编码值:

SELECT SWITCHOFFSET (DATETIMEFIELD, '-03:00')
SELECT TODATETIMEOFFSET(DATETIMEFIELD,'-03:00')

Ps:不要忘记 DAYLIGHT SAVING

【问题讨论】:

原始数据是什么数据类型? datetime/datetime2 还是你在使用datetimeoffset @Larnu 源数据是一个日期时间列 我假设,由于您提到夏令时,您或来源不使用夏令时,或者他们在不同的日子? @EvertonGomes BTW both 函数工作并返回 datetimeoffset 值。第一个将datetime 输入视为UTC,并返回新时区中的等效时间。第二个将偏移量附加到输入。 doesn't solve my problem 是什么意思?输入值是什么,预期结果是什么? @Tanner 没有理由这样做,如果您使用 datetimeoffset。在这种情况下,无需担心“我的时区”是什么意思 【参考方案1】:

没有任何样本数据,这在很大程度上是在黑暗中刺伤,至少试图解释它。请注意,这不是万无一失的。例如,当时钟返回时,时间 01:00:00 - 01:59:59 将出现两次。这些时间将始终被假定为 DST之前,无论它们是否真的是。

无论如何,首先我创建了一个小表,其中包含 DST 在英国 (GMT: UTC + 0) 和美国东部 (EST: UTC - 5) 发生的日期。

然后,我使用该数据创建了如下查询。

USE Sandbox;
GO
--SAmple Daylight Savings Table
CREATE TABLE DaylightSaving (Timezone char(3),
                             ClocksChangeDate datetime,
                             Change smallint,
                             UTCDiff smallint);
--Dates for UK
INSERT INTO DaylightSaving
VALUES ('GMT','20170326 02:00:00',1,0),
       ('GMT','20171029 02:00:00',0,0),
       ('GMT','20180325 02:00:00',1,0),
       ('GMT','20181028 02:00:00',0,0),
       ('GMT','20190331 02:00:00',1,0),
       ('GMT','20191027 02:00:00',0,0);

--Dates for Eastern America
INSERT INTO DaylightSaving
VALUES ('EST','20170312',1,-5),
       ('EST','20171105',0,-5),
       ('EST','20180311',1,-5),
       ('EST','20181104',0,-5),
       ('EST','20190310',1,-5),
       ('EST','20191103',0,-5);
GO
--Made up sample data

CREATE TABLE SampleData (DateAndTime datetime, Timezone char(3));

INSERT INTO SampleData
VALUES ('20180123 12:28:00.000','EST'),
       ('20180523 19:58:00.000','EST'),
       ('20181101 07:19:00.000','EST'),
       ('20190330 20:50:00.000','EST'),
       ('20190330 21:05:00.000','EST');
GO

SELECT DateAndTime AS ESTTime,
       DATEADD(HOUR, 5 + DT.Change - ST.Change, DateAndTime) AS GMTTime,
       DATEDIFF(HOUR, DateAndTime, DATEADD(HOUR, DT.UTCDiff - ST.UTCDiff + DT.Change - ST.Change, DateAndTime)) AS TimeZoneDifference,
       ST.ClocksChangeDate, DT.ClocksChangeDate
FROM SampleData SD
     CROSS APPLY (SELECT TOP 1 *
                  FROM DaylightSaving sq
                  WHERE sq.ClocksChangeDate <= SD.DateAndTime
                    AND Timezone = SD.Timezone
                  ORDER BY sq.ClocksChangeDate DESC) ST
     CROSS APPLY (SELECT TOP 1 *
                  FROM DaylightSaving sq
                  WHERE sq.ClocksChangeDate <= DATEADD(HOUR, sq.UTCDiff - ST.UTCDiff,SD.DateAndTime)
                    AND sq.Timezone = 'GMT' --your destination Timezone
                  ORDER BY sq.ClocksChangeDate DESC) DT;


GO

DROP TABLE DaylightSaving;
DROP TABLE SampleData;

编辑:请注意,这两个区域之间的差异是硬编码的(我有一个 DATEADD,硬编码值为 5),因为这是一个示例。您需要为自己的系统进行推断,但由于我们不知道这是什么样的,您需要完成这项工作。

编辑 2:感觉就像添加时区差异。现在只有硬编码的值是本地时区的值('GMT' 在这种情况下是第二个CROSS APPLY

正如一些人所说,datetime 没有时区的概念。如果这对您的数据至关重要,那么不要使用datetime,使用datetimeoffset。将 UTC +/- 值存储为值的一部分;让这样的事情变得微不足道。

【讨论】:

以上是关于转换为我的时区 - SQL Server的主要内容,如果未能解决你的问题,请参考以下文章

[SQL SERVER][Memo]全时区转换

将 UTC 中的 SQL Server 日期时间转换为特定时区

将 SQL Server 数据库转换为 MySQL

如何将包含时区的字符串转换为日期时间 sql server

SQL Server 2016 - 为啥我需要为我的选择语句指定一个根元素

来自带有时区的 SQL Server 的 DateTime