UFN_RECURRENCE_CALCULATEACTUALSTARTDATE
Determines the effective start date for a recurrence. This is the first actual occurrence after the supplied start date.
Return
Return Type |
---|
date |
Parameters
Parameter | Parameter Type | Mode | Description |
---|---|---|---|
@RECURRENCETYPE | tinyint | IN | |
@DAYOFWEEK | tinyint | IN | |
@DAY | tinyint | IN | |
@WEEK | tinyint | IN | |
@MONTH | tinyint | IN | |
@STARTDATE | date | IN |
Definition
Copy
CREATE function [DBO].[UFN_RECURRENCE_CALCULATEACTUALSTARTDATE]
(
@RECURRENCETYPE tinyint = 0,
@DAYOFWEEK tinyint = 0,
@DAY tinyint = 0,
@WEEK tinyint = 0,
@MONTH tinyint = 0,
@STARTDATE date = null
)
returns date
begin
--Have to convert DATE type to DATETIME for the following math to be allowed
declare @RESULT datetime = @STARTDATE;
declare @TEMPDAYOFWEEK int;
declare @TEMPDAYOFWEEKBIT int;
declare @BEGINNINGOFMONTH datetime;
declare @DAYSINMONTH int;
if @RECURRENCETYPE = 1 set @DAYOFWEEK=62; --Mon thru Fri
--Fix Day of Week. This is duplicated in "Special Case for 6"
if @RECURRENCETYPE IN (1,2,4,6)
begin
if @DAYOFWEEK NOT BETWEEN 1 AND 127 return @RESULT;
set @TEMPDAYOFWEEK = (datepart(DW, @RESULT) + @@datefirst - 1) % 7 + 1
set @TEMPDAYOFWEEKBIT = power(2, @TEMPDAYOFWEEK-1)
while (@DAYOFWEEK & @TEMPDAYOFWEEKBIT) = 0
begin
set @RESULT = dateadd(DD, 1, @RESULT);
set @TEMPDAYOFWEEK = (datepart(DW, @RESULT) + @@datefirst - 1) % 7 + 1
set @TEMPDAYOFWEEKBIT = power(2, @TEMPDAYOFWEEK-1)
end
end
--Fix Day of Month
if @RECURRENCETYPE IN (3,5)
begin
if @DAY NOT BETWEEN 1 AND 31 return @RESULT;
while day(@RESULT) != @DAY
set @RESULT = dateadd(DD, 1, @RESULT);
end
--Fix Week-Of-Month. This is duplicated in "Special Case for 6"
if @RECURRENCETYPE IN (4,6)
begin
if @WEEK NOT BETWEEN 1 AND 5 return @RESULT;
if @WEEK = 5
begin
--Handle the "last week" case
set @BEGINNINGOFMONTH = @RESULT - day(@RESULT) + 1
set @DAYSINMONTH = datediff(DD, @BEGINNINGOFMONTH, dateadd(MM, 1, @BEGINNINGOFMONTH))
while (@DAYSINMONTH - day(@RESULT)) >= 7
begin
set @RESULT = dateadd(WK, 1, @RESULT);
set @BEGINNINGOFMONTH = @RESULT - day(@RESULT) + 1
set @DAYSINMONTH = datediff(DD, @BEGINNINGOFMONTH, dateadd(MM, 1, @BEGINNINGOFMONTH))
end
end
else
begin
while ((day(@RESULT) - 1) / 7) + 1 != @WEEK
set @RESULT = dateadd(WK, 1, @RESULT);
end
end
--Special handling for RecurType 6:
declare @MONTHWASADJUSTED bit = 0;
--Fix Month of Year
if @RECURRENCETYPE IN (5,6)
begin
declare @TEMPMONTH int = datepart(MM, @RESULT);
declare @COUNTER int = 0;
if @TEMPMONTH != @MONTH
set @MONTHWASADJUSTED = 1;
--Using a counter rather than updateing @RESULT each time b/c if Day is 31 and we
--go through a month with 30 days, our day will drop down to that on the Add Month command.
while @TEMPMONTH != @MONTH
begin
set @COUNTER = @COUNTER + 1;
set @TEMPMONTH = datepart(MM, dateadd(MM, @COUNTER, @RESULT));
end
set @RESULT = dateadd(MM, @COUNTER, @RESULT);
end
if @RECURRENCETYPE = 5 AND @MONTH = 2 AND @DAY = 29 AND datepart(DD, @RESULT) = 28
begin
while datepart(DD, dateadd(DD, 1, @RESULT)) != 29
set @RESULT = dateadd(YY, 1, @RESULT);
set @RESULT = dateadd(DD, 1, @RESULT);
end
-- Special Case for 6
if @RECURRENCETYPE = 6 AND @MONTHWASADJUSTED = 1
begin
--- Because we had to adjust the month, then we are no longer on
--- the "Nth" "Day" of the month. We need to readjust those vales.
--- We also back back up to the first day of the month without fear
--- of going to before the provided start date, b/c the month was advanced.
--Go back to day one, and advance from there.
set @RESULT = @RESULT - day(@RESULT) + 1
--Fix Day of Week again.
set @TEMPDAYOFWEEK = (datepart(DW, @RESULT) + @@datefirst - 1) % 7 + 1
set @TEMPDAYOFWEEKBIT = power(2, @TEMPDAYOFWEEK-1)
while (@DAYOFWEEK & @TEMPDAYOFWEEKBIT) = 0
begin
set @RESULT = dateadd(DD, 1, @RESULT);
set @TEMPDAYOFWEEK = (datepart(DW, @RESULT) + @@datefirst - 1) % 7 + 1
set @TEMPDAYOFWEEKBIT = power(2, @TEMPDAYOFWEEK-1)
end
--Fix Week of Month again.
if @WEEK = 5
begin
--Handle the "last week" case
set @BEGINNINGOFMONTH = @RESULT - day(@RESULT) + 1
set @DAYSINMONTH = datediff(DD, @BEGINNINGOFMONTH, dateadd(MM, 1, @BEGINNINGOFMONTH))
while (@DAYSINMONTH - day(@RESULT)) >= 7
begin
set @RESULT = dateadd(WK, 1, @RESULT);
set @BEGINNINGOFMONTH = @RESULT - day(@RESULT) + 1
set @DAYSINMONTH = datediff(DD, @BEGINNINGOFMONTH, dateadd(MM, 1, @BEGINNINGOFMONTH))
end
end
else
begin
while ((day(@RESULT) - 1) / 7) + 1 != @WEEK
set @RESULT = dateadd(WK, 1, @RESULT);
end
end
return @RESULT;
end