Also includes ISOWeek & WeekendsDont know whether this is of any use to anyone or it has been done before but there are a lot of posts on here regarding date calculation issues & usually the most straight forward answer is to compare against a table of dates.So while looking at Bretts blog and another post on here, i thought i'd post this on here[url]http://weblogs.sqlteam.com/brettk/archive/2005/05/12/5139.aspx[/url][url]http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=49698[/url]Special thanks to rockmoose & BOL (as always)Edit: It also moves bank holidays to the following Monday (and Tuesday - xmas) if the bank holiday(s) falls on the weekendSET DATEFIRST 1SET NOCOUNT ONGO--Create ISO week Function (thanks BOL)CREATE FUNCTION ISOweek (@DATE datetime)RETURNS intASBEGIN DECLARE @ISOweek int SET @ISOweek= DATEPART(wk,@DATE)+1 -DATEPART(wk,CAST(DATEPART(yy,@DATE) as CHAR(4))+'0104')--Special cases: Jan 1-3 may belong to the previous year IF (@ISOweek=0) SET @ISOweek=dbo.ISOweek(CAST(DATEPART(yy,@DATE)-1 AS CHAR(4))+'12'+ CAST(24+DATEPART(DAY,@DATE) AS CHAR(2)))+1--Special case: Dec 29-31 may belong to the next year IF ((DATEPART(mm,@DATE)=12) AND ((DATEPART(dd,@DATE)-DATEPART(dw,@DATE))>= 28)) SET @ISOweek=1 RETURN(@ISOweek)ENDGO--END ISOweek--CREATE Easter algorithm function --Thanks to Rockmoose (http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=45689)CREATE FUNCTION fnDLA_GetEasterdate(@year INT)RETURNS CHAR (8)ASBEGIN -- Easter date algorithm of Delambre DECLARE @A INT,@B INT,@C INT,@D INT,@E INT,@F INT,@G INT, @H INT,@I INT,@K INT,@L INT,@M INT,@O INT,@R INT SET @A = @YEAR%19 SET @B = @YEAR / 100 SET @C = @YEAR%100 SET @D = @B / 4 SET @E = @B%4 SET @F = (@B + 8) / 25 SET @G = (@B - @F + 1) / 3 SET @H = ( 19 * @A + @B - @D - @G + 15)%30 SET @I = @C / 4 SET @K = @C%4 SET @L = (32 + 2 * @E + 2 * @I - @H - @K)%7 SET @M = (@A + 11 * @H + 22 * @L) / 451 SET @O = 22 + @H + @L - 7 * @M IF @O > 31 BEGIN SET @R = @O - 31 + 400 + @YEAR * 10000 END ELSE BEGIN SET @R = @O + 300 + @YEAR * 10000 END RETURN @RENDGO--END fnDLA_GetEasterdate--Create the tableCREATE TABLE MyDateTable(FullDate datetime NOT NULL CONSTRAINT PK_FullDate PRIMARY KEY CLUSTERED, Period int, ISOWeek int, WorkingDay varchar(1) CONSTRAINT DF_MyDateTable_WorkDay DEFAULT 'Y')GO--End table create--Populate table with required datesDECLARE @DateFrom datetime, @DateTo datetime, @Period intSET @DateFrom = CONVERT(datetime,'20000101') --yyyymmdd (1st Jan 2000) amend as requiredSET @DateTo = CONVERT(datetime,'20991231') --yyyymmdd (31st Dec 2099) amend as requiredWHILE @DateFrom <= @DateToBEGIN SET @Period = CONVERT(int,LEFT(CONVERT(varchar(10),@DateFrom,112),6)) INSERT MyDateTable(FullDate, Period, ISOWeek) SELECT @DateFrom, @Period, dbo.ISOweek(@DateFrom) SET @DateFrom = DATEADD(dd,+1,@DateFrom)ENDGO--End population/* Start of WorkingDays UPDATE */UPDATE MyDateTableSET WorkingDay = 'B' --B = Bank Holiday--------------------------------EASTER---------------------------------------------WHERE FullDate = DATEADD(dd,-2,CONVERT(datetime,dbo.fnDLA_GetEasterdate(DATEPART(yy,FullDate)))) --Good Friday OR FullDate = DATEADD(dd,+1,CONVERT(datetime,dbo.fnDLA_GetEasterdate(DATEPART(yy,FullDate)))) --Easter MondayGOUPDATE MyDateTableSET WorkingDay = 'B'--------------------------------NEW YEAR-------------------------------------------WHERE FullDate IN (SELECT MIN(FullDate) FROM MyDateTable WHERE DATEPART(mm,FullDate) = 1 AND DATEPART(dw,FullDate) NOT IN (6,7) GROUP BY DATEPART(yy,FullDate))---------------------MAY BANK HOLIDAYS(Always Monday)------------------------------ OR FullDate IN (SELECT MIN(FullDate) FROM MyDateTable WHERE DATEPART(mm,FullDate) = 5 AND DATEPART(dw,FullDate) = 1 GROUP BY DATEPART(yy,FullDate)) OR FullDate IN (SELECT MAX(FullDate) FROM MyDateTable WHERE DATEPART(mm,FullDate) = 5 AND DATEPART(dw,FullDate) = 1 GROUP BY DATEPART(yy,FullDate))--------------------AUGUST BANK HOLIDAY(Always Monday)------------------------------ OR FullDate IN (SELECT MAX(FullDate) FROM MyDateTable WHERE DATEPART(mm,FullDate) = 8 AND DATEPART(dw,FullDate) = 1 GROUP BY DATEPART(yy,FullDate))--------------------XMAS(Move to next working day if on Sat/Sun)-------------------- OR FullDate IN (SELECT CASE WHEN DATEPART(dw,FullDate) IN (6,7) THEN DATEADD(dd,+2,FullDate) ELSE FullDate END FROM MyDateTable WHERE DATEPART(mm,FullDate) = 12 AND DATEPART(dd,FullDate) IN (25,26))GO---------------------------------------WEEKENDS--------------------------------------UPDATE MyDateTableSET WorkingDay = 'N'WHERE DATEPART(dw,FullDate) IN (6,7)GO/* End of WorkingDays UPDATE */--SELECT * FROM MyDateTable ORDER BY 1DROP FUNCTION fnDLA_GetEasterdateDROP FUNCTION ISOweek--DROP TABLE MyDateTableSET NOCOUNT OFF
AndyBeauty is in the eyes of the beerholder