sourcecode

select 문의 Datetime 열을 UTC에서 로컬 시간으로 변환

codebag 2023. 4. 18. 22:36
반응형

select 문의 Datetime 열을 UTC에서 로컬 시간으로 변환

SQL 선택 쿼리를 몇 개 실행하고 있으며 UTC datetime 열을 로컬 시간으로 변환하여 쿼리 결과에 로컬 시간으로 표시하려고 합니다.코드로 변환하는 것이 아니라 데이터베이스에 대해 수동 및 랜덤 SQL 쿼리를 수행할 때 변환하려고 합니다.

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에서 여름 시간 시작 및 종료 함수를 만드는 방법

UTC로 저장된 날짜/시간을 지정된 시간대(Azure SQL 데이터베이스가 UTC로 실행되므로 서버의 시간대가 아님)로 만드는 데 도움이 되지 않는 예시를 발견했습니다.난 이렇게 처리했어우아하지는 않지만 심플하고 다른 표를 유지하지 않고도 올바른 답을 얻을 수 있습니다.

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

날짜 이 "Date Time"인 경우Eastern Standard TimeUTC: Azure SQL: SQL Server 2016: UTC: Azure SQL: Azure SQL: SQL Server 2016: Azure Server: UTC: Azure SQL: 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

서버의 위치 이외의 변환이 필요한 경우는, 표준 오프셋을 건네고 US Summer Savings Times 를 어카운트 할 수 있는 함수를 다음에 나타냅니다.

-- =============================================
-- 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

새로운 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

상수 간격띄우기만 추가할 수는 없습니다.

SQL 서버의 타임존을 사용하는 것 외에 데이터베이스에서 CLR을 활성화하는 것이 옵션인 경우 에 기술할 수 있습니다.넷은 꽤 간단하다.

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 datetime 값이 입력되고 서버에 상대적인 로컬 datetime 값이 출력됩니다.null 값은 null을 반환합니다.

이것들 중 어느 것도 나에게는 효과가 없었지만, 아래의 것은 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

데이터를 UTC 날짜로 데이터베이스에 저장하면 다음과 같은 간단한 작업을 수행할 수 있습니다.

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

이며, 일은 .TIME ZONE 'your time zone name'클라이언트의 인스톨과 같이 데이터베이스가 다른 타임 존으로 이동하면, 하드 코드화된 타임 존에 감염될 가능성이 있습니다.

가장 쉬운 답은 항상 맨 아래쪽에 있는 것은 아니지만, 이번에는 맨 아래이며, 위의 댓글에 이미 숨겨져 있는 어딘가에서 볼 수 있습니다.현재 SYSDATETIME 필드가 아닌 자신의 'AT TIME ZONE'을 사용하여 TzOffset을 캡처합니다.아래 데이터에서는 2개의 쿼리, 2개의 쿼리(DST는 오프, 암스테르담의 윈터) +1 diff, 두 번째 쿼리는 암스테르담의 4월 데이터에 대해 +2시간 차이입니다.

    select top 2 month(receiveTimeUTC) as MonthInWinterOrSpring
   ,  receiveTimeUTC
   ,  CONVERT(datetime,  SWITCHOFFSET(CONVERT(datetimeoffset,  receiveTimeUTC),  DATENAME(TzOffset, SYSDATETIMEOFFSET()))) as LocalTimeWrongNoDST
   ,  CONVERT(datetime,  SWITCHOFFSET(CONVERT(datetimeoffset,  receiveTimeUTC),  DATENAME(TzOffset, receiveTimeUTC  AT TIME ZONE 'Central European Standard Time' ))) as LocalTimeWithDST
       from sensordetails order by id

    select top 2 month(receiveTimeUTC) as MonthInWinterOrSpring, receiveTimeUTC
,  CONVERT(datetime,  SWITCHOFFSET(CONVERT(datetimeoffset,  receiveTimeUTC),  DATENAME(TzOffset, SYSDATETIMEOFFSET()))) as LocalTimeWrongNoDST
,  CONVERT(datetime,  SWITCHOFFSET(CONVERT(datetimeoffset,  receiveTimeUTC),  DATENAME(TzOffset, receiveTimeUTC  AT TIME ZONE 'Central European Standard Time' ))) as LocalTimeWithDST
       from sensordetails order by id desc

