Sql server TSQL:如何将本地时间转换为UTC?(SQL Server 2008)

Sql server TSQL:如何将本地时间转换为UTC?(SQL Server 2008),sql-server,tsql,sql-server-2008,timezone,utc,Sql Server,Tsql,Sql Server 2008,Timezone,Utc,我们正在处理一个需要处理来自不同时区和夏令时设置的全局时间数据的应用程序。其思想是在内部以UTC格式存储所有内容,并且仅针对本地化用户界面进行来回转换。SQL Server是否提供任何机制来处理给定时间、国家和时区的翻译 这一定是一个常见的问题,所以我很惊讶谷歌没有找到任何有用的东西 有什么指示吗?是的,在某种程度上是详细的 我使用的方法(2008年之前)是在插入数据库之前在.NET业务逻辑中进行转换。您可以使用GETUTCDATE()函数获取UTC日期时间 可能您可以选择GETUTCDATE(

我们正在处理一个需要处理来自不同时区和夏令时设置的全局时间数据的应用程序。其思想是在内部以UTC格式存储所有内容,并且仅针对本地化用户界面进行来回转换。SQL Server是否提供任何机制来处理给定时间、国家和时区的翻译

这一定是一个常见的问题,所以我很惊讶谷歌没有找到任何有用的东西


有什么指示吗?

是的,在某种程度上是详细的
我使用的方法(2008年之前)是在插入数据库之前在.NET业务逻辑中进行转换。

您可以使用GETUTCDATE()函数获取UTC日期时间 可能您可以选择GETUTCDATE()和GETDATE()之间的差异,并使用此差异将日期调整为UTC


但我同意前面的观点,即在业务层(例如在.NET中)控制正确的日期时间要容易得多

SQL Server 2008有一个名为
datetimeoffset
的类型。这对这类东西很有用

然后,您可以使用功能
SWITCHOFFSET
将其从一个时区移动到另一个时区,但仍保持相同的UTC值


Rob

这适用于当前与SQL Server主机具有相同UTC偏移量的日期;它没有考虑到夏令时的变化。将
您的_日期
替换为要转换的本地日期


选择DATEADD(第二个,DATEDIFF(第二个,GETDATE(),GETUTCDATE()),您的日期)

虽然这些答案中的一些将使您大致了解情况,但由于夏令时的原因,您无法对SQLServer2005及更早版本的任意日期执行您试图执行的操作。使用当前本地UTC和当前UTC之间的差值将得到当前存在的偏移量。我还没有找到一种方法来确定该日期的补偿额

也就是说,我知道SQLServer2008提供了一些新的日期函数,可以解决这个问题,但是使用早期版本的用户需要注意这些限制


我们的方法是保持UTC并在客户端执行转换,在客户端我们可以更好地控制转换的准确性。

我倾向于使用DateTimeOffset来存储与本地事件无关的所有日期时间(例如:会议/聚会等,下午12点到3点在博物馆)

要以UTC格式获取当前DTO,请执行以下操作:

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进行通信。请参阅:
newdate().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;
  };
}
if(typeof Date.fromISOString!=“函数”){
//方法处理从ISO-8601样式字符串到日期对象的转换
//日期:fromISOString(“2009-07-03T16:09:45Z”)
//2009年7月3日星期五09:09:45 GMT-0700
Date.fromISOString=函数(输入){
var date=新日期(输入);//ECMAScript 5包括ISO-8601样式的解析
如果(!isNaN(日期))返回日期;
//无效输入的早期短路
if(typeof input!=“string”| | input.length<10 | | input.length>40)返回null;
var ISO8601格式=/^(\d{4})-(\d{2})([T](\d{2}):(\d{2})(:(\d{2})(\.(\d{1,12}))?)?)?([Zz]([-+])(\d{2}:(\d{2})(\.(\d{1,12}))?)?)?)?([Zz 124;([-+]):(\ d{2}:?)/;
//规范化输入
var input=input.toString().replace(/^\s+/,'').replace(/\s+$/,'');
如果(!ISO8601格式测试(输入))
返回null;//格式无效
var d=输入匹配(ISO8601格式);
var偏移=0;
日期=新日期(+d[1]、+d[2]-1、+d[3]、+d[7]|| 0、+d[8]| 0、+d[10]| 0、数学四舍五入(+(“0.”+(d[12]| 0))*1000);
//使用指定的偏移量
如果(d[13]=“Z”)偏移量=0-date.getTimezoneOffset();
否则如果(d[13])偏移量=((parseInt(d[15],10)*60)+(parseInt(d[16],10))*((d[14]='-')?1:-1))-date.getTimezoneOffset();
date.setTime(date.getTime()+(偏移量*60000));
if(date.getTime()示例用法:

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

对于SQL Server 2016和更新版本以及Azure SQL数据库,请使用内置的

对于较旧版本的SQL Server,您可以使用my project在IANA标准时区之间进行转换

UTC到本地的格式如下:

SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'America/Los_Angeles')
SELECT Tzdb.LocalToUtc('2015-07-01 00:00:00', 'America/Los_Angeles', 1, 1)
UTC的本地设置如下所示:

SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'America/Los_Angeles')
SELECT Tzdb.LocalToUtc('2015-07-01 00:00:00', 'America/Los_Angeles', 1, 1)
当本地时间值受夏令时影响时,数字选项是控制行为的标志。这些在项目文档中有详细描述。

7年过去了,…
实际上,SQL Server 2016的新功能正好满足您的需要。
它在时区调用,并根据DST(夏令时)的变化将日期转换为指定的时区。
更多信息请点击此处:
以下是将一个区域
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
注意:
在时区
仅适用于SQL Server 2016+,其优点是转换到特定时区时自动考虑日光

子字符串(CONVERT(VARCHAR(34),SYSDATETIMEOFFSET()),29,5)

返回(例如):

-06:0


并非100%肯定这将始终有效。

谢谢,这是一个好主意,但它只适用于一个时区-本地机器。不过,我们需要它适用于任意时区…这不包括夏令时不!差异取决于确切日期。它取决于夏令时。在我的情况下,我只需要1时区,这很好!谢谢。如果你知道你今天的跑步情况,这很有效,而不是历史记录,谢谢不!差异取决于确切的日期。这取决于夏令时。不考虑夏令时。我使用类似的解决方案已经有一段时间了,它导致了重大问题。你必须确定你选择的日期是否正确e与DST中的is进行比较。SWITCHOFFSET不