рд▓рдЪреАрд▓реЗ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЗ рд╕рд╛рде SQL рд╕рд░реНрд╡рд░ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рддрд┐рдерд┐ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп рджрд┐рд╡рд╕ рдЬреЛрдбрд╝реЗрдВ
рдпрджрд┐ рдЖрдкрдиреЗ рдЕрдиреНрдп рддрд┐рдерд┐ рд▓реЗрдЦреЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХреА рд╣реИ рддреЛ рдЖрдкрдХреЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рддрд╛рд▓рд┐рдХрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ, рдпрджрд┐ рдирд╣реАрдВ рддреЛ рдЗрд╕реЗ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
рдпреЗ рдЗрдВрдЧреНрд▓реИрдВрдб рдФрд░ рд╡реЗрд▓реНрд╕ рдореЗрдВ рдорд╛рдирдХ рдЫреБрдЯреНрдЯрд┐рдпреЛрдВ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИрдВред
рдореБрдЦреНрдп рдкреГрд╖реНрда рдкрд░ рдЕрдиреНрдп рджреЗрд╢реЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп рд╣реИрдВред
CREATE TABLE Dates.Calendar(
CalendarDate DATETIME2 NOT NULL CONSTRAINT PK_CalendarDate PRIMARY KEY,
CalendarCA AS (DATEDIFF(DAY,DATEADD(DAY,1-DATEPART(DAY,CalendarDate),CalendarDate),CalendarDate)/7)+1 PERSISTED,
CalendarCD AS (DATEDIFF(DAY,CalendarDate,DATEADD(DAY,-1,DATEADD(MONTH,1,DATEADD(DAY,1-DATEPART(DAY,CalendarDate),CalendarDate))))/7)+1 PERSISTED,
WeekDayID AS (DATEPART(weekday,[CalendarDate])),
WeekDayName AS (case DATEPART(weekday,[CalendarDate]) when (1) then 'Sunday' when (2) then 'Monday' when (3) then 'Tuesday' when (4) then 'Wednesday' when (5) then 'Thursday' when (6) then 'Friday' when (7) then 'Saturday' end))
GO
DECLARE @D DATETIME2='1850-01-01'
WHILE @D<='2099-12-31' BEGIN
INSERT INTO Dates.Calendar(CalendarDate) SELECT @D
SET @D=DATEADD(DAY,1,@D)
END
GO
CREATE TABLE Dates.CalendarHolidays(CalendarDate DATETIME2 NOT NULL,CalendarFunction INT NOT NULL,HolidayType VARCHAR(100) NULL,CONSTRAINT PK_Holidays_Id PRIMARY KEY(CalendarDate,CalendarFunction))
GO
/*English & Welsh Holidays*/
INSERT INTO Dates.CalendarHolidays
SELECT CalendarDate,0,'New Years Day' FROM Dates.Calendar WHERE DATEPART(MONTH,CalendarDate)=1 AND DATEPART(DAY,CalendarDate)=1 UNION --New Years Day
SELECT CalendarDate,0,'Good Friday' FROM Dates.Calendar WHERE CalendarDate=DATEADD(DAY,-2,Dates.GetEasterDate(DATEPART(YEAR,CalendarDate))) UNION--Good Friday
SELECT CalendarDate,0,'Easter Monday' FROM Dates.Calendar WHERE CalendarDate=DATEADD(DAY,1,Dates.GetEasterDate(DATEPART(YEAR,CalendarDate))) UNION--Easter Monday
SELECT CalendarDate,0,'May Holidays' FROM Dates.Calendar WHERE DATEPART(MONTH,CalendarDate)=5 AND WeekDayID=2 AND (CalendarCA=1 OR CalendarCD=1)UNION--May Holidays
SELECT CalendarDate,0,'August Holidays' FROM Dates.Calendar WHERE DATEPART(MONTH,CalendarDate)=8 AND WeekDayID=2 AND (CalendarCD=1) UNION--August Holidays
SELECT CalendarDate,0,'Christmas Day' FROM Dates.Calendar WHERE DATEPART(MONTH,CalendarDate)=12 AND DATEPART(DAY,CalendarDate)=25 UNION --Christmas Day
SELECT CalendarDate,0,'Boxing Day' FROM Dates.Calendar WHERE DATEPART(MONTH,CalendarDate)=12 AND DATEPART(DAY,CalendarDate)=26 --Boxing Day
GO
рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдбреЗрдЯрд╛ рд╣реИ, рд╣рдо рдПрдХ рдРрд╕рд╛ рдлрдВрдХреНрд╢рди рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдкреНрд░рддреНрдпреЗрдХ рджрд┐рди рд╢реБрд░реВ рд╕реЗ рдЕрдВрдд рддрдХ рдЪрд▓рддрд╛ рд╣реИ рдФрд░ 1 рд╕реЗ @Count рдЬреЛрдбрд╝рддрд╛ рд╣реИ рдЬрд╣рд╛рдВ рдпрд╣ рд╢рдирд┐рд╡рд╛рд░, рд░рд╡рд┐рд╡рд╛рд░ рдпрд╛ рдЕрд╡рдХрд╛рд╢ рдХреЗ рджрд┐рдиреЛрдВ рдХреЗ рдЖрдкрдХреЗ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдирд╣реАрдВ рд╣реИред
рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреБрдЫ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдереА рдХрд┐ рдкрд┐рдЫрд▓реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд▓рдЪреАрд▓рд╛ рдмрдирд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдХреБрдЫ рдЕрддрд┐рд░рд┐рдХреНрдд рдХреНрд▓рд╛рдЗрдВрдЯ рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдлрд┐рд░ рд╕реЗ рдЖрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рд╣рдордиреЗ рдЗрд╕реЗ рдФрд░ рдЕрдзрд┐рдХ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЗ рд╕рд╛рде рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рд╣реИ:
- @ AdjustDate - рд╡рд╣ рддрд┐рдерд┐ рдЬрд┐рд╕реЗ рдЖрдк рдмрджрд▓рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ
- @ рдХреИрд▓реЗрдиреНрдбрд░рдлрдВрдХреНрд╢рди - рд╡рд╣ рдЕрд╡рдХрд╛рд╢ рдлрд╝рдВрдХреНрд╢рди рдЬрд┐рд╕рдХрд╛ рдЖрдк рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ (рдпреВрдХреЗ рдХреЗ рдХреБрдЫ рджреЗрд╢реЛрдВ рдореЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рддрд┐рдерд┐рдпрд╛рдВ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЙрдиреНрд╣реЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рджрд┐рдиреЛрдВ рдореЗрдВ рд╕реНрдЯреЛрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ)
- @ AdjustDats - рдЖрдзрд╛рд░ рддрд┐рдерд┐ рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдпрд╛ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рджрд┐рдиреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛
- @ AdjustMode - 0 рдЬреЛрдбрд╝ рджрд┐рдиреЛрдВ рдХреЗ рд▓рд┐рдП, рдШрдЯрд╛рд╡ рджрд┐рдиреЛрдВ рдХреЗ рд▓рд┐рдП 1
- @ AdjustWeekend - рдЖрдкрдХреА рдЧрдгрдирд╛ рд╕реЗ рд╕рдкреНрддрд╛рд╣рд╛рдВрдд рдирд┐рдХрд╛рд▓ рджреЗрддрд╛ рд╣реИ
- @ AdjustHolidays - рдЫреБрдЯреНрдЯрд┐рдпреЛрдВ рдХреЛ рдЫреЛрдбрд╝ рджреЗрддрд╛ рд╣реИ рдпрджрд┐ рдЕрд╡рдХрд╛рд╢ рдлрд╝рдВрдХреНрд╢рди рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ
CREATE FUNCTION Dates.GetDateAdjusted(@AdjustDate AS DATETIME2,@CalendarFunction INT,@AdjustDays AS INT,@AdjustMode BIT,@AdjustWeekEnds BIT,@AdjustHolidays BIT) RETURNS DATETIME2 AS BEGIN
SELECT @AdjustDate=DATEADD(DAY,(CASE @AdjustMode WHEN 0 THEN -1 ELSE 1 END),@AdjustDate),
@AdjustDays=(CASE @AdjustMode WHEN 0 THEN @AdjustDays+1 ELSE (0-@AdjustDays)-1 END)
DECLARE @AdjustCount INT=0,@AdjustWorkDays INT=0,@Date DATETIME2=@AdjustDate
/*Add Days*/
WHILE @AdjustMode=0 AND @AdjustWorkDays < @AdjustDays
BEGIN
SET @AdjustCount=@AdjustCount+1
SET @Date=DATEADD(DAY,@AdjustCount,@AdjustDate)
IF NOT ((DATEPART(WEEKDAY,@Date) IN (1,7) AND @AdjustWeekEnds=1)
OR
EXISTS (SELECT * FROM Dates.CalendarHolidays WHERE CalendarDate=@Date AND CalendarFunction=@CalendarFunction AND @AdjustHolidays=1))
BEGIN
SET @AdjustWorkDays = @AdjustWorkDays + 1
END
END
/*Subtract Days*/
WHILE @AdjustMode=1 AND @AdjustWorkDays > @AdjustDays
BEGIN
SET @AdjustCount=@AdjustCount-1
SET @Date=DATEADD(DAY,@AdjustCount,@AdjustDate)
IF NOT ((DATEPART(WEEKDAY,@Date) IN (1,7)AND @AdjustWeekEnds=1)
OR
EXISTS (SELECT * FROM Dates.CalendarHolidays WHERE CalendarDate=@Date AND CalendarFunction=@CalendarFunction AND @AdjustHolidays=1))
BEGIN
SET @AdjustWorkDays = @AdjustWorkDays - 1
END
END
RETURN @Date
END
GO
SELECT Dates.GetDateAdjusted('2014-05-01',0,1,0,1,1)--'2014-05-02'
SELECT Dates.GetDateAdjusted('2014-05-01',0,2,0,0,0)--'2014-05-03'
SELECT Dates.GetDateAdjusted('2014-05-01',0,2,0,1,1)--'2014-05-06'
SELECT Dates.GetDateAdjusted('2014-05-01',0,3,0,1,1)--'2014-05-07'
SELECT Dates.GetDateAdjusted('2014-05-01',0,4,0,1,1)--'2014-05-08'
SELECT Dates.GetDateAdjusted('2014-05-01',0,5,0,1,1)--'2014-05-09'
SELECT Dates.GetDateAdjusted('2014-05-01',0,6,0,1,1)--'2014-05-12'