Script to create a function to get previous and next working day.

CREATE FUNCTION dbo.udf_GetPrevNextWorkDay (@dtDate DATETIME, @strPrevNext VARCHAR(10)) RETURNS DATETIME AS BEGIN DECLARE @intDay INT DECLARE @rtResult DATETIME SET @intDay = DATEPART(weekday,@dtDate) --To find Previous working day IF @strPrevNext = 'Previous' IF @intDay = 1 SET @rtResult = DATEADD(d,-2,@dtDate) ELSE IF @intDay = 2 SET @rtResult = DATEADD(d,-3,@dtDate) ELSE SET @rtResult = DATEADD(d,-1,@dtDate) --To find Next working day ELSE IF @strPrevNext = 'Next' IF @intDay = 6 SET @rtResult = DATEADD(d,3,@dtDate) ELSE IF @intDay = 7 SET @rtResult = DATEADD(d,2,@dtDate) ELSE SET @rtResult = DATEADD(d,1,@dtDate) --Default case returns date passed to function ELSE SET @rtResult = @dtDate RETURN @rtResult END GO

Following examples will execute the above function and provide the desired results.

SELECT dbo.udf_GetPrevNextWorkDay('1/1/2007','Previous') SELECT dbo.udf_GetPrevNextWorkDay('1/1/2007','Next') SELECT dbo.udf_GetPrevNextWorkDay('12/31/2007','Previous') SELECT dbo.udf_GetPrevNextWorkDay('12/31/2007','Next')

Let me know what you think of this blog post. I personally found this one of the most interesting functions related to daytime and worth bookmarking.

