Hi All,
Sorry I'm late to the party, but just wanted to post something for anyone to comment on as another method of solving the problem using date diff and % and a seed date to avoid changing first day of week issues. Personally I'd drop the timestamp part which makes it determanistic when packaged as a function so you could use it in persisted computed columns etc.
/*
* Find the next "First Thursday of the month" after the input date
*
* Mathematical solution avoiding external dependencies.
*
* Darren Comeau - 7th Feb 2012.
*
*/
DECLARE
@inputDate DATETIME
,@workDate DATETIME
,@outputDate DATETIME
SET @inputDate = COALESCE(@inputDate,CURRENT_TIMESTAMP) -- If no input date passed take today.
SET @inputDate = DATEADD(day,DATEDIFF(day,'19000101',@inputDate),'19000101') -- remove any time component
DECLARE
-- any Thursday date in time. Could design the function using @@DATEFIRST but perhaps this is more portable.
@seedDate DATETIME
--SET @seedDate = '19990520' -- Thursday 20th May, 1999.
SET @seedDate = '20120320' -- Tuesday 20th March, 2012. -- would give first tuesday of the month
DECLARE
@dowToday TINYINT
,@dowWorkDate TINYINT
,@monthForward TINYINT -- The value to add to this month
-- What day is today, Thursday = 1, Wednesday = 7
SET @dowToday = (((DATEDIFF(day,@seedDate,@inputDate))%7)+7)%7 + 1
-- This will handle the seed date being in the future or past, the %7+7 handles negative datediff results from future dates
-- uncomment for Debug
--SELECT @dowToday AS [dow],DATEPART(day,@inputDate) AS [dom]
-- Has there already been a thursday in this month?
IF @dowToday > DATEPART(day,@inputDate)
BEGIN
-- uncomment for Debug
--SELECT 'First Thursday This month'
SET @monthForward = 0
END
ELSE
BEGIN
-- uncomment for Debug
--SELECT 'First Thursday Next month'
SET @monthForward = 1
END
SET @workDate = DATEADD(month,@monthForward,@inputDate)
SET @dowWorkDate = (((DATEDIFF(day,@seedDate,@workDate))%7)+7)%7 + 1
SELECT @outputDate = DATEADD(day
,(DATEPART(day,@workDate) +7 -@dowWorkDate)%7 -- add n days to the first day of the month to return the thursday.
,DATEADD(day,((DATEPART(day,@workDate)-1)*-1),@workDate) -- Get the first day of the month
)
-- format the date dd/mm/yyyy
SELECT CONVERT(CHAR(10),@outputDate,103) AS [NextFirstThursday]