web-dev-qa-db-ja.com

SQL Server 2008-GMT(UTC)日時をローカル日時に変換する方法

各挿入は挿入されたときにも格納するため、GETDATE()を値の1つとして渡す挿入プロシージャがあります。これは、GMTを使用するSQL Azureでホストされています。

今、私がメッセージを受信して​​いるとき、それらのタイムスタンプ列にそれぞれのGMT日付が保存されています。私のページにアクセスしているとき、どこにいてもこれをローカルdatetimeに変換するにはどうすればよいですか?

ありがとう。

10
slandau

あなたはこのようなことをすることができます:

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
11
Alex Aza

夏時間の問題は別として、次のように単純化してみませんか。

yourDateTime - getutcdate() + getdate()
5
bwperrin

例として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の保持を説明するために、ロジックを関数呼び出しに抽象化することをお勧めします。ただし、それほど難しくはないはずです。

1
Tracker1
_/*
=============================================
 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日であるその他の結果が正しくない場合がありました。

0

これは、履歴データを処理する関数です。私はそれをイギリスの夏の時間のために書いた-残念ながら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
0
Rich