web-dev-qa-db-fra.com

Convertir la colonne Datetime de l'heure UTC en heure locale dans l'instruction select

Je fais quelques requêtes de sélection SQL et j'aimerais convertir ma colonne de date/heure UTC en heure locale afin qu'elle soit affichée en heure locale dans les résultats de ma requête. Notez que je ne cherche PAS à effectuer cette conversion via le code, mais plutôt lorsque je fais des requêtes SQL manuelles et aléatoires sur mes bases de données.

156
Nugs

Vous pouvez le faire comme suit sur SQL Server 2008 ou version ultérieure:

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

Vous pouvez aussi faire le moins bavard:

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

Quoi que vous fassiez, not not n'utilisez pas - pour soustraire des dates, car l'opération n'est pas atomique et vous obtiendrez parfois des résultats indéterminés en raison de conditions de concurrence entre l'heure système et l'heure locale en cours de vérification à , non atomiquement).

Veuillez noter que cette réponse ne tient pas compte de l'heure d'été. Si vous souhaitez inclure un ajustement DST, veuillez également consulter la question SO suivante:

Comment créer des fonctions de début et de fin de l'heure d'été dans SQL Server

261

Je n'ai trouvé aucun de ces exemples utile pour obtenir une date/heure stockée au format UTC dans un fuseau horaire spécifié (PAS le fuseau horaire du serveur car les bases de données Azure SQL s'exécutent au format UTC). Voici comment je l'ai géré. Ce n’est pas élégant mais c’est simple et vous donne la bonne réponse sans conserver d’autres tables:

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

Si vous avez besoin d'une conversion autre que celle de votre serveur, voici une fonction qui vous permet de transmettre un décalage standard et des comptes pour les heures d'été:

-- =============================================
-- 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
20
Ron Smith

Utilisation des nouvelles opportunités 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

Mais la procédure CLR fonctionne 5 fois plus vite: '- (

Faites attention au fait que le décalage d’un fuseau horaire peut changer en heure d’été ou en été. Par exemple

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'

résultats:

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

Vous ne pouvez pas simplement ajouter un décalage constant.

6
Pavel Samoylenko

Si activer le CLR sur votre base de données est une option et utiliser le fuseau horaire du serveur SQL, il peut être écrit assez facilement en .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());
    }
}

Une valeur date/heure UTC entre et la valeur date/heure locale relative au serveur sort. Les valeurs nulles renvoient null.

5
JGates

Voici une version qui tient compte de l'heure avancée, du décalage UTC et qui n'est pas verrouillée pour une année donnée.

---------------------------------------------------------------------------------------------------
--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
4
Patrick Slesicki

Il n'y a pas de moyen simple de le faire de manière correcte ET générique.

Tout d'abord, il faut comprendre que le décalage dépend de la date en question, du fuseau horaire ET de l'heure d'été. GetDate()-GetUTCDate ne vous donne le décalage qu'aujourd'hui sur la TZ du serveur, ce qui n'est pas pertinent.

Je n'ai vu que deux solutions de travail et j'ai beaucoup cherché.

1) Une fonction SQL personnalisée avec quelques tables de données de base telles que les fuseaux horaires et les règles DST par TZ . Fonctionnant mais pas très élégant. Je ne peux pas poster car je ne possède pas le code.

EDIT: Voici un exemple de cette méthode https://Gist.github.com/drumsta/16b79cee6bc195cd89c8

2) Ajoutez un assemblage .net à la base de données. Net peut le faire très facilement. Cela fonctionne très bien, mais l’inconvénient est que vous devez configurer plusieurs paramètres au niveau du serveur et que la configuration est facilement cassée, par exemple. si vous restaurez la base de données . J'utilise cette méthode mais je ne peux pas la poster car je ne possède pas le code. 

4
vikjon0

J'ai trouvé que la fonction unique était trop lente lorsqu'il y avait beaucoup de données. Je l’ai donc fait en joignant une fonction de table qui permettait de calculer le différentiel d’heures. Il s’agit essentiellement de segments datetime avec le décalage horaire. Une année serait 4 rangées. Donc, la fonction de table

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

retournerait cette table:

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

Cela tient compte de l'heure avancée. Vous trouverez ci-dessous un exemple d'utilisation. Le blog complet est ici .

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
3
JBrooks
 declare @mydate2 datetime
 set @mydate2=Getdate()
 select @mydate2 as mydate,
 dateadd(minute, datediff(minute,getdate(),@mydate2),getutcdate())
2
Looking_for_answers

Aucune de ces solutions n'a fonctionné pour moi, mais cela a fonctionné à 100% ci-dessous. J'espère que cela pourra aider d'autres personnes qui essaient de le convertir comme je l'étais.

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
2
Mike

L’horodatage UNIX est simplement le nombre de secondes entre une date donnée et l’époque Unix, 

