【问题标题】:How to calculate local time based on GMT?如何根据格林威治标准时间计算当地时间?
【发布时间】:2020-03-31 13:46:57
【问题描述】:

我正在尝试根据我为他们提供的 GMT 时间数据来计算各个国家/地区的当地时间。我还需要知道他们是否也遵守夏令时。有没有办法在没有 CLR 的情况下实现这一目标?以下是一些示例数据供您参考。

DDL:

CREATE TABLE #Temp(
COUNTRY_CODE VARCHAR(2)
DATETIME VARCHAR(50)
);

DML:

INSERT INTO #Temp(COUNTRY_CODE, DATETIME)
VALUES
('EE', 'Sun Mar 29 00:00:00 GMT 1992'),
('AZ', 'Sun Mar 28 00:00:00 GMT 1993'),
('CZ', 'Sun Mar 27 00:00:00 GMT 1994'),
('DE', 'Sun Mar 26 00:00:00 GMT 1995'),
('AD', 'Sun Mar 31 00:00:00 GMT 1996'),
('GI', 'Sun Mar 30 00:00:00 GMT 1997'),
('DK', 'Sun Mar 29 00:00:00 GMT 1998'),
('AL', 'Sun Mar 28 00:00:00 GMT 1999'),
('ES', 'Sun Mar 26 00:00:00 GMT 2000'),
('LT', 'Sun Mar 25 00:00:00 GMT 2001');

环境: Microsoft Azure SQL 数据仓库 - 10.0.10783.0 2019 年 10 月 26 日 23:24:02 版权所有 (c) Microsoft Corporation

谢谢!

【问题讨论】:

  • 为什么要将日期和时间存储为varchar?你所拥有的格式是一种糟糕的处理方式。将时间存储为日期和时间数据类型,然后使用AT TIME ZONESWITCHOFFSET
  • 另外请注意,某些国家/地区(例如您的示例中的德国 (DE) 和西班牙 (ES))使用夏令时,这意味着它们会更改偏移量。通过 GMT,我假设您还指的是 UTC,而不是英国的时间(英国也使用 DST,因此夏季的时间是 UTC +01:00,而不是 UTC)。
  • +10 到拉努的所有积分。此外,该表既不需要也不太可能工作。国家没有固定的偏移量,它们有多个偏移量和 DST 规则。 AT TIME ZONE 已经照顾好他们了。 SQL Server 2016+ 已经有一个时区表。每个人的抱怨是它使用 Windows 时区名称而不是事实上的标准 IANA 时区名称
  • 你为什么要在多个论坛上独立发布同一个问题?喜欢msdn
  • @Julaayi select getdate() 在 VM 上(假设 VM 在正确的时区)并将该值复制到 DW 到表或变量中。然后在 DW 中执行 datediff(minute,@DateFromVM,getdate()) 以获取当前分钟与 UTC 的偏移量。

标签: sql-server azure-sql-database azure-sqldw azure-sql-server azure-sql-reporting


【解决方案1】:

这很混乱,因为您的数据是。你还有很长的路要走,我建议实际上将“DateTime”列更改为正确的数据类型,而不是使用计算列:

--Create sample table
CREATE TABLE dbo.YourTable (CountryCode char(2),
                            NotADateTime varchar(50));

INSERT INTO dbo.YourTable (CountryCode,
                           NotADateTime)
VALUES ('EE', 'Sun Mar 29 00:00:00 GMT 1992'),
       ('AZ', 'Sun Mar 28 00:00:00 GMT 1993'),
       ('CZ', 'Sun Mar 27 00:00:00 GMT 1994'),
       ('DE', 'Sun Mar 26 00:00:00 GMT 1995'),
       ('AD', 'Sun Mar 31 00:00:00 GMT 1996'),
       ('GI', 'Sun Mar 30 00:00:00 GMT 1997'),
       ('DK', 'Sun Mar 29 00:00:00 GMT 1998'),
       ('AL', 'Sun Mar 28 00:00:00 GMT 1999'),
       ('ES', 'Sun Mar 26 00:00:00 GMT 2000'),
       ('LT', 'Sun Mar 25 00:00:00 GMT 2001'),
       ('FR', 'Sun Jul 14 00:00:00 GMT 2019'); --Add one that is in DST.
GO
--Create a proper datetimeoffset column
ALTER TABLE dbo.YourTable ADD ADateTime AS TRY_CONVERT(datetimeoffset(0),RIGHT(NotADateTime,4) + '-' +
                                                                         CASE SUBSTRING(NotADateTime,5,3) WHEN 'Jan' THEN '01'
                                                                                                             WHEN 'Feb' THEN '02'
                                                                                                             WHEN 'Mar' THEN '03'
                                                                                                             WHEN 'Apr' THEN '04'
                                                                                                             WHEN 'May' THEN '05'
                                                                                                             WHEN 'Jun' THEN '06'
                                                                                                             WHEN 'Jul' THEN '07'
                                                                                                             WHEN 'Aug' THEN '08'
                                                                                                             WHEN 'Sep' THEN '09'
                                                                                                             WHEN 'Oct' THEN '10'
                                                                                                             WHEN 'Nov' THEN '11'
                                                                                                             WHEN 'Dec' THEN '12'
                                                                         END + '-' + SUBSTRING(NotADateTime,9,2) + 'T' +
                                                                         SUBSTRING(NotADateTime,12,9));

GO
--Check data
SELECT YT.CountryCode,
       YT.NotADateTime,
       YT.ADateTime
FROM dbo.YourTable YT;
GO     
--Add a timezone lookup table
CREATE TABLE dbo.TimeZoneLookup (CountryCode char(2),
                                 MSTimeZoneName nvarchar(128));
INSERT INTO dbo.TimeZoneLookup (CountryCode,
                                MSTimeZoneName)
SELECT CountryCode,'Central Europe Standard Time' --All apepar to be european countries, so jsut assumed. You should NOT. 
FROM dbo.YourTable; --You can find all the timezones in sys.time_zone_info


GO
--JOIN and change timezone
SELECT YT.CountryCode,
       YT.ADateTime,
       YT.ADateTime AT TIME ZONE TZ.MSTimeZoneName
FROM dbo.YourTable YT
     JOIN dbo.TimeZoneLookup TZ ON YT.CountryCode = TZ.CountryCode

GO
--Clean up
DROP TABLE dbo.YourTable;
DROP TABLE dbo.TimeZoneLookup;

【讨论】:

  • 我从旧版应用程序中获取日期,但我无法控制它。因此,在将其输入 DW 之前,我必须对其进行相应的处理。
猜你喜欢
  • 1970-01-01
  • 2020-11-25
  • 1970-01-01
  • 2011-05-13
  • 1970-01-01
  • 2012-05-31
  • 2011-10-30
  • 2019-11-25
  • 2013-03-10
相关资源
最近更新 更多