SQL Server 2008 - Как преобразовать время по Гринвичу (UTC) в местное время? - PullRequest
10 голосов
/ 20 мая 2011

У меня есть вставка proc, которая передает GETDATE() как одно из значений, потому что каждая вставка также сохраняет, когда она была вставлена.Это размещено в SQL Azure - который использует GMT.

Теперь, когда я получаю сообщения, у меня хранится дата GMT для каждого из них в столбцах меток времени, как мне преобразовать ее в локальный datetime где вы находитесь, когда заходите на мою страницу?

Спасибо.

Ответы [ 5 ]

11 голосов
/ 20 мая 2011

Вы можете сделать что-то вроде этого:

declare @InputUtcDateTime datetime2 = '2011-05-20 06:30:18'

declare @LocalDateTime datetime2 = dateadd(minute, datepart(TZoffset, sysdatetimeoffset()), @InputUtcDateTime)
print @LocalDateTime

или

declare @InputUtcDateTime datetime2 = '2011-05-20 06:30:18'

declare @LocalDateTime datetime2 = dateadd(minute, datediff(minute, sysutcdatetime(), sysdatetime()), @InputUtcDateTime)
print @LocalDateTime
5 голосов
/ 05 октября 2013

Помимо проблемы перехода на летнее время, почему бы не упростить:

yourDateTime - getutcdate() + getdate()
1 голос
/ 09 октября 2012

Для примера MST ... учитывая, что каждый DTM уже сохранен в GMT, это упрощает вещи.

SWITCHOFFSET(CONVERT(DATETIMEOFFSET, [ColumnName]), '-07:00')

Теперь, если ваша местная дата / время отличается от GMT / UTC, вы, вероятно, захотите использовать следующее ...

SWITCHOFFSET(TODATETIMEOFFSET([ColumnName], datepart(tz,sysdatetimeoffset())),'+00:00')

Вот разбивка.

  • SWITCHOFFSET - преобразует значение DateTimeOffset в другой часовой пояс, сохраняя смещение.
  • TODATETIMEOFFSET - преобразует значение DateTime в значение DateTimeOffset в указанном часовом поясе.
  • DATEPART - в данном случае получает часть часового пояса с местной датой.
  • '+00:00' - смещение цели, во втором примере - цель UTC / GMT, от локального ... предыдущий пример - MST.

ПРИМЕЧАНИЕ / ВНИМАНИЕ: я не считаю, что это объясняет переход на летнее время, что может быть проблемой для вас. Если абсолютная консервация не требуется, вы можете просто добавить дополнительный столбец с грубым преобразованием и идти вперед безопасно.

Возможно, вы захотите абстрагировать логику в вызов функции, чтобы учесть сохранение DST ... хотя это не должно быть чрезмерно сложно сделать.

