selectステートメントで日時列をUTCから現地時間に変換する


208

いくつかのSQL選択クエリを実行していますが、UTC日時列を現地時間に変換して、クエリ結果に現地時間として表示したいと考えています。この変換をコードで行うのではなく、データベースに対して手動でランダムなSQLクエリを実行する場合に注意してください。


この質問はあなたの状況に似ていますか? stackoverflow.com/questions/3404646/...
タリン東

回答:


322

これは、SQL Server 2008以降で次のように実行できます。

SELECT CONVERT(datetime, 
               SWITCHOFFSET(CONVERT(datetimeoffset, 
                                    MyTable.UtcColumn), 
                            DATENAME(TzOffset, SYSDATETIMEOFFSET()))) 
       AS ColumnInLocalTime
FROM MyTable

冗長度を下げることもできます。

SELECT DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), GETDATE()), MyTable.UtcColumn) 
       AS ColumnInLocalTime
FROM MyTable

操作はアトミックではないため、何をする場合でも、日付の減算には使用しないください。-システムの日付時刻とローカルの日付時刻の競合状態が異なるときに(つまり、非原子的に)チェックされるため、結果が不確定になることがあります。 。

この回答ではDSTが考慮されていないことに注意してください。DST調整を含める場合は、次のSO質問も参照してください。

SQL Serverで夏時間の開始および終了関数を作成する方法


38
このアカウントで夏時間を節約する方法はありますか?
Steve

15
ここにはタイムゾーンの名前が表示されないため、これは正しくありません。算術演算によって現地時間に変換できると仮定するのは本当に悪い考えです
JonnyRaa

7
@MichaelGoldshteynタイムゾーンオフセットがある場合、時間の論理タイムゾーンがまだわかりません。タイムゾーンは社会的なものであり、政府によってさまざまな時点で変更できます。タイムゾーンのオフセットは、時間/履歴のさまざまな時点で異なる場合があります(夏時間が一般的です)。UTCからの現在のオフセットで時間をオフセットしています...さらにポイントは、クライアントではなくサーバーのタイムゾーンを提供することです。これは、別の国でホスティングしている場合はさらに問題になる可能性があります。
JonnyRaa 2015

4
@Niloofar簡単な答えは、あなたはそうしない、すべきではないということです。日時は常にUTCで保存する必要があります(できれば、データベースサーバーのクロックに基づいてください。Webサーバー、アプリケーションサーバーのクロックではなく、クライアントのクロックではありません)。その日時の表示はUIレイヤーの関数であり、日時を必要な形式(必要に応じてタイムゾーンを含む)に変換します。
Robert McKee

11
SQL Azureを使用している人にとっては、日付/時刻関数はすべてUTCを返すため、このアプローチは機能しません。したがって、GETDATE()とGETUTCDATE()を比較しても、何も操作できず、結果は最初と同じです。
Brian Surowiec 2016年

59

これらの例のいずれも、UTCとして格納された日時を指定されたタイムゾーン(Azure SQLデータベースはUTCとして実行されるため、サーバーのタイムゾーンではありません)の日時に取得するのに役立ちませんでした。これは私がそれを処理した方法です。エレガントではありませんが、シンプルであり、他のテーブルを維持しなくても正しい答えが得られます。

select CONVERT(datetime, SWITCHOFFSET(dateTimeField, DATEPART(TZOFFSET, 
dateTimeField AT TIME ZONE 'Eastern Standard Time')))

4
2016でのみ機能し、システムレジストリを使用します。しかし、Azureの優れたソリューションです。
Dan Cundy 2017

2
これはUTCに保存されている紺碧の時間で機能します。ありがとうございました
Null

3
タイムゾーンに使用できる文字列のリストは次のとおりです。stackoverflow.com
Matt Kemp

1
SQL 2016とAT TIME ZONE構文を使用している場合は、stackoverflow.com / a / 44941536/112764を検討してください。複数のを連結するだけで、複数の変換をチェーン化できますat time zone <blah>
NateJ

3
これも少し奇妙ですが、いくつかの非常に基本的なテストはこれでうまくいくように見えます- ステートメントをdateTimeField AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time'チェーンするだけAT TIME ZONEです。(@NateJは、私が今見るこの上でこれについて言及しました)
David Mohundro

22

