代码之家  ›  专栏  ›  技术社区  ›  BuschnicK

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

  •  62
  • BuschnicK  · 技术社区  · 17 年前

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

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

    有什么建议吗?

    10 回复  |  直到 11 年前
        1
  •  66
  •   Sam    13 年前

    这适用于当前与SQL Server主机具有相同UTC偏移量的日期;它没有考虑到夏令时的变化。代替 YOUR_DATE

    SELECT DATEADD(second, DATEDIFF(second, GETDATE(), GETUTCDATE()), YOUR_DATE);

        2
  •  57
  •   Piotr Owsiak    9 年前

    7年过去了。。。
    实际上,SQL Server 2016的这一新功能正是您所需要的。
    它在时区调用,并根据DST(夏令时)的变化将日期转换为指定的时区。
    https://msdn.microsoft.com/en-us/library/mt612795.aspx

        3
  •  22
  •   user890155    14 年前

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

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

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

        4
  •  16
  •   Seva    7 年前

    下面是转换一个区域的代码 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+ 优点是 自动考虑日光

        5
  •  16
  •   Matt Johnson-Pint    6 年前

    AT TIME ZONE statement .

    对于较旧版本的SQL Server,您可以使用我的 SQL Server Time Zone Support 项目将在IANA标准时区之间转换, as listed here .

    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)
    

    数字选项是用于控制本地时间值受夏令时影响时的行为的标志。这些在项目文件中有详细描述。

        6
  •  14
  •   marc_s MisterSmith    11 年前

    datetimeoffset . 这对这类东西很有用。

    http://msdn.microsoft.com/en-us/library/bb630289.aspx

    然后你可以使用这个函数 SWITCHOFFSET 将其从一个时区移动到另一个时区,但仍保持相同的UTC值。

    http://msdn.microsoft.com/en-us/library/bb677244.aspx

    抢劫

        7
  •  4
  •   Tracker1    14 年前

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

    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;
      };
    }
        8
  •  3
  •   AdaTheDev    17 年前

    是的,在某种程度上是详细的 here .

        9
  •  1
  •   Bogdan_Ch    17 年前

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

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

        10
  •  0
  •   Jared Beach    5 年前

    SUBSTRING(CONVERT(VARCHAR(34), SYSDATETIMEOFFSET()), 29, 5)

    返回(例如):

    -06:0

    不是100%肯定的,这将始终有效。

        11
  •  -1
  •   rgettman    12 年前

    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