0 голосов
/ 01 апреля 2019
/*
=============================================
 Author:        Mark Griffiths
 Create date:   29/05/2018
 Description:   BST runs from 02:00AM on the last Sunday of March to the same time on the last Sunday of October.       
    The Series of DATEDIFFs and DATEADDS below function as follows
    1   ●   Count the number of months there have been between the given date and start of computer time
    2   ●   Add that number of months to the end of the first month to get the end of the given month
    3   ●   Count the number of days there have been between the end of the given month and the first Saturday
    4   ●   Add that number of days to the calculated end of the given month
    5   ●   Add Two hours to that time as the clocks go back at 02:00 in the morning

    I know that the tabbing below makes it all look odd, but the description above is the best way I could find to comment things, given the nesting...
    The comments in the code below should help find the nesting levels and the numbers refer to the bullet points above.
=============================================
-- Test Variables --
DECLARE @GMTime DATETIME2(3) = '2018-05-01 12:00:00.000'
*/

    DECLARE @RealTime As DATETIME2(3)
    DECLARE @Year VARCHAR(4)
    SET @Year = CONVERT(VARCHAR,DATEPART(YEAR,@GMTime))
    DECLARE @StartOfBST AS DATETIME
    DECLARE @EndOfBST AS DATETIME
    SELECT
        @StartOfBST =
        DATEADD     -----------------------------------------------------------------------------------------
            (                                                       --                                      |
             HOUR                                                   --                                      |
            ,2                                                      --                                      |
            ,DATEADD    -----------------------------------------------------------------------------       |
                (                                                   --                              |       |
                 DAY                                                --                              |       |
                ,DATEDIFF       -------------------------------------------------------------       |       |
                    (                                               --                      |       |       |
                     DAY                                            --                      |       |       |
                    ,'19000107'                                     --                      |       |       5
                    ,DATEADD            ---------------------------------------------       |       |       |
                        (                                           --              |       3       4       |
                         MONTH                                      --              |       |       |       |
                        ,DATEDIFF(MONTH,0,CONVERT(DATE,'03/01/' + @Year)) -- 1      2       |       |       |
                        ,CONVERT(DATE,'01/30/1900')                 --              |       |       |       |
                        )               ---------------------------------------------       |       |       |
                    )/7*7       -------------------------------------------------------------       |       |
                    ,'19000107'                                     --                              |       |
                )               ---------------------------------------------------------------------       |
            ),      -----------------------------------------------------------------------------------------
    @EndOfBST =
        DATEADD(HOUR,2,DATEADD(day,DATEDIFF(day,'19000107',DATEADD(month,DATEDIFF(MONTH,0,CONVERT(DATE,'10/01/' + @Year)),30))/7*7,'19000107'))
    SET @RealTime = CASE
                    WHEN @GMTime BETWEEN @StartOfBST AND @EndOfBST THEN DATEADD(HOUR,-1,@GMTime)
                    ELSE @GMTime
                END
RETURN @RealTime;
--SELECT @RealTime
END
0 голосов
/ 24 июня 2013

Вот функция, которая работает с историческими данными. Я написал это для британского летнего времени, которое, к сожалению, происходит в последнее воскресенье марта и октября, что делает логику немного запутанной.

В основном, жестко закодированная часть 01/03 ищет последнее воскресенье марта, а 01/10 ищет последнее воскресенье октября (когда часы идут вперед и назад). ПРИМЕЧАНИЕ: ЕСЛИ ВАШ СЕРВЕР ИСПОЛЬЗУЕТ НАЦИОНАЛЬНЫЕ ДАТЫ США, ОБРАТИТЕСЬ К ЭТИМ ДВУМЯ ЧАСТЯМ ДАТЫ ДО 03/01 и 10/01 !!!!

Таким образом, вы указываете дату в формате UTC, и она автоматически определит, является ли историческая дата BST или GMT. Не самая лучшая вещь для использования с большим набором данных, но это решение.

Запустите этот сценарий, чтобы создать функцию и вызвать ее в своем выборе. В SQL 2008 есть проблема с пользовательскими функциями, кажется, он помещает красную линию под код, но он все еще запускает ее, пока вы используете префикс dbo (SELECT dbo.UTCConvert (yourdate) для его запуска)

CREATE FUNCTION [dbo].[UTCConvert] 
(

    @p1 datetime
)
RETURNS datetime
AS
BEGIN

    DECLARE @Result datetime


RETURN CASE 
WHEN
@p1 >
(DATEADD(day,DATEDIFF(day,'19000107',DATEADD(month,DATEDIFF(MONTH,0,'01/03/' + CAST(DATEPART(year,@p1) as CHAR)),30))/7*7,'19000107'))
AND
@p1<
(DATEADD(day,DATEDIFF(day,'19000107',DATEADD(month,DATEDIFF(MONTH,0,'01/10/' + CAST(DATEPART(year,@p1) as CHAR)),30))/7*7,'19000107'))
THEN (DATEADD(HH, 1, @p1)) 
ELSE @p1
END
END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...