Voici une implémentation SQL seulement que j'ai récemment mis en place que vous pouvez utiliser (Les forums suggèrent que CLR est la seule méthode depuis TSQL est inutilement compliquée pour y parvenir - pas vraiment afaik).J'ai implémenté via une fonction inline qui évite RBAR (Vous pouvez profiler et tester ceci pour confirmer).
Les performances sont excellentes même sur les vues partitionnées distribuées de la vieille école. Assurez-vous que votre indexation est bonne pour elle, même sur les manipulations de chaîne sur les champs DateTime (Pour contourner les dépendances Année DatePart) Je reçois les recherches souhaitées. Certaines tables partitionnées sous-jacentes ont une taille supérieure à 80 Go.
Bien sûr, vous devrez ajouter vos lignes de fuseau horaire comme vous le souhaitez et n'oubliez pas de garder les dates de début et de fin de l'heure d'été actualisées (elles peuvent changer). Dans les deux cas de fuseau horaire et d'heure d'été, les décalages sont en minutes, donc cela fonctionne pour tous les scénarios que j'ai rencontrés jusqu'à présent.
Enfin, les économies d'Daylight décalage est toujours un nombre positif, notez la fonction s'adresse à ce à la suite de la règle générale (Spring Forward, Fall Back)
If Not Exists (Select Name from sys.objects where name = 'tblTimeZones' and type = 'U')
Begin
Create Table tblTimeZones(
[ID] Int Identity (0,1) NOT NULL,
[UserID] Int NOT NULL,
[Description] NVarchar(128) NOT NULL,
[TZ_OffSet_Mins] Int NOT NULL,
[Use_DST] Bit NOT NULL,
[DST_AddOffSet] Int NOT NULL,
[DST_StartDate] DateTime NOT NULL Constraint DF_DST_StartDate Default ('1900-01-01 00:00:00.000'),
[DST_EndDate] DateTime NOT NULL Constraint DF_DST_EndDate Default ('1900-01-01 00:00:00.000'),
Constraint PK_tblTimeZones Primary Key NonClustered (ID),
Constraint UQ_tblTimeZones_Description Unique Clustered ([Description])
)
End
Go
If Exists (Select Name from sys.objects where name = 'fncV1_iCalcDateInTimeZone' and type = 'IF')
Begin
Drop Function fncV1_iCalcDateInTimeZone
End
Go
Create Function fncV1_iCalcDateInTimeZone
(
@UserID Int, @DateAndTime DateTime, @EntID Int
)
Returns Table
With SchemaBinding
As
Return (
Select TZDateAndTime =
DateAdd(
mi,
tz.TZ_OffSet_Mins +
-- Daylight Savings STARTS earlier in the Year than Ends (So, Northern Hemisphere), In Daylight Savings Time Period and Daylight Savings In Use
Case when
tz.Use_DST = 1
And SubString(Convert(Varchar(23),tz.DST_StartDate,21), 6, 18) < SubString(Convert(Varchar(23),tz.DST_EndDate,21), 6, 18)
And SubString(Convert(Varchar(23),@DateAndTime,21), 6, 18) >= SubString(Convert(Varchar(23),tz.DST_StartDate,21), 6, 18)
And SubString(Convert(Varchar(23),@DateAndTime,21), 6, 18) < SubString(Convert(Varchar(23),tz.DST_EndDate,21), 6, 18)
then tz.DST_AddOffSet
Else 0
End
+
-- Daylight Savings STARTS later in the Year than Ends (So, Southern Hemisphere), In Daylight Savings Surround Period
Case when
tz.Use_DST = 1
And SubString(Convert(Varchar(23),tz.DST_StartDate,21), 6, 18) > SubString(Convert(Varchar(23),tz.DST_EndDate,21), 6, 18)
And
(
SubString(Convert(Varchar(23),@DateAndTime,21), 6, 18) >= SubString(Convert(Varchar(23),tz.DST_StartDate,21), 6, 18)
Or
SubString(Convert(Varchar(23),@DateAndTime,21), 6, 18) < SubString(Convert(Varchar(23),tz.DST_EndDate,21), 6, 18)
)
then tz.DST_AddOffSet
Else 0
End
,@DateAndTime
)
From dbo.tblSomeEntityTable rd
Inner Join dbo.tblBranch b on rd.BranchID = b.ID
Inner Join dbo.tblUsers u on u.ID = @UserID
Inner Join dbo.tblTimeZones tz on tz.ID = case when u.UserTZOverBranchTZ = 1 then u.TimeZoneID else b.TimeZoneID End
Where
rd.ID = Case when ISNULL(@EntID, -1) = -1 then rd.ID else @EntID End
)
Go
ce que le moteur et la version s'il vous plaît? – gbn
Désolé, j'ai oublié de mentionner - sql 2005. – vikasde