ローカルの日付時刻が指定さEastern Standard Timeれていて、UTCからUTCに変換する場合は、Azure SQLおよびSQL Server 2016以降で次のことができます。

SELECT YourUtcColumn AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time' AS
       LocalTime
FROM   YourTable

タイムゾーン名の完全なリストは、次の場所にあります。

SELECT * FROM sys.time_zone_info 

そして、はい、タイムゾーンの名前は不適切です。たとえそれがEastern Standard Time夏時間であるかは考慮されています。


2
タイムゾーンとオフセットは、SQL Serverの次の場所にもあります。SELECT * FROM sys.time_zone_info
rayzinnz

21

サーバーの場所以外の変換が必要な場合は、次の関数を使用して、標準のオフセットを渡し、米国の夏時間を考慮することができます。

-- =============================================
-- Author:      Ron Smith
-- Create date: 2013-10-23
-- Description: Converts UTC to DST
--              based on passed Standard offset
-- =============================================
CREATE FUNCTION [dbo].[fn_UTC_to_DST]
(
    @UTC datetime,
    @StandardOffset int
)
RETURNS datetime
AS
BEGIN

    declare 
        @DST datetime,
        @SSM datetime, -- Second Sunday in March
        @FSN datetime  -- First Sunday in November

    -- get DST Range
    set @SSM = datename(year,@UTC) + '0314' 
    set @SSM = dateadd(hour,2,dateadd(day,datepart(dw,@SSM)*-1+1,@SSM))
    set @FSN = datename(year,@UTC) + '1107'
    set @FSN = dateadd(second,-1,dateadd(hour,2,dateadd(day,datepart(dw,@FSN)*-1+1,@FSN)))

    -- add an hour to @StandardOffset if @UTC is in DST range
    if @UTC between @SSM and @FSN
        set @StandardOffset = @StandardOffset + 1

    -- convert to DST
    set @DST = dateadd(hour,@StandardOffset,@UTC)

    -- return converted datetime
    return @DST

END

GO

2
Ron Smith私はこれが古い投稿であることを知っていますが、ハードコーディングされた '0314'と '1107'がDST範囲の取得で何を表すのか知りたいと思っていました。DTSにより変更されるハードコードされた日であるようです。3月の第2日曜日と11月の第1日曜日がカレンダーのどこに当たるかに基づいて日が変わるため、これを計算された日付にする必要があるのに、なぜこれをハードコーディングするのでしょうか。ハードコーディングされた日は、このコードに根本的な欠陥をもたらします。
マイク

2
良い質問:)これらは、3月の第2日曜日と11月の第1日曜日が発生する可能性がある最大の日付です。次の行は、変数を実際の日付に設定します。
ロン・スミス

8

新しいSQL Server 2016の機会を使用する:

CREATE FUNCTION ToLocalTime(@dtUtc datetime, @timezoneId nvarchar(256))
RETURNS datetime
AS BEGIN

return @dtUtc AT TIME ZONE 'UTC' AT TIME ZONE @timezoneId

/* -- second way, faster

return SWITCHOFFSET(@dtUtc , DATENAME(tz, @dtUtc AT TIME ZONE @timezoneId))

*/

/* -- third way

declare @dtLocal datetimeoffset
set @dtLocal = @dtUtc AT TIME ZONE @timezoneId
return dateadd(minute, DATEPART (TZoffset, @dtLocal), @dtUtc)

*/

END
GO

しかし、clrプロシージャは5倍速く動作します: '-(

1つのTimeZoneのオフセットが冬時間または夏時間に変更される可能性があることに注意してください。例えば

select cast('2017-02-08 09:00:00.000' as datetime) AT TIME ZONE 'Eastern Standard Time'
select cast('2017-08-08 09:00:00.000' as datetime) AT TIME ZONE 'Eastern Standard Time'

結果:

2017-02-08 09:00:00.000 -05:00
2017-08-08 09:00:00.000 -04:00

一定のオフセットを追加することはできません。


5

データベースでCLRを有効にすることがオプションであり、SQLサーバーのタイムゾーンを使用している場合は、.Netで簡単に書き込むことができます。

public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static SqlDateTime fn_GetLocalFromUTC(SqlDateTime UTC)
    {
        if (UTC.IsNull)
            return UTC;

        return new SqlDateTime(UTC.Value.ToLocalTime());
    }
}

