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.
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
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')))
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
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.
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.
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
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.
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
declare @mydate2 datetime
set @mydate2=Getdate()
select @mydate2 as mydate,
dateadd(minute, datediff(minute,getdate(),@mydate2),getutcdate())
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
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
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
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
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
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
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;
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.
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
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
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
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)
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.
- Obtenir l'heure standard indienne d'utc
CREATE FUNCTION dbo.getISTTime
(
@UTCDate datetime
)
RETURNS datetime
AS
BEGIN
RETURN dateadd(minute,330,@UTCDate)
END
GO
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