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

时间:2009-07-30 08:15:59

标签: sql-server tsql sql-server-2008 timezone utc

我们正在处理需要处理来自不同时区和夏令时设置的全球时间数据的应用程序。我们的想法是在内部以UTC格式存储所有内容,只为本地化用户界面来回转换。 SQL Server是否提供了处理给定时间,国家和时区的翻译的任何机制?

这一定是一个常见问题,所以我很惊讶谷歌不会发现任何可用的东西。

任何指针?

11 个答案:

答案 0 :(得分:57)

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

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

答案 1 :(得分:33)

7年过去了...... 实际上,这个新的SQL Server 2016功能正是您所需要的 它被称为AT TIME ZONE,它根据DST(夏令时)的变化将日期转换为指定的时区 更多信息: https://msdn.microsoft.com/en-us/library/mt612795.aspx

答案 2 :(得分:21)

虽然这些答案中的一些会让你大吃一惊,但由于夏令时,你无法为SqlServer 2005及更早版本的任意日期做些什么。使用当前本地和当前UTC之间的差异将给出我今天存在的偏移量。我还没有办法确定相关日期的偏移量。

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

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

答案 3 :(得分:14)

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

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

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

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

罗布

答案 4 :(得分:14)

您可以使用我的SQL Server Time Zone Support项目在IANA标准时区as listed here之间进行转换。

UTC to Local就像这样:

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)

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

答案 5 :(得分:9)

此处将一个区域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 到特定的时区

答案 6 :(得分:4)

我倾向于将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;
  };
}

答案 7 :(得分:3)

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

答案 8 :(得分:2)

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

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

答案 9 :(得分:0)

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

返回(例如):

-06:0

并非 100% 肯定这总是有效的。

答案 10 :(得分:-1)

样本用法:

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
相关问题