SQL Server 2008 - Как конвертировать GMT (UTC) datetime в локальное datetime?
У меня есть вставка proc, которая проходит в GETDATE()
как одно из значений, потому что каждая вставка также сохраняется, когда она была вставлена. Это размещено на SQL Azure, которое использует GMT.
Теперь, когда я получаю сообщения, у меня есть дата GMT, которая хранится для каждого из них в столбцах временной метки, как мне преобразовать ее в локальный datetime
, где бы вы ни находились, когда вы обращаетесь к моей странице?
Спасибо.
Ответы
Ответ 1
Вы можете сделать что-то вроде этого:
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
Ответ 2
Помимо проблемы с летней экономией, почему бы не упростить:
yourDateTime - getutcdate() + getdate()
Ответ 3
Для 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... но это не должно быть чрезмерно сложно.
Ответ 4
Здесь функция, которая работает с историческими данными. Я написал это для британского летнего времени, что, к сожалению, происходит в последнее воскресенье марта и октября, делая логику немного запутанной.
В основном жесткая кодированная дата 01/03 ищет последнее воскресенье марта, а 01/10 ищет последнее воскресенье октября (когда часы идут вперед и назад). ПРИМЕЧАНИЕ: ЕСЛИ ВАШ СЕРВЕР ИСПОЛЬЗУЕТСЯ НАЦИОНАЛЬНЫЕ ДАТЫ, ВОЗВРАЩАЮТ ЭТИ ДВЕ ДЕТАЛИ ДЕТАЛЯ ДО 03/01 и 10/01!!!!
Таким образом, вы отправляете ему дату UTC и автоматически определяете, является ли историческая дата BST или GMT. Не лучшая вещь для использования в большом наборе данных, но это решение.
Запустите этот script, чтобы создать функцию и вызвать ее встроенный в свой выбор. У 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
Ответ 5
/*
=============================================
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
Boom.