Reference : **Pinal Dave (****https://blog.sqlauthority.com****)**

## 16 Comments. Leave new

Hi Pianl,

Hello, how are you? I need help with a sql query that I am trying to write. I am trying to convert a date into a day in a query where a field called eventstartdttm is a varchar field that holds date and time

for example if substring(eventstartdttm, 0,9) returns 30th Jan 2008 then I need it to say Wednesday. Is there a function that can help me do that? Thanks

Warm Regards,

Chitra

Try it:

select DATENAME(dw ,convert(datetime, substring(eventstartdttm, 0,9),3))

— 3 for format dd/MM/yy

Good-Luck!

I am a newbie in SQL

I am trying to structure a query wherein

I need to display data where the Qtrly end dates(3/31,6/30/9/30/12/31) have been moved for vendors.

also The Table has multiple records for the same vedor ending in 3/31 and I need to take a max

When I tried using date diff between Quarters for different Years it does not work.. any help here is appreciated

Hi,

I am looking for a function through which I can calculate a particular working day. let say I want to know the 8th working day from todays date.

Any help??? its urgent..

Thanks in advance.

Rahul

@RAHUL

You mean this ??

select datename(dd,getdate()+8)

Result: 25

select datename (dw,getdate() +8)

Result : Friday –(if today is July 17, Thursday)

This is a great function and I really like how this function works . Is there any way to account for Holidays? I have seen something where one could enter Holidays in a table (eg – tblHolidays –>brilliant naming huh?). When the workday falls on the date in the table, the function would then go onto the next working day.

How would I modify this Function to do this?

Just came across the need to do this myself. I made the function just call itself again in the event that the previous/next date falls on a holiday.

IF EXISTS(SELECT * FROM tblHolidays WHERE HolidayDate = @EndDate)

BEGIN

SELECT @EndDate = dbo.udf_GetPrevNextWorkDay(@EndDate, @strPrevNext)

END

hi Pianl,

I need a help from u.

I am having a field name issueDate datatype as smalldatetime.

I need this field and also the previous date

ex: Item id ItemName IssueDate

1023 XXXX 12/02/2009

1023 XXXX 13/02/2009

I need the answer is diff between the 13/02/2009(LastDate) – 12/02/2009(previous date)

Simple and good…!!!

Works well for me…

select DATEDIFF ( day , ’02/13/2009′ , ’02/12/2009′ )

select DATEDIFF ( hour , ’02/13/2009′ , ’02/12/2009′ )

how can i get the balance which the only given is the breakdown of payments, transaction amount and transaction date and i will use the transaction date as parameters.

for example(table form): this shoul be the output:

customer trans_amt payments trans_date balance

robert 200 10 1-1-09 190

robert 200 50 1-5-09 140

robert 200 60 1-7-09 80

i want to get balance for every trans_date

please help me

thanks

robert

how can i get the balance which the only given is the breakdown of payments, transaction amount and transaction date and i will use the transaction date as parameters.

for example(table form): this shoul be the output:

customer—-trans_amt—-payments—trans_date—-balance

robert——–200————–10———-1-1-09———-190

robert——–200————–50———-1-5-09———-140

robert——–200————–60———-1-7-09———-80

i want to get balance for every trans_date

please help me

thanks

robert

Built off this script to create the following udf that has option to exclude holidays and also to retrieve more than just 1 day prev/next:

CREATE FUNCTION dbo.udfGetPrevNextWorkDay

(

@StartDate DATETIME,

@bGetPrevious BIT = 0,

@bExcludeHolidays BIT = 1,

@MultipleDayCount INT = 0

)

RETURNS DATETIME

AS

BEGIN

DECLARE @EndDate DATETIME, @Day NVARCHAR(10), @DayCount INT

SET @Day = DATENAME(weekday, @StartDate)

IF @MultipleDayCount > 0

BEGIN

DECLARE @MultipleDayIndex INT, @MultipleDayDate DATETIME

SET @MultipleDayDate = @StartDate

SET @MultipleDayIndex = 1

WHILE @MultipleDayIndex < @MultipleDayCount

BEGIN

SELECT @MultipleDayDate = dbo.udfGetPrevNextWorkDay(@MultipleDayDate, @bGetPrevious, @bExcludeHolidays, 0)

SET @MultipleDayIndex = @MultipleDayIndex + 1

END

RETURN @MultipleDayDate

END

–To find Previous working day

IF @bGetPrevious = 1

BEGIN

SELECT @DayCount =

CASE @Day WHEN 'Sunday' THEN -2

WHEN 'Monday' THEN -3

ELSE -1

END

END

–To find Next working day

IF @bGetPrevious = 0

BEGIN

SELECT @DayCount =

CASE @Day WHEN 'Friday' THEN 3

WHEN 'Saturday' THEN 2

ELSE 1

END

END

SET @EndDate = DATEADD(d,@DayCount,@StartDate)

IF (@bExcludeHolidays = 1) AND (EXISTS(SELECT * FROM tblzcdIndexHoliday WHERE IndexHolidayCelebrationDate = @EndDate))

BEGIN

SELECT @EndDate = dbo.udfGetPrevNextWorkDay(@EndDate, @bGetPrevious, @bExcludeHolidays, 0)

END

RETURN ISNULL(@EndDate, @StartDate)

END

Script to calculate hollidays (i.e not using a table… Tricky part is Easter :)

— Drop function if exists

IF EXISTS (SELECT * FROM dbo.sysobjects WHERE [id] = OBJECT_ID(N'[dbo].[IsHolliday]’) AND xtype IN (N’FN’, N’IF’, N’TF’)) DROP FUNCTION [dbo].[IsHolliday]

GO

— Create function

CREATE FUNCTION dbo.IsHolliday

— +————————————————————————–+

— | Function : IsHolliday |

— | Author : Martin Grape |

— | Version : 1.1 |

— | Description : Returns 1 for holliday and 0 for all other days |

— | Parameters : @IsHolliday – Date to check |

— | Returns : 0 (workday) or 1 (holliday) |

— | Other : This is calculation for Swedish hollidays |

— | Example : SELECT dbo.IsHolliday(‘2010-04-04′) –> 1 |

— +————————————————————————–+

(

@IsHolliday DATETIME

)

RETURNS INT

AS

BEGIN

— Declare variables

DECLARE @IsHollidayResult INT

DECLARE @IsHollidayYear INT

DECLARE @IsHollidayMonth INT

DECLARE @IsHollidayDay INT

DECLARE @IsHollidayMonthDay VARCHAR(5)

DECLARE @IsHollidayEasterDate DATETIME

— Declare variables

SET @IsHollidayYear = YEAR(@IsHolliday)

SET @IsHollidayMonth = MONTH(@IsHolliday)

SET @IsHollidayDay = DAY(@IsHolliday)

SET @IsHollidayMonthDay = RIGHT(CONVERT(CHAR(10), @IsHolliday, 120), 5)

— Set starting values

SET @IsHollidayResult = 0

— Check for set dates (this is for Sweden)

SET @IsHollidayResult = CASE WHEN @IsHollidayMonthDay IN (’01-01′, ’01-06′, ’05-01′, ’12-25′, ’12-26′) THEN 1 ELSE @IsHollidayResult END

SET @IsHollidayResult = CASE WHEN @IsHollidayResult = 0 AND @IsHollidayMonthDay = ’06-06’ AND @IsHollidayYear > 2004 THEN 1 ELSE @IsHollidayResult END

— Return if a set date

IF @IsHollidayResult = 1 BEGIN

RETURN @IsHollidayResult

END

— Calculate easter date

SET @IsHollidayEasterDate = CONVERT(DATETIME, CONVERT(CHAR(4), @IsHollidayYear) + ‘-‘ +

RIGHT(’00’ + CONVERT(VARCHAR, CONVERT(INT, ((((19 * (@IsHollidayYear % 19) + (CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) / 4)) – (CONVERT(INT, ((CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) + 8) / 25) + 1) / 3)) + 15) % 30)) + (((32 + 2 * ((CONVERT(INT, @IsHollidayYear / 100)) % 4) + 2 * (CONVERT(INT, (@IsHollidayYear % 100) / 4)) – (((19 * (@IsHollidayYear % 19) + (CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) / 4)) – (CONVERT(INT, ((CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) + 8) / 25) + 1) / 3)) + 15) % 30)) – ((@IsHollidayYear % 100) % 4)) % 7)) – 7 * (CONVERT(INT, ((@IsHollidayYear % 19) + 11 * (((19 * (@IsHollidayYear % 19) + (CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) / 4)) – (CONVERT(INT, ((CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) + 8) / 25) + 1) / 3)) + 15) % 30)) + 22 * (((32 + 2 * ((CONVERT(INT, @IsHollidayYear / 100)) % 4) + 2 * (CONVERT(INT, (@IsHollidayYear % 100) / 4)) – (((19 * (@IsHollidayYear % 19) + (CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) / 4)) – (CONVERT(INT, ((CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) + 8) / 25) + 1) / 3)) + 15) % 30)) – ((@IsHollidayYear % 100) % 4)) % 7))) / 451)) + 114) / 31)), 2) + ‘-‘ +