SELECT DATEDIFF (SECONDE, {d '1970-01-01'}, GETDATE ()) // Ceci retournera l'horodatage UNIX dans le serveur SQL

vous pouvez créer une fonction pour la conversion de l'heure locale en heure Unix UTC à l'aide de l'offset pays Fonction en horodatage Unix Dans SQL Server

1
Vasanthlal V A

Pour les utilisateurs de SQL Azure et @@Version> = = SQL Server 2016, voici une fonction simple utilisant 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

Pour les types de valeurs que @LocalTimeZone peut prendre, veuillez vous rendre à ce lien ou aller à KEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones

1
Ranger

Cela peut être fait sans fonction. Le code ci-dessous convertira une heure UTC en heure de la montagne en tenant compte de l'heure avancée. Ajustez tous les chiffres -6 et -7 à votre fuseau horaire en conséquence (c.-à-d. Pour EST, vous devez ajuster à -4 et -5 respectivement)

--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
1
Alex Fenech

La réponse de Ron contient une erreur. Il utilise 2:00 AM heure locale où l'équivalent UTC est requis. Comme je n'ai pas assez de points de réputation pour commenter la réponse de Ron, une version corrigée apparaît ci-dessous:

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

C'est simple. Essayez ceci pour Azure SQL Server:

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

Pour le serveur SQL local:

SELECT CONVERT (datetime2, SWITCHOFFSET (CONVERT (datetimeoffset, gETDATE ()), DATENAME (TzOffset, gETDATE () AT ZONE HORAIRE 'Heure normale de l'Est'))) DE Votre Table

0
lijuthomas

Vous devez reformater la chaîne ainsi que la conversion à l'heure correcte. Dans ce cas, j'avais besoin de temps zoulou.

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
Tommyz

Pour Azure et SQL Server 2016 et versions ultérieures, vous pouvez effectuer les opérations suivantes:

select YourDateTimeUtcColumn AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time' as LocalTime from YourTable

La liste complète des noms de fuseaux horaires peut être trouvée dans cet article: Liste des ID de fuseaux horaires à utiliser avec FindTimeZoneById () en C #?

Et oui, les fuseaux horaires sont mal nommés - même s’il s’agit de "l’heure normale de l’Est", l’heure avancée est prise en compte.

0
Matt Frear

Meilleur moyen pour Oracle:

Avec date/heure codée en dur:

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

Avec noms de colonne et de table:

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
BOB

Première fonction: configurée pour le fuseau horaire italien (+1, +2), dates de commutation: dernier dimanche de mars et octobre, retourne en paramètre la différence entre le fuseau horaire actuel et le datetime. 

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

Le code est:

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

Puis la fonction qui convertit la date

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
GigiS

J'ai le code pour effectuer UTC à Local et Local à UTC fois qui permet la conversion en utilisant un code comme celui-ci

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

et

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

Les fonctions peuvent prendre en charge la totalité ou un sous-ensemble de fuseaux horaires dans IANA/TZDB fournis par NodaTime - voir la liste complète à l'adresse https://nodatime.org/TimeZones

Sachez que mon cas d'utilisation signifie que je n'ai besoin que d'une fenêtre "actuelle", permettant la conversion des temps dans une fourchette d'environ +/- 5 ans à partir de maintenant. Cela signifie que la méthode que j'ai utilisée ne vous convient probablement pas si vous avez besoin d'une très longue période, en raison de la manière dont elle génère le code pour chaque intervalle de fuseau horaire dans une plage de dates donnée.

Le projet est sur GitHub: https://github.com/elliveny/SQLServerTimeConversion

Ceci génère le code de fonction SQL selon cet exemple

0
Elliveny

Cela devrait pouvoir obtenir l'heure du serveur avec DST

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

sysdatetimeoffset prend en compte l'heure d'été

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

En guise d'avertissement - si vous allez utiliser ce qui suit (notez les millisecondes au lieu de minutes):

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

Gardez à l'esprit que la partie DATEDIFF ne renverra pas toujours le même numéro. Donc, ne l'utilisez pas pour comparer DateTimes à des millisecondes.

0
Sasquatch

- Obtenir l'heure standard indienne d'utc

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

    RETURN dateadd(minute,330,@UTCDate)

END
GO
0
Meghraj Swami

J'ai constaté que cette fonction est plus rapide que d'autres solutions utilisant un tableau séparé ou des boucles. C'est juste une déclaration de base. Étant donné que tous les mois d'avril à octobre ont un décalage de -4 heures (heure de l'Est), il suffit d'ajouter quelques lignes de cas supplémentaires pour les jours marginaux. Sinon, le décalage est de -5 heures.

Ceci est spécifique à une conversion de l'heure UTC en heure de l'Est, mais des fonctions de fuseau horaire supplémentaires peuvent être ajoutées si nécessaire.

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
Jason Green