UTC日時値が入力され、サーバーに対するローカル日時値が出力されます。null値はnullを返します。


5

これを正しい一般的な方法で行う簡単な方法はありません。

まず第一に、オフセットは問題の日付、タイムゾーンおよびDSTに依存することを理解する必要があります。 GetDate()-GetUTCDate今日はサーバーのTZでのオフセットのみを提供しますが、これは関係ありません。

私は2つの有効なソリューションしか見たことがなく、検索もたくさんあります。

1)タイムゾーンやTZごとのDSTルールなどのベースデータのテーブルがいくつかあるカスタムSQL関数。機能しますが、あまりエレガントではありません。コードを所有していないので投稿できません。

編集:これはこのメソッドの例です https://gist.github.com/drumsta/16b79cee6bc195cd89c8

2).netアセンブリをdbに追加します。.Netはこれを非常に簡単に行うことができます。これは非常にうまく機能していますが、欠点はサーバーレベルでいくつかのパラメーターを構成する必要があり、データベースを復元する場合など、構成が簡単に壊れることです。この方法を使用していますが、コードを所有していないため、投稿できません。


4

これらのどれも私にとってはうまくいきませんでしたが、これは100%うまくいきました。これが私がそうであったようにそれを変換しようとしている他の人を助けることができることを願っています。

CREATE FUNCTION [dbo].[fn_UTC_to_EST]
(
    @UTC datetime,
    @StandardOffset int
)
RETURNS datetime
AS
BEGIN

declare 
    @DST datetime,
    @SSM datetime, -- Second Sunday in March
    @FSN datetime  -- First Sunday in November
-- get DST Range
set @SSM = DATEADD(dd,7 + (6-(DATEDIFF(dd,0,DATEADD(mm,(YEAR(GETDATE())-1900) * 12 + 2,0))%7)),DATEADD(mm,(YEAR(GETDATE())-1900) * 12 + 2,0))+'02:00:00' 
set @FSN = DATEADD(dd, (6-(DATEDIFF(dd,0,DATEADD(mm,(YEAR(GETDATE())-1900) * 12 + 10,0))%7)),DATEADD(mm,(YEAR(GETDATE())-1900) * 12 + 10,0)) +'02:00:00'

-- add an hour to @StandardOffset if @UTC is in DST range
if @UTC between @SSM and @FSN
    set @StandardOffset = @StandardOffset + 1

-- convert to DST
set @DST = dateadd(hour,@StandardOffset,@UTC)

-- return converted datetime
return @DST

END

1
これは受け入れられる答えになるはずです。私が変更する唯一のことは、実際には現地時間であり、StandardOffsetがパラメーターとして渡されるときに、EST時刻であることを意味する名前です。
グレッグガム

同意、...代わりにパラメータとしてオフセットを渡したの最良の答えは、私は、関数本体内にこれを追加しました:declare @StandardOffset int = datediff (hh, GETUTCDATE(), GETDATE())
トム・ウォーフィールド

以前の提案のフォローアップ-@StandardOffsetを計算する場合、DST補正を行う必要はありません。
トムウォーフィールド

3

これは夏時間、UTCオフセットを考慮したバージョンで、特定の年に固定されていません。

---------------------------------------------------------------------------------------------------
--Name:     udfToLocalTime.sql
--Purpose:  To convert UTC to local US time accounting for DST
--Author:   Patrick Slesicki
--Date:     3/25/2014
--Notes:    Works on SQL Server 2008R2 and later, maybe SQL Server 2008 as well.
--          Good only for US States observing the Energy Policy Act of 2005.
--          Function doesn't apply for years prior to 2007.
--          Function assumes that the 1st day of the week is Sunday.
--Tests:        
--          SELECT dbo.udfToLocalTime('2014-03-09 9:00', DEFAULT)
--          SELECT dbo.udfToLocalTime('2014-03-09 10:00', DEFAULT)
--          SELECT dbo.udfToLocalTime('2014-11-02 8:00', DEFAULT)
--          SELECT dbo.udfToLocalTime('2014-11-02 9:00', DEFAULT)
---------------------------------------------------------------------------------------------------
ALTER FUNCTION udfToLocalTime
    (
    @UtcDateTime    AS DATETIME
    ,@UtcOffset     AS INT = -8 --PST
    )
