So real case scenario, I was asked to calculate real nights in a month. Below are the sample scenarios:
- If guest checked in at 2016-04-23, checked out at 2016-05-01, actual nights for May 2016 = 0 night
- If guest checked in at 2016-04-23, checked out at 2016-05-05, actual nights for May 2016 = 4 nights
- If guest checked in at 2016-05-23, checked out at 2016-05-27, actual nights for May 2016 = 4 nights
- If guest checked in at 2016-05-27, checked out at 2016-06-07, actual nights for May 2016 = 5 nights
- If guest checked in at 2016-04-27, checked out at 2016-06-07, actual nights for May 2016 = 31 nights
Here’s how I do it:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: David B
-- Created date: 2016-04-07
-- Description: Calculating how many nights for a period of stay in a month
-- How to use: select * from [dbo].[Fn_nightsmonth]('2015-01-25','2015-02-05',1 , 2015)
-- =============================================
CREATE FUNCTION [dbo].[Fn_nightsmonth](@StartDate datetime, @EndDate datetime, @for_month int, @for_year int)
RETURNS TABLE
AS
RETURN
Select
CASE
WHEN (DATEPART(MONTH, @StartDate) = @for_month and DATEPART(MONTH, @EndDate) = @for_month) and ((DATEPART(YEAR, @StartDate) = @for_year or DATEPART(YEAR, @EndDate) = @for_year)) THEN
DATEDIFF(DAY, @StartDate,@EndDate)
WHEN (@StartDate < cast(CONVERT(varchar(4), @for_year) + '-' + CONVERT(varchar(2), @for_month) + '-01' as date)) and (@EndDate between (cast(CONVERT(varchar(4), @for_year) + '-' + CONVERT(varchar(2), @for_month) + '-01' as date)) and (cast(DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, cast( CONVERT(varchar(4), @for_year) + '-' + CONVERT(varchar(2), @for_month) + '-01' as date)) + 1, 0)) as date))) THEN
DATEDIFF(DAY, DATEADD(MONTH, DATEDIFF(MONTH, -1, @EndDate)-1, 0),@EndDate)
WHEN (@EndDate > cast(DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, cast( CONVERT(varchar(4), @for_year) + '-' + CONVERT(varchar(2), @for_month) + '-01' as date)) + 1, 0)) as date)) and (@StartDate between (cast(CONVERT(varchar(4), @for_year) + '-' + CONVERT(varchar(2), @for_month) + '-01' as date)) and (cast(DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, cast( CONVERT(varchar(4), @for_year) + '-' + CONVERT(varchar(2), @for_month) + '-01' as date)) + 1, 0)) as date))) THEN
DATEDIFF(DAY, @StartDate,DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, @StartDate) + 1, 0))) + 1
WHEN ((DATEDIFF(DAY, @StartDate, cast(DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, cast( CONVERT(varchar(4), @for_year) + '-' + CONVERT(varchar(2), @for_month) + '-01' as date)) + 1, 0)) as date)) >= 0) and (DATEDIFF(DAY, cast(CONVERT(varchar(4), @for_year) + '-' + CONVERT(varchar(2), @for_month) + '-01' as date), @EndDate) >= 0)) THEN
DATEDIFF(DAY, cast( CONVERT(varchar(4), @for_year) + '-' + CONVERT(varchar(2), @for_month) + '-01' as datetime), DATEADD(d, -1, DATEADD(m, DATEDIFF(m, 0, cast( CONVERT(varchar(4), @for_year) + '-' + CONVERT(varchar(2), @for_month) + '-01' as datetime)) + 1, 0))) + 1
ELSE
0
END as [DD]
And what if you need between a range but not in a month let say weekly, then you can use below query:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: David B
-- Created date: 2016-06-07
-- Description: Calculating how many nights overlap between 2 date ranges
-- How to use: select * from [dbo].[Fn_dayoverlap]('2000-01-25','2000-02-05','2000-01-01','2000-01-31')
-- =============================================
CREATE FUNCTION [dbo].[Fn_dayoverlap](@StartDate1 datetime, @EndDate1 datetime, @StartDate2 datetime, @EndDate2 datetime)
RETURNS TABLE
AS
RETURN
SELECT CASE
WHEN (NOT((@EndDate2 < @StartDate1) or (@StartDate2 > @EndDate1))) THEN
DATEDIFF(DAY,
CASE WHEN @StartDate1 > @StartDate2 THEN @StartDate1 ELSE @StartDate2 END,
CASE WHEN @EndDate1 < @EndDate2 AND NOT(@EndDate1 >= @StartDate2) and (@StartDate2 > @StartDate1) THEN DATEADD(day,1,@EndDate1)
WHEN (@EndDate1 <= @EndDate2 AND (@EndDate1 >= @StartDate2)) or (@StartDate1 > @StartDate2 and @EndDate1 < @EndDate2) THEN @EndDate1
WHEN (@EndDate2 < @EndDate1 and (@StartDate1 > @StartDate2)) or (@StartDate2 > @StartDate1 and @EndDate1 > @EndDate2) or (@EndDate2 = @StartDate1) THEN DATEADD(day,1,@EndDate2)
WHEN @EndDate2 < @EndDate1 AND not (@EndDate2 = @StartDate1) THEN @EndDate2 END)
ELSE
0
END AS [DAY]
Latest posts by David B (see all)
- GeekOut Drivers - October 24, 2025
- Setup dnscrypt-proxy on Ubuntu 24.04 (Raspberry Pi 5) - September 4, 2024
- Mosh your VPS from Windows using Cygwin - May 12, 2024