결과:

이것은 T-SQL(SQL Server Answer)이며, 저장 프로시저가 필요하지 않습니다.

이것을 올바르고 일반적인 방법으로 하는 간단한 방법은 없습니다.

DST에.GetDate()-GetUTCDate는 서버의 TZ에서 현재 오프셋만 제공되며, 이는 관련이 없습니다.

저는 두 가지 솔루션만 보았고 많이 검색했습니다.

1) TZ당 표준 시간대 및 DST 규칙 등의 기본 데이터 테이블이 몇 개 있는 커스텀 SQL 함수.일을 하고 있지만 우아하지는 않다.코드가 없어서 올릴 수가 없어요.

편집: 다음은 이 방법의 예입니다.https://gist.github.com/drumsta/16b79cee6bc195cd89c8

2) .net 어셈블리를 db 에 추가합니다.넷은 이것을 매우 쉽게 할 수 있다.이 방법은 매우 잘 동작하지만 단점은 서버 레벨에서 몇 가지 파라미터를 설정해야 한다는 것입니다.또한 데이터베이스를 복원하는 등 설정이 쉽게 파손됩니다.저는 이 방법을 사용하지만 코드가 없어서 게시할 수 없습니다.

이 함수는 DST 조정을 통해 UTC 시간을 EST 시간으로 변환합니다.이 함수로 설계한 시간대 이름을 변경하거나 레지스트리에서 가져올 수 있습니다.