RETURNS DATETIME
AS 
BEGIN
    DECLARE 
        @PstDateTime    AS DATETIME
        ,@Year          AS CHAR(4)
        ,@DstStart      AS DATETIME
        ,@DstEnd        AS DATETIME
        ,@Mar1          AS DATETIME
        ,@Nov1          AS DATETIME
        ,@MarTime       AS TIME
        ,@NovTime       AS TIME
        ,@Mar1Day       AS INT
        ,@Nov1Day       AS INT
        ,@MarDiff       AS INT
        ,@NovDiff       AS INT

    SELECT
        @Year       = YEAR(@UtcDateTime)
        ,@MarTime   = CONVERT(TIME, DATEADD(HOUR, -@UtcOffset, '1900-01-01 02:00'))
        ,@NovTime   = CONVERT(TIME, DATEADD(HOUR, -@UtcOffset - 1, '1900-01-01 02:00'))
        ,@Mar1      = CONVERT(CHAR(16), @Year + '-03-01 ' + CONVERT(CHAR(5), @MarTime), 126)
        ,@Nov1      = CONVERT(CHAR(16), @Year + '-11-01 ' + CONVERT(CHAR(5), @NovTime), 126)
        ,@Mar1Day   = DATEPART(WEEKDAY, @Mar1)
        ,@Nov1Day   = DATEPART(WEEKDAY, @Nov1)

    --Get number of days between Mar 1 and DST start date
    IF @Mar1Day = 1 SET @MarDiff = 7
    ELSE SET @MarDiff = 15 - @Mar1Day

    --Get number of days between Nov 1 and DST end date
    IF @Nov1Day = 1 SET @NovDiff = 0
    ELSE SET @NovDiff = 8 - @Nov1Day

    --Get DST start and end dates
    SELECT 
        @DstStart   = DATEADD(DAY, @MarDiff, @Mar1)
        ,@DstEnd    = DATEADD(DAY, @NovDiff, @Nov1)

    --Change UTC offset if @UtcDateTime is in DST Range
    IF @UtcDateTime >= @DstStart AND @UtcDateTime < @DstEnd SET @UtcOffset = @UtcOffset + 1

    --Get Conversion
    SET @PstDateTime = DATEADD(HOUR, @UtcOffset, @UtcDateTime)
    RETURN @PstDateTime
END
GO

3

大量のデータがある場合、1回限りの関数の方法では遅すぎることがわかりました。それで、時間差の計算を可能にするテーブル関数に結合することでそれを行いました。基本的には、時間オフセットのある日時セグメントです。1年は4行になります。したがって、テーブル関数

dbo.fn_getTimeZoneOffsets('3/1/2007 7:00am', '11/5/2007 9:00am', 'EPT')

このテーブルを返します:

startTime          endTime   offset  isHr2
3/1/07 7:00     3/11/07 6:59    -5    0
3/11/07 7:00    11/4/07 6:59    -4    0
11/4/07 7:00    11/4/07 7:59    -5    1
11/4/07 8:00    11/5/07 9:00    -5    0

夏時間を考慮します。それがどのように使用されるかのサンプルは以下であり、完全なブログ投稿はここにあります

select mt.startTime as startUTC, 
    dateadd(hh, tzStart.offset, mt.startTime) as startLocal, 
    tzStart.isHr2
from MyTable mt 
inner join dbo.fn_getTimeZoneOffsets(@startViewUTC, @endViewUTC, @timeZone)  tzStart
on mt.startTime between tzStart.startTime and tzStart.endTime

DSTを正しく考慮していないようです。米国のみが存在し、DSTルールが変更されないと想定するかどうかは不明です。
vikjon0 2017

@ vikjon0はい、私がこれを構築したプロジェクトには米国のタイムゾーンしかありませんでした。
JBrooks 2017

2
 declare @mydate2 datetime
 set @mydate2=Getdate()
 select @mydate2 as mydate,
 dateadd(minute, datediff(minute,getdate(),@mydate2),getutcdate())

1

ロンの回答に誤りがあります。UTC相当が必要な現地時間の午前2時を使用します。私はロンの答えにコメントするのに十分な評判ポイントがないので、修正されたバージョンが以下に表示されます:

-- =============================================
-- Author:      Ron Smith
-- Create date: 2013-10-23
-- Description: Converts UTC to DST
--              based on passed Standard offset
-- =============================================
CREATE FUNCTION [dbo].[fn_UTC_to_DST]
(
    @UTC datetime,
    @StandardOffset int
)
RETURNS datetime
AS
BEGIN

declare 
    @DST datetime,
    @SSM datetime, -- Second Sunday in March
    @FSN datetime  -- First Sunday in November
-- get DST Range
set @SSM = datename(year,@UTC) + '0314' 
set @SSM = dateadd(hour,2 - @StandardOffset,dateadd(day,datepart(dw,@SSM)*-1+1,@SSM))
set @FSN = datename(year,@UTC) + '1107'
set @FSN = dateadd(second,-1,dateadd(hour,2 - (@StandardOffset + 1),dateadd(day,datepart(dw,@FSN)*-1+1,@FSN)))

-- add an hour to @StandardOffset if @UTC is in DST range
if @UTC between @SSM and @FSN
    set @StandardOffset = @StandardOffset + 1

-- convert to DST
set @DST = dateadd(hour,@StandardOffset,@UTC)

-- return converted datetime
return @DST

END

これは機能であり、バグではありません:)米国のほとんどは夏時間の午前2時に開始しますen.wikipedia.org/wiki/Daylight_saving_time
Ron Smith

@RonSmithはい、現地時間の午前2時に、指定されたUTC時刻がDSTの範囲にあるかどうかを検出するためにUTCに変換する必要があります。
jlspublic '18年


1

それは簡単です。Azure SQL Serverでこれを試してください。

SELECT YourDateTimeColumn AT TIME ZONE 'Eastern Standard Time' FROM YourTable

ローカルSQL Serverの場合:

SELECT CONVERT(datetime2, SWITCHOFFSET(CONVERT(datetimeoffset, gETDATE()), DATENAME(TzOffset, gETDATE() AT TIME ZONE 'Eastern Standard Time'))) FROM YourTable

1
夏時間の間にこれで何が起こりますか(タイムゾーンが特に「東部標準時」と言っているため)?
Mark

1

Azure SQLおよび@@VersionSQL Server 2016以上のユーザーの場合、以下はを使用した簡単な関数AT TIME ZONEです。

CREATE FUNCTION [dbo].[Global_Convert_UTCTimeTo_LocalTime]
(
   @LocalTimeZone        VARCHAR(50),
   @UTCDateTime          DATETIME
)
RETURNS DATETIME
AS
BEGIN
   DECLARE @ConvertedDateTime DATETIME;

   SELECT @ConvertedDateTime = @UTCDateTime AT TIME ZONE 'UTC' AT TIME ZONE @LocalTimeZone
   RETURN @ConvertedDateTime

END
GO

@LocalTimeZone取り得る値のタイプについては、このリンクに移動するか、KEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones


0

警告として-以下を使用する場合(分ではなくミリ秒に注意してください):

    SELECT DATEADD(ms, DATEDIFF(ms, GETUTCDATE(), GETDATE()), MyTable.UtcColumn) 
    AS ColumnInLocalTime
    FROM MyTable

DATEDIFF部分が常に同じ数を返すとは限らないことに注意してください。したがって、DateTimeをミリ秒まで比較するために使用しないでください。


0

この関数は、別のテーブルまたはループを使用する他のソリューションよりも高速であることがわかりました。これは単なる基本的なケースステートメントです。4月から10月までのすべての月に-4時間のオフセット(東部標準時)があることを考えると、フリンジデーのケース行をさらにいくつか追加する必要があります。それ以外の場合、オフセットは-5時間です。

これはUTCから東部標準時への変換に固有ですが、必要に応じて追加のタイムゾーン機能を追加できます。

USE [YourDatabaseName]
GO

