SQL Server:准确地在UTC和本地时间之间进行转换

时间:2012-06-16 12:14:22

标签: sql-server database tsql datetime utc

我在SQL Server 2008 R2数据库中有几列需要从本地时间(sql server所在的时区)转换为UTC。

我在StackOverflow上看到了不少类似的问题,但答案都无法正常使用夏令时,他们只考虑当前的差异并抵消了日期。

2 个答案:

答案 0 :(得分:7)

我无法单独使用T-SQL找到任何方法。我用SQL CLR解决了它:

public static class DateTimeFunctions
{
    [SqlFunction(IsDeterministic = true, IsPrecise = true)]
    public static DateTime? ToLocalTime(DateTime? dateTime)
    {
        if (dateTime == null) return null;
        return dateTime.Value.ToLocalTime();
    }

    [SqlFunction(IsDeterministic = true, IsPrecise = true)]
    public static DateTime? ToUniversalTime(DateTime? dateTime)
    {
        if (dateTime == null) return null;
        return dateTime.Value.ToUniversalTime();
    }
}

以下注册脚本:

CREATE FUNCTION ToLocalTime(@dateTime DATETIME2) RETURNS DATETIME2 AS EXTERNAL NAME AssemblyName.[AssemblyName.DateTimeFunctions].ToLocalTime; 
GO
CREATE FUNCTION ToUniversalTime(@dateTime DATETIME2) RETURNS DATETIME2 AS EXTERNAL NAME AssemblyName.[AssemblyName.DateTimeFunctions].ToUniversalTime; 

在UTC时间被迫转换这种努力是一种耻辱。

请注意,这些函数将本地时间解释为服务器的本地时间。建议将客户端和服务器设置为相同的时区,以避免混淆。

答案 1 :(得分:1)

    DECLARE @convertedUTC datetime, @convertedLocal datetime
    SELECT DATEADD(
                    HOUR,                                    -- Add a number of hours equal to
                    DateDiff(HOUR, GETDATE(), GETUTCDATE()), -- the difference of UTC-MyTime
                    GetDate()                                -- to MyTime
                    )

    SELECT @convertedUTC = DATEADD(HOUR,DateDiff(HOUR, GETDATE(), GETUTCDATE()),GetDate()) --Assign the above to a var

    SELECT DATEADD(
                    HOUR,                                    -- Add a number of hours equal to
                    DateDiff(HOUR, GETUTCDATE(),GETDATE()), -- the difference of MyTime-UTC
                    @convertedUTC                           -- to MyTime
                    )

    SELECT @convertedLocal = DATEADD(HOUR,DateDiff(HOUR, GETUTCDATE(),GETDATE()),GetDate()) --Assign the above to a var


    /* Do our converted dates match the real dates? */
    DECLARE @realUTC datetime = (SELECT GETUTCDATE())
    DECLARE @realLocal datetime = (SELECT GetDate())

    SELECT 'REAL:', @realUTC AS 'UTC', @realLocal AS 'Local'
    UNION
    SELECT 'CONVERTED:', @convertedUTC AS 'UTC', @convertedLocal AS 'Local'