RIGHT(’00’ + CONVERT(VARCHAR, (((((19 * (@IsHollidayYear % 19) + (CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) / 4)) – (CONVERT(INT, ((CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) + 8) / 25) + 1) / 3)) + 15) % 30)) + (((32 + 2 * ((CONVERT(INT, @IsHollidayYear / 100)) % 4) + 2 * (CONVERT(INT, (@IsHollidayYear % 100) / 4)) – (((19 * (@IsHollidayYear % 19) + (CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) / 4)) – (CONVERT(INT, ((CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) + 8) / 25) + 1) / 3)) + 15) % 30)) – ((@IsHollidayYear % 100) % 4)) % 7)) – 7 * (CONVERT(INT, ((@IsHollidayYear % 19) + 11 * (((19 * (@IsHollidayYear % 19) + (CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) / 4)) – (CONVERT(INT, ((CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) + 8) / 25) + 1) / 3)) + 15) % 30)) + 22 * (((32 + 2 * ((CONVERT(INT, @IsHollidayYear / 100)) % 4) + 2 * (CONVERT(INT, (@IsHollidayYear % 100) / 4)) – (((19 * (@IsHollidayYear % 19) + (CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) / 4)) – (CONVERT(INT, ((CONVERT(INT, @IsHollidayYear / 100)) – (CONVERT(INT, (CONVERT(INT, @IsHollidayYear / 100)) + 8) / 25) + 1) / 3)) + 15) % 30)) – ((@IsHollidayYear % 100) % 4)) % 7))) / 451)) + 114) % 31) + 1), 2))

— Easter

IF @IsHolliday = @IsHollidayEasterDate – 2 OR

@IsHolliday = @IsHollidayEasterDate OR

@IsHolliday = @IsHollidayEasterDate + 1 BEGIN

RETURN 1

END

— Ascension Day

IF @IsHolliday = DATEADD(dd, 39, @IsHollidayEasterDate) BEGIN

RETURN 1

END

— Whitsun

IF @IsHolliday = DATEADD(dd, 49, @IsHollidayEasterDate) OR

(@IsHolliday = DATEADD(dd, 50, @IsHollidayEasterDate) AND @IsHollidayYear < 2005) BEGIN

RETURN 1

END

— Midsummer

IF @IsHolliday = DATEADD(dd, 7 – DATEPART(dw, CONVERT(CHAR(4), @IsHollidayYear) + '-06-20'), CONVERT(CHAR(4), @IsHollidayYear) + '-06-20') BEGIN

RETURN 1

END

— Halloween

IF @IsHolliday = DATEADD(dd, 7 – DATEPART(dw, CONVERT(CHAR(4), @IsHollidayYear) + '-10-31'), CONVERT(CHAR(4), @IsHollidayYear) + '-10-31') BEGIN

RETURN 1

END

RETURN 0

END

GO

it’s usefull..

thanks for your code..

:D

Hi,

I need help in A stored procedure.

I have to calculate a parameter only on week days,

For eg if i give input date to be 10th october(Sunday) and today is 28th october.

I have to calculate these parameters for 5 weekdays..

So if i give A date which is a sunday then it should automatically skip that day and should calculate from Monday to friday.

Another eg. Suppose the input date is a wednesday, then calculate the parameters for wednesday, thursday, friday, moday and tuesday.

Skipping the Saturday and sunday.

Could you please suggest a way out of this.