/****** Object:  UserDefinedFunction [dbo].[ConvertUTCtoEastern]    Script Date: 11/2/2016 5:21:52 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


CREATE FUNCTION [dbo].[ConvertUTCtoEastern]
(
@dtStartDate DATETIME
)
RETURNS DATETIME
AS
BEGIN
DECLARE @Working DATETIME
DECLARE @Returned DATETIME

SET @Working = @dtStartDate
SET @Working = 
case when month(@Working) between 4 and 10 then dateadd(HH,-4,@Working) 
     when @Working between '2017-03-12' and '2017-11-05' then dateadd(HH,-4,@Working) 
     when @Working between '2016-03-13' and '2016-11-06' then dateadd(HH,-4,@Working) 
     when @Working between '2015-03-08' and '2015-11-01' then dateadd(HH,-4,@Working) 
     when @Working between '2014-03-09' and '2014-11-02' then dateadd(HH,-4,@Working) 
     when @Working between '2013-03-10' and '2013-11-03' then dateadd(HH,-4,@Working) 
     when @Working between '2012-03-11' and '2012-11-04' then dateadd(HH,-4,@Working) 
else dateadd(HH,-5,@Working) end

SET @Returned = @Working

RETURN @Returned

END


GO

0

これはDSTでサーバー時間を取得できるはずです

declare @dt datetime
set @dt = getutcdate() -- GMT equivalent

sysdatetimeoffsetはDSTを考慮に入れます

select [InputTime] = @dt
       , [LocalTime2] = dateadd(mi, datediff(mi, sysdatetimeoffset(),getdate()), @dt) 

0

最初の関数:イタリアのタイムゾーン(+ 1、+ 2)用に構成、日付の切り替え:3月と10月の最終日曜日、現在のタイムゾーンと日時の差をパラメーターとして返します。

Returns:
current timezone < parameter timezone ==> +1
current timezone > parameter timezone ==> -1
else 0

コードは次のとおりです。

CREATE FUNCTION [dbo].[UF_ADJUST_OFFSET]
(
    @dt_utc datetime2(7)
)
RETURNS INT
AS
BEGIN


declare @month int,
        @year int,
        @current_offset int,
        @offset_since int,
        @offset int,
        @yearmonth varchar(8),
        @changeoffsetdate datetime2(7)

declare @lastweek table(giorno datetime2(7))

select @current_offset = DATEDIFF(hh, GETUTCDATE(), GETDATE())

select @month = datepart(month, @dt_utc)

if @month < 3 or @month > 10 Begin Set @offset_since = 1 Goto JMP End

if @month > 3 and @month < 10 Begin Set @offset_since = 2 Goto JMP End

--If i'm here is march or october
select @year = datepart(yyyy, @dt_utc)

if @month = 3
Begin

Set @yearmonth = cast(@year as varchar) + '-03-'

Insert Into @lastweek Values(@yearmonth + '31 03:00:00.000000'),(@yearmonth + '30 03:00:00.000000'),(@yearmonth + '29 03:00:00.000000'),(@yearmonth + '28 03:00:00.000000'),
                         (@yearmonth + '27 03:00:00.000000'),(@yearmonth + '26 03:00:00.000000'),(@yearmonth + '25 03:00:00.000000')

--Last week of march
Select @changeoffsetdate = giorno From @lastweek Where  datepart(weekday, giorno) = 1

    if @dt_utc < @changeoffsetdate 
    Begin 
        Set @offset_since = 1 
    End Else Begin
        Set @offset_since = 2
    End
End

if @month = 10
Begin

Set @yearmonth = cast(@year as varchar) + '-10-'

Insert Into @lastweek Values(@yearmonth + '31 03:00:00.000000'),(@yearmonth + '30 03:00:00.000000'),(@yearmonth + '29 03:00:00.000000'),(@yearmonth + '28 03:00:00.000000'),
                         (@yearmonth + '27 03:00:00.000000'),(@yearmonth + '26 03:00:00.000000'),(@yearmonth + '25 03:00:00.000000')

--Last week of october
Select @changeoffsetdate = giorno From @lastweek Where  datepart(weekday, giorno) = 1

    if @dt_utc > @changeoffsetdate 
    Begin 
        Set @offset_since = 1 
    End Else Begin
        Set @offset_since = 2
    End
End

JMP:

if @current_offset < @offset_since Begin
    Set @offset = 1
End Else if @current_offset > @offset_since Set @offset = -1 Else Set @offset = 0

Return @offset

END

次に、日付を変換する関数

CREATE FUNCTION [dbo].[UF_CONVERT]
(
    @dt_utc datetime2(7)
)
RETURNS datetime
AS
BEGIN

    declare @offset int


    Select @offset = dbo.UF_ADJUST_OFFSET(@dt_utc)

    if @dt_utc >= '9999-12-31 22:59:59.9999999'
        set @dt_utc = '9999-12-31 23:59:59.9999999'
    Else
        set @dt_utc = (SELECT DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), GETDATE()), @dt_utc) )

    if @offset <> 0
        Set @dt_utc = dateadd(hh, @offset, @dt_utc)

    RETURN @dt_utc

END

0

-UTCからインド標準時を取得

CREATE FUNCTION dbo.getISTTime
(
@UTCDate datetime
)
RETURNS datetime
AS
BEGIN

    RETURN dateadd(minute,330,@UTCDate)

END
GO

0

これは関数なしで行うことができます。以下のコードは、夏時間を考慮してUTC時間を山岳時間に変換します。それに応じて、すべての-6および-7の数値をタイムゾーンに合わせて調整します(ESTの場合は、それぞれ-4および-5に調整します)。

--Adjust a UTC value, in the example the UTC field is identified as UTC.Field, to account for daylight savings time when converting out of UTC to Mountain time.
CASE
    --When it's between March and November, it is summer time which is -6 from UTC
    WHEN MONTH ( UTC.Field ) > 3 AND MONTH ( UTC.Field ) < 11 
        THEN DATEADD ( HOUR , -6 , UTC.Field )
    --When its March and the day is greater than the 14, you know it's summer (-6)
    WHEN MONTH ( UTC.Field ) = 3
        AND DATEPART ( DAY , UTC.Field ) >= 14 
        THEN
            --However, if UTC is before 9am on that Sunday, then it's before 2am Mountain which means it's still Winter daylight time.
            CASE 
                WHEN DATEPART ( WEEKDAY , UTC.Field ) = 1 
                    AND UTC.Field < '9:00'
                    --Before 2am mountain time so it's winter, -7 hours for Winter daylight time
                    THEN DATEADD ( HOUR , -7 , UTC.Field )
                --Otherwise -6 because it'll be after 2am making it Summer daylight time
                ELSE DATEADD ( HOUR , -6 , UTC.Field )
            END
    WHEN MONTH ( UTC.Field ) = 3
        AND ( DATEPART ( WEEKDAY , UTC.Field ) + 7 ) <= DATEPART ( day , UTC.Field ) 
        THEN 
            --According to the date, it's moved onto Summer daylight, but we need to account for the hours leading up to 2am if it's Sunday
            CASE 
                WHEN DATEPART ( WEEKDAY , UTC.Field ) = 1 
                    AND UTC.Field < '9:00'
                    --Before 9am UTC is before 2am Mountain so it's winter Daylight, -7 hours
                    THEN DATEADD ( HOUR , -7 , UTC.Field )
                --Otherwise, it's summer daylight, -6 hours
                ELSE DATEADD ( HOUR , -6 , UTC.Field )
            END
    --When it's November and the weekday is greater than the calendar date, it's still Summer so -6 from the time
    WHEN MONTH ( UTC.Field ) = 11
        AND DATEPART ( WEEKDAY , UTC.Field ) > DATEPART ( DAY , UTC.Field ) 
        THEN DATEADD ( HOUR , -6 , UTC.Field )
    WHEN MONTH ( UTC.Field ) = 11
        AND DATEPART ( WEEKDAY , UTC.Field ) <= DATEPART ( DAY , UTC.Field ) 
            --If the weekday is less than or equal to the calendar day it's Winter daylight but we need to account for the hours leading up to 2am.
            CASE 
                WHEN DATEPART ( WEEKDAY , UTC.Field ) = 1 
                    AND UTC.Field < '8:00'
                    --If it's before 8am UTC and it's Sunday in the logic outlined, then it's still Summer daylight, -6 hours
                    THEN DATEADD ( HOUR , -6 , UTC.Field )
                --Otherwise, adjust for Winter daylight at -7
                ELSE DATEADD ( HOUR , -7 , UTC.Field )
            END
    --If the date doesn't fall into any of the above logic, it's Winter daylight, -7
    ELSE
        DATEADD ( HOUR , -7 , UTC.Field )
END

0

文字列を再フォーマットし、正しい時刻に変換する必要があります。この場合、私はズールー族の時間が必要でした。

Declare @Date datetime;
Declare @DateString varchar(50);
set @Date = GETDATE(); 
declare @ZuluTime datetime;

Declare @DateFrom varchar (50);
Declare @DateTo varchar (50);
set @ZuluTime = DATEADD(second, DATEDIFF(second, GETDATE(), GETUTCDATE()), @Date);
set @DateString =  FORMAT(@ZuluTime, 'yyyy-MM-ddThh:mm:ssZ', 'en-US' )  
select @DateString;

0

Oracleに最適な方法:

ハードコードされた日時:

SELECT TO_CHAR(CAST((FROM_TZ(CAST(TO_DATE('2018-10-27 21:00', 'YYYY-MM-DD HH24:MI') AS TIMESTAMP), 'UTC') AT  TIME ZONE 'EET') AS DATE), 'YYYY-MM-DD HH24:MI') UTC_TO_EET FROM DUAL

Result: 2018-10-28 00:00

列とテーブルの名前:

SELECT TO_CHAR(CAST((FROM_TZ(CAST(COLUMN_NAME AS TIMESTAMP), 'UTC') AT  TIME ZONE 'EET') AS DATE), 'YYYY-MM-DD HH24:MI') UTC_TO_EET FROM TABLE_NAME

0

このようなコードを使用した変換を可能にする、UTCからローカルおよびローカルからUTC時間を実行するコードがあります

DECLARE @usersTimezone VARCHAR(32)='Europe/London'
DECLARE @utcDT DATETIME=GetUTCDate()
DECLARE @userDT DATETIME=[dbo].[funcUTCtoLocal](@utcDT, @usersTimezone)

そして

DECLARE @usersTimezone VARCHAR(32)='Europe/London'
DECLARE @userDT DATETIME=GetDate()
DECLARE @utcDT DATETIME=[dbo].[funcLocaltoUTC](@userDT, @usersTimezone)

関数は、NodaTimeによって提供されるIANA / TZDBのタイムゾーンのすべてまたはサブセットをサポートできます-https://nodatime.org/TimeZonesで完全なリストを参照してください

私のユースケースでは、「現在の」ウィンドウのみが必要であり、現在から約+/- 5年の範囲内で時間を変換できることを意味しています。つまり、私が使用した方法は、特定の日付範囲のタイムゾーン間隔ごとにコードを生成する方法が原因で、非常に広い期間が必要な場合にはおそらく適していません。

プロジェクトはGitHubにあります:https : //github.com/elliveny/SQLServerTimeConversion

これにより、この例のようにSQL関数コードが生成されます


0

データをデータベースにUTC日付として保存すると、次のように簡単なことができます。

select 
 [MyUtcDate] + getdate() - getutcdate()
from [dbo].[mytable]

これは、サーバーのポイントから常にローカルでありTIME ZONE 'your time zone name'、データベースがクライアントインストールのような別のタイムゾーンに移動された場合、ハードコーディングされたタイムゾーンがあなたに噛みつく可能性があるため、ATを探す必要はありません。


0

postgresではこれは非常にうまく機能します。時刻が保存された時刻「utc」をサーバーに通知し、特定のタイムゾーン(この場合は「ブラジル/東」)に変換するように要求します。

quiz_step_progresses.created_at  at time zone 'utc' at time zone 'Brazil/East'

以下の選択でタイムゾーンの完全なリストを取得します。

select * from pg_timezone_names;

詳細はこちら。

https://popsql.com/learn-sql/postgresql/how-to-convert-utc-to-local-time-zone-in-postgresql


-1

これは、dstを考慮に入れる簡単なものです

CREATE FUNCTION [dbo].[UtcToLocal] 
(
    @p_utcDatetime DATETIME 
)
RETURNS DATETIME
AS
BEGIN
    RETURN DATEADD(MINUTE, DATEDIFF(MINUTE, GETUTCDATE(), @p_utcDatetime), GETDATE())
END

6
これは実際には夏時間を考慮していません。ぜひお試しくださいSELECT DATEADD(MINUTE, DATEDIFF(MINUTE, GETUTCDATE(), '20150101'), GETDATE())。私は現在CEST(UTC + 2)ですが、DSTは元日には有効にならないため、正解は2015年1月1日01:00です。承認された回答と同様に、回答は2015年1月1日02:00を返します。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.