我们正在处理一个需要处理来自不同时区和夏令时设置的全球时间数据的应用程序。这个想法是将所有内容以UTC格式存储在内部,并且仅针对本地化的用户界面来回转换。SQL Server是否提供任何机制来处理给定时间,国家/地区和时区的翻译?
这肯定是一个普遍的问题,所以我很惊讶Google不会提供任何可用的东西。
有指针吗?
我们正在处理一个需要处理来自不同时区和夏令时设置的全球时间数据的应用程序。这个想法是将所有内容以UTC格式存储在内部,并且仅针对本地化的用户界面来回转换。SQL Server是否提供任何机制来处理给定时间,国家/地区和时区的翻译?
这肯定是一个普遍的问题,所以我很惊讶Google不会提供任何可用的东西。
有指针吗?
Answers:
过去了7年,
实际上...此新SQL Server 2016功能完全可以满足您的需求。
它被称为“ AT TIME ZONE”,它考虑DST(夏令时)的更改,将日期转换为指定的时区。
此处的更多信息:https :
//msdn.microsoft.com/en-us/library/mt612795.aspx
这适用于当前具有与SQL Server主机相同的UTC偏移量的日期。它不考虑夏令时的变化。替换YOUR_DATE
为要转换的本地日期。
SELECT DATEADD(second, DATEDIFF(second, GETDATE(), GETUTCDATE()), YOUR_DATE);
对于SQL Server 2016和更高版本以及Azure SQL数据库,请使用内置AT TIME ZONE
语句。
对于旧版本的SQL Server,您可以使用我的SQL Server时区支持项目在IANA标准时区之间进行转换,如下所示。
UTC到本地是这样的:
SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'America/Los_Angeles')
UTC本地是这样的:
SELECT Tzdb.LocalToUtc('2015-07-01 00:00:00', 'America/Los_Angeles', 1, 1)
数字选项是用于控制本地时间值受夏令时影响的行为的标志。这些在项目文档中进行了详细描述。
SQL Server 2008的类型为datetimeoffset
。这对于这类东西真的很有用。
http://msdn.microsoft.com/en-us/library/bb630289.aspx
然后,您可以使用该功能SWITCHOFFSET
将其从一个时区移至另一个时区,但仍保持相同的UTC值。
http://msdn.microsoft.com/en-us/library/bb677244.aspx
抢
这是将一个区域转换DateTime
为另一区域的代码DateTime
DECLARE @UTCDateTime DATETIME = GETUTCDATE();
DECLARE @ConvertedZoneDateTime DATETIME;
-- 'UTC' to 'India Standard Time' DATETIME
SET @ConvertedZoneDateTime = @UTCDateTime AT TIME ZONE 'UTC' AT TIME ZONE 'India Standard Time'
SELECT @UTCDateTime AS UTCDATE,@ConvertedZoneDateTime AS IndiaStandardTime
-- 'India Standard Time' to 'UTC' DATETIME
SET @UTCDateTime = @ConvertedZoneDateTime AT TIME ZONE 'India Standard Time' AT TIME ZONE 'UTC'
SELECT @ConvertedZoneDateTime AS IndiaStandardTime,@UTCDateTime AS UTCDATE
注意事项:AT TIME ZONE
仅适用于SQL Server 2016+,优点是转换为特定时区时会自动考虑日光
AT TIME ZONE
呼叫(短语?)链接在一起的事实外,别无其他!简单优雅。我之前说过stackoverflow.com/a/44579178/112764可以满足我的需求,但这甚至更好。主要荣誉。
DECLARE @UTCDateTime DATETIME = GETUTCDATE();
DECLARE @ConvertedZoneDateTime DATETIME;
-- 'UTC' to 'India Standard Time' to 'Eastern Standard Time' DATETIME
SET @ConvertedZoneDateTime = @UTCDateTime AT TIME ZONE 'UTC' AT TIME ZONE 'India Standard Time' AT TIME ZONE 'Eastern Standard Time'
SELECT @UTCDateTime AS UTCDATE,@ConvertedZoneDateTime AS EasternStandardTime
是的,您可以链接多个 AT TIME ZONE
呼叫,但是“从”和“到”就足以进行任何转换,而我们最需要的是
我倾向于将DateTimeOffset用于与本地活动(例如,博物馆的会议/聚会等,下午12点至下午3点)无关的所有日期时间存储。
要将当前的DTO设置为UTC:
DECLARE @utcNow DATETIMEOFFSET = CONVERT(DATETIMEOFFSET, SYSUTCDATETIME())
DECLARE @utcToday DATE = CONVERT(DATE, @utcNow);
DECLARE @utcTomorrow DATE = DATEADD(D, 1, @utcNow);
SELECT @utcToday [today]
,@utcTomorrow [tomorrow]
,@utcNow [utcNow]
注意:通过有线发送时,我将始终使用UTC ...客户端JS可以轻松地从本地UTC进出。看到:new Date().toJSON()
...
以下JS将处理将ISO8601格式的UTC / GMT日期解析为本地日期时间。
if (typeof Date.fromISOString != 'function') {
//method to handle conversion from an ISO-8601 style string to a Date object
// Date.fromISOString("2009-07-03T16:09:45Z")
// Fri Jul 03 2009 09:09:45 GMT-0700
Date.fromISOString = function(input) {
var date = new Date(input); //EcmaScript5 includes ISO-8601 style parsing
if (!isNaN(date)) return date;
//early shorting of invalid input
if (typeof input !== "string" || input.length < 10 || input.length > 40) return null;
var iso8601Format = /^(\d{4})-(\d{2})-(\d{2})((([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d{1,12}))?)?)?)?)?([Zz]|([-+])(\d{2})\:?(\d{2}))?$/;
//normalize input
var input = input.toString().replace(/^\s+/,'').replace(/\s+$/,'');
if (!iso8601Format.test(input))
return null; //invalid format
var d = input.match(iso8601Format);
var offset = 0;
date = new Date(+d[1], +d[2]-1, +d[3], +d[7] || 0, +d[8] || 0, +d[10] || 0, Math.round(+("0." + (d[12] || 0)) * 1000));
//use specified offset
if (d[13] == 'Z') offset = 0-date.getTimezoneOffset();
else if (d[13]) offset = ((parseInt(d[15],10) * 60) + (parseInt(d[16],10)) * ((d[14] == '-') ? 1 : -1)) - date.getTimezoneOffset();
date.setTime(date.getTime() + (offset * 60000));
if (date.getTime() <= new Date(-62135571600000).getTime()) // CLR DateTime.MinValue
return null;
return date;
};
}
用法示例:
SELECT
Getdate=GETDATE()
,SysDateTimeOffset=SYSDATETIMEOFFSET()
,SWITCHOFFSET=SWITCHOFFSET(SYSDATETIMEOFFSET(),0)
,GetutcDate=GETUTCDATE()
GO
返回值:
Getdate SysDateTimeOffset SWITCHOFFSET GetutcDate
2013-12-06 15:54:55.373 2013-12-06 15:54:55.3765498 -08:00 2013-12-06 23:54:55.3765498 +00:00 2013-12-06 23:54:55.373