各挿入は挿入されたときにも格納するため、GETDATE()
を値の1つとして渡す挿入プロシージャがあります。これは、GMTを使用するSQL Azureでホストされています。
今、私がメッセージを受信しているとき、それらのタイムスタンプ列にそれぞれのGMT日付が保存されています。私のページにアクセスしているとき、どこにいてもこれをローカルdatetime
に変換するにはどうすればよいですか?
ありがとう。
あなたはこのようなことをすることができます:
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
夏時間の問題は別として、次のように単純化してみませんか。
yourDateTime - getutcdate() + getdate()
例として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'
-2番目の例のターゲットオフセットは、ローカルからのUTC/GMTターゲットです...前者の例はMSTです。注/警告:これが夏時間の原因であるとは思わないので、問題になる可能性があります。絶対的な保存が必要ない場合は、2次カラムを追加し、大まかな変換を行って、安全に進んでください。
DSTの保持を説明するために、ロジックを関数呼び出しに抽象化することをお勧めします。ただし、それほど難しくはないはずです。
_/*
=============================================
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/31/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
_
*編集:45BC以来、1月には31日があったため、CONVERT(DATE,'01/30/1900')
をCONVERT(DATE,'01/31/1900')
に変更しました。これにより、2019年と、3月の最終日曜日が31日であるその他の結果が正しくない場合がありました。
これは、履歴データを処理する関数です。私はそれをイギリスの夏の時間のために書いた-残念ながら3月と10月の月の最後の日曜日に起こり、論理を少し複雑にしている。
基本的に、ハードコードされた日付部分01/03は3月の最後の日曜日を探し、01/10は10月の最後の日曜日を探します(時計がここを前後に移動するとき)。注:サーバーの場合ISネイティブUS日付を使用すると、これらの2つの日付部分が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