UFN_TIMEZONEENTRY_GETTIMEZONEOFFSETFROMUTC
Returns the offset from UTC in minutes for the time zone and date passed in
Return
Return Type |
---|
int |
Parameters
Parameter | Parameter Type | Mode | Description |
---|---|---|---|
@TIMEZONEENTRYID | uniqueidentifier | IN | |
@DATEFOROFFSET | datetime | IN | |
@DATEISUTC | bit | IN |
Definition
Copy
CREATE function dbo.UFN_TIMEZONEENTRY_GETTIMEZONEOFFSETFROMUTC
(
@TIMEZONEENTRYID uniqueidentifier,
@DATEFOROFFSET datetime,
@DATEISUTC bit
)
returns integer
with execute as caller
as begin
/**
If the date is UTC this function adds the base offset to the date to determine the
time zone offset for that date.
This function does not handle ambiguous time or invalid time.
Ambiguous time is the hour before falling back (happens twice) and invalid time
is hour after springing forward (time never happens).
In the ambiguous time case, it will always be considered in daylight savings time since
the ambiguous time is before the cutoff (ie 1:45 AM first Sunday in November will always be
daylight savings time even though we really don't know which time it really is).
In the invalid time case, it will always be considered in daylight savings time since the
invalid time is after the cutoff (ie 2:45 AM second Sunday in March will always be daylight
savings time even though this is not a valid time).
**/
declare @DAYLIGHTDELTA as integer
declare @ISFIXEDSTARTDATE as bit
declare @STARTFIXEDDATE as datetime
declare @STARTMONTH as tinyint
declare @STARTDAYOFWEEK as tinyint
declare @STARTWEEKOFMONTH as tinyint
declare @STARTDAYLIGHTDATE as datetime
declare @STARTTIME as dbo.UDT_HOURMINUTE
declare @ISFIXEDENDDATE as bit
declare @ENDFIXEDDATE as datetime
declare @ENDMONTH as tinyint
declare @ENDDAYOFWEEK as tinyint
declare @ENDWEEKOFMONTH as tinyint
declare @ENDDAYLIGHTDATE as datetime
declare @ENDTIME as dbo.UDT_HOURMINUTE
declare @UTCOFFSET as integer
select
@UTCOFFSET = TIMEZONEENTRY.BASETIMEZONEOFFSET
from
dbo.TIMEZONEENTRY
where
ID = @TIMEZONEENTRYID
--if date is utc, then add base offset to more accurately determine
--daylight savings time
if @DATEISUTC = 1
set @DATEFOROFFSET = dateadd(minute, @UTCOFFSET, @DATEFOROFFSET)
select
@DAYLIGHTDELTA = TZRULE.DAYLIGHTSAVINGSDELTA,
--if month for date passed in is not the start month then
--we don't need to determine exact start date
@ISFIXEDSTARTDATE = (
case
when TZRULE.ISFIXEDSTARTDATE <> 0 then
1
when datepart(month, @DATEFOROFFSET) <> TZRULE.STARTMONTHCODE then
1
else
0
end),
@STARTFIXEDDATE = TZRULE.STARTFIXEDDATE,
@STARTMONTH = TZRULE.STARTMONTHCODE,
@STARTDAYOFWEEK = TZRULE.STARTDAYOFWEEKCODE,
@STARTWEEKOFMONTH = TZRULE.STARTWEEKOFMONTHCODE,
@STARTTIME = TZRULE.STARTTIMEOFDAY,
@ISFIXEDENDDATE = (
case
when TZRULE.ISFIXEDENDDATE <> 0 then
1
when datepart(month, @DATEFOROFFSET) <> TZRULE.ENDMONTHCODE then
1
else
0
end),
@ENDFIXEDDATE = TZRULE.ENDFIXEDDATE,
@ENDMONTH = TZRULE.ENDMONTHCODE,
@ENDDAYOFWEEK = TZRULE.ENDDAYOFWEEKCODE,
@ENDWEEKOFMONTH = TZRULE.ENDWEEKOFMONTHCODE,
@ENDTIME = TZRULE.ENDTIMEOFDAY
from
dbo.TIMEZONEENTRYADJUSTMENTRULE TZRULE
where
TZRULE.TIMEZONEENTRYID = @TIMEZONEENTRYID and
TZRULE.STARTRULEDATE <= @DATEFOROFFSET and
TZRULE.ENDRULEDATE >= @DATEFOROFFSET
if @ISFIXEDSTARTDATE = 0
begin
set @STARTDAYLIGHTDATE = cast(datepart(year,@DATEFOROFFSET) as nvarchar(4)) + '-' + cast(@STARTMONTH as nvarchar(2)) + '-' + cast((7 * (@STARTWEEKOFMONTH - 1)) + 1 as nvarchar(2))
while datepart(dw, @STARTDAYLIGHTDATE)<>@STARTDAYOFWEEK
begin
set @STARTDAYLIGHTDATE = dateadd(d, 1, @STARTDAYLIGHTDATE)
end
set @STARTDAYLIGHTDATE = dateadd(hh, cast(substring(@STARTTIME, 1, 2) as integer), @STARTDAYLIGHTDATE)
set @STARTDAYLIGHTDATE = dateadd(minute, cast(substring(@STARTTIME, 3, 2) as integer), @STARTDAYLIGHTDATE)
--if week of month is 5, then this means last week of the month so if adding 5 weeks pushes
--to next month, take the date back a week
if datepart(month, @STARTDAYLIGHTDATE) <> @STARTMONTH
set @STARTDAYLIGHTDATE = dateadd(d, -7, @STARTDAYLIGHTDATE)
end
else
begin
set @STARTDAYLIGHTDATE = dateadd(year, datepart(year, @DATEFOROFFSET)-1753, @STARTFIXEDDATE)
end
if @ISFIXEDENDDATE = 0
begin
set @ENDDAYLIGHTDATE = cast(datepart(year,@DATEFOROFFSET) as nvarchar(4)) + '-' + cast(@ENDMONTH as nvarchar(2)) + '-' + cast((7 * (@ENDWEEKOFMONTH - 1)) + 1 as nvarchar(2))
while datepart(dw, @ENDDAYLIGHTDATE)<>@ENDDAYOFWEEK
begin
set @ENDDAYLIGHTDATE = dateadd(d, 1, @ENDDAYLIGHTDATE)
end
set @ENDDAYLIGHTDATE = dateadd(hh, cast(substring(@ENDTIME, 1, 2) as integer), @ENDDAYLIGHTDATE)
set @ENDDAYLIGHTDATE = dateadd(minute, cast(substring(@ENDTIME, 3, 2) as integer), @ENDDAYLIGHTDATE)
--if week of month is 5, then this means last week of the month so if adding 5 weeks pushes
--to next month, take the date back a week
if datepart(month, @ENDDAYLIGHTDATE) <> @ENDMONTH
set @ENDDAYLIGHTDATE = dateadd(d, -7, @ENDDAYLIGHTDATE)
end
else
begin
set @ENDDAYLIGHTDATE = dateadd(year, datepart(year, @DATEFOROFFSET)-1753, @ENDFIXEDDATE)
end
if @DATEFOROFFSET >= @STARTDAYLIGHTDATE and @DATEFOROFFSET < @ENDDAYLIGHTDATE
set @UTCOFFSET = @UTCOFFSET + @DAYLIGHTDELTA
return @UTCOFFSET
end