TSQL:如何将本地时间转换为UTC? (SQL Server 2008)
我们正在处理需要处理来自不同时区和夏令时设置的全球时间数据的应用程序。 这个想法是在内部以UTC格式存储所有内容,只能来回转换本地化的用户界面。 SQL Server是否提供了一个机制来处理一段时间,一个国家和一个时区的翻译?
这一定是一个常见的问题,所以我很惊讶谷歌不会出现任何可用的东西。
任何指针?
7年过去了…
实际上有这个新的SQL Server 2016function,正是你所需要的。
它被称为AT TIME ZONE,并且考虑到夏令时(DST)的变化,它将date转换为指定的时区。
更多信息在这里: https : //msdn.microsoft.com/en-us/library/mt612795.aspx
这适用于当前具有与SQL Server主机相同的UTC偏移量的date; 它不考虑夏时制的变化。 将YOUR_DATE
replace为要转换的本地date。
SELECT DATEADD(second, DATEDIFF(second, GETDATE(), GETUTCDATE()), YOUR_DATE);
虽然这些答案中的一部分会让你大吃一惊,但是由于夏时制的原因,你不能为SqlServer 2005和更早的版本做任何你想做的事情。 使用当前本地和当前UTC之间的差异将给我今天的偏移量。 我还没有find一种方法来确定在该date抵消的东西。
也就是说,我知道SqlServer 2008提供了一些可以解决这个问题的新date函数,但是使用早期版本的人需要知道这个限制。
我们的方法是坚持UTC并在客户端执行转换,我们可以更好地控制转换的准确性。
SQL Server 2008有一个称为datetimeoffset
的types。 这对于这种types的东西非常有用。
http://msdn.microsoft.com/en-us/library/bb630289.aspx
然后,您可以使用SWITCHOFFSET
function将其从一个时区移到另一个时区,但仍保持相同的UTC值。
http://msdn.microsoft.com/en-us/library/bb677244.aspx
抢
您可以使用我的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)
数字选项是用于控制本地时间值受夏令时影响时的行为的标志。 这些在项目文件中有详细的描述。
我倾向于使用DateTimeOffset来处理与本地事件无关的所有date – 时间存储(即:会议/聚会等,下午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 / GMTdateparsing为本地date时间。
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; }; }
是的,在某种程度上这里详细说明。
我使用的方法(2008之前)是在插入数据库之前,在.NET业务逻辑中进行转换。
您可以使用GETUTCDATE()函数获取UTC datetime可能您可以selectGETUTCDATE()和GETDATE()之间的差异,并使用此差异来将您的date调整为UTC
但是,我同意以前的信息,在业务层中控制正确的date时间要容易得多(例如,在.NET中)。
这里代码转换一个区域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+上运行,而且这个优势在转换到特定时区时会自动考虑Daylight
示例用法:
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