Create Function fnConvertUTCTimetoESTTime(
    @UTCTime as datetime
)
returns datetime
as
begin
    return convert(datetime, convert(varchar(23), @UTCTime AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time', 121), 121)
end
go

select dbo.fnConvertUTCTimetoESTTime ('2020-3-8 5:00:00.000')
    , dbo.fnConvertUTCTimetoESTTime ('2020-3-8 6:00:00.000')
    , dbo.fnConvertUTCTimetoESTTime ('2020-3-8 7:00:00.000')
    , dbo.fnConvertUTCTimetoESTTime ('2020-3-8 8:00:00.000')

--returns 0:00am, 1:00am, 3:00am, 4:00am

select dbo.fnConvertUTCTimetoESTTime ('2020-11-1 4:00:00.000')
    , dbo.fnConvertUTCTimetoESTTime ('2020-11-1 5:00:00.000')
    , dbo.fnConvertUTCTimetoESTTime ('2020-11-1 6:00:00.000')
    , dbo.fnConvertUTCTimetoESTTime ('2020-11-1 7:00:00.000')

--returns 0:00am, 1:00am, 1:00am, 2:00am

이 결과는 실제로는 EST 형식의 UTC 시간이므로 "@UTCime AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time'" 결과를 반환할 수 없습니다(이 "짝퉁" EST 시간을 비교하거나 절에 포함하면 UTC 시간으로 다시 변환됩니다).

및 Azure SQL의 »@@Version>= SQL Server 2016 사용자 아래는 를 사용한 간단한 기능입니다.

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

다음은 여름 시간, 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

데이터가 많을 때 one off function이 너무 느리다는 것을 알게 되었습니다.그래서 시간 차이를 계산할 수 있는 표 함수에 결합함으로써 이 작업을 수행했습니다.기본적으로 시간 오프셋이 있는 날짜/시간 세그먼트입니다.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
 declare @mydate2 datetime
 set @mydate2=Getdate()
 select @mydate2 as mydate,
 dateadd(minute, datediff(minute,getdate(),@mydate2),getutcdate())

나중에 이것은 매우 잘 작동한다.서버에 시간을 절약한 시간을 '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

론의 답변에는 오류가 포함되어 있습니다.UTC와 동등한 UTC가 필요한 현지시간으로 오전 2시를 사용합니다.Ron의 답변에 대해 코멘트를 할 수 있는 평가 포인트가 부족하기 때문에 수정 버전은 다음과 같습니다.

-- =============================================
-- 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

UNIX 타임스탬프는 특정 날짜와 Unix Epoch 사이의 초수일 뿐입니다.

SELECT DATIFF (SECond, {d '1970-01-01'}, GETDATE() // SQL Server에서 UNIX 타임스탬프가 반환됩니다.

Country Offset Function to Unix Time Stamp In SQL Server를 사용하여 로컬 날짜에서 Unix UTC로 변환하는 함수를 만들 수 있습니다.

간단해요.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

아직 이 문제를 해결하려는 사용자를 위해 SQL Server 2017에서 사용할 수 있는 개념 증명서를 소개합니다.

 declare
    @StartDate date = '2020-01-01'

;with cte_utc as
(
    select 
         1 as i
        ,CONVERT(datetime, @StartDate) AS UTC
        ,datepart(weekday, CONVERT(datetime, @StartDate)) as Weekday
        ,datepart(month, CONVERT(datetime, @StartDate)) as [Month]
        ,datepart(YEAR, CONVERT(datetime, @StartDate)) as [Year]
        
    union all

    Select
         i + 1
        ,dateadd(d, 1, utc)
        ,datepart(weekday, CONVERT(datetime, dateadd(d, 1, utc))) as Weekday
        ,datepart(month, CONVERT(datetime, dateadd(d, 1, utc))) as [Month]
        ,datepart(YEAR, CONVERT(datetime, dateadd(d, 1, utc))) as [Year]
    from    
        cte_utc
    where
        (i + 1) < 32767

), cte_utc_dates as 
(
    select 
        *,
        DENSE_RANK()OVER(PARTITION BY [Year], [Month], [Weekday] ORDER BY Utc) WeekDayIndex
    from
        cte_utc

), cte_hours as (
    select 0 as [Hour]
    union all
    select [Hour] + 1 from cte_hours where [Hour] < 23
)

select
    d.*
    , DATEADD(hour, h.Hour, d.UTC) AS UtcTime
    ,CONVERT(datetime, DATEADD(hour, h.Hour, d.UTC) AT TIME ZONE 'UTC' AT TIME ZONE 'Central Standard Time') CST
    ,CONVERT(datetime, DATEADD(hour, h.Hour, d.UTC) AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time') EST
from
    cte_utc_dates d, cte_hours h
where
    ([Month] = 3 and [Weekday] = 1 and WeekDayIndex = 2 )-- dst start
    or 
    ([Month] = 11 and [Weekday] = 1 and WeekDayIndex = 1 )-- dst end
order by
    utc
OPTION (MAXRECURSION 32767)

GO

경고 - 다음을 사용하는 경우(분 단위 대신 밀리초 단위)

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

DATIFF 부품은 항상 같은 번호를 반환하지 않습니다.따라서 DateTimes를 밀리초 단위로 비교하는 데 사용하지 마십시오.

그러면 DST에서 서버 시간을 얻을 수 있습니다.

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

sysdatetime offset은 DST를 고려합니다.

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

첫 번째 함수: 이탈리아 표준시(+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

-- 인도 표준시를 utc에서 가져옵니다.

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

    RETURN dateadd(minute,330,@UTCDate)

END
GO

올바른 시간으로 변환할 뿐만 아니라 문자열을 다시 포맷해야 합니다.이 경우 나는 줄루 시간이 필요했다.

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;

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

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 함수 코드가 생성됩니다.

utc 시각에서 로컬 시각으로 변환하기 위해 switchoffset을 사용했습니다.시간대 오프셋은 datname(tzoffset, systemdatetimeoffset)을 사용하여 확인할 수 있습니다.마찬가지로 경과시간을 취득하려면 datediff 함수에 대해 utcdate 시간을 utc로 유지하는 것을 사용합니다.

select
      ,[Field1]
      ,Format(SWITCHOFFSET([MyDateOnUTC],DATENAME(TZOFFSET, SYSDATETIMEOFFSET())),'MM/dd/yyyy hh:mm:ss tt')  UtcToLocalTime
      ,datediff(minute,[ClaimedOnUTC],getutcdate()) ElapsedMinutes
 from dbo.my_table

여기 dst를 고려한 더 간단한 것이 있습니다.

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

이 기능은 별도의 테이블이나 루프를 사용하는 다른 솔루션보다 빠르다는 것을 알게 되었습니다.그냥 기본적인 사건 진술서일 뿐이에요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

언급URL : https://stackoverflow.com/questions/8038744/convert-datetime-column-from-utc-to-local-time-in-select-statement

반응형