Nov 11

Get First and Last Day of Month

Tag: SQL Server, sqlJeremiah Peschka @ 10:39 pm

Just a quick post with two T-SQL functions to compute the first and last day of the month for any DATETIME. These have been incredibly useful on a daily basis and I figured that I would pass them along.

Keep in mind that these are inline scalar-value functions and will be evaluated for every row in a result set. This isn’t so bad when you only have a few rows, but when you have a million rows, it’s expensive. It’s much better to use the inline SQL computation if you need to work on a large number of results.

The third function will compute the first instance of the longest month between two dates. This is often used in utility billing to determine which month the bill should be applied to. An example would be a bill from January 1 to February 28. This bill would fall into January. If the bill were from January 15th to August 28th, the bill would be for March. It’s a more specific case than the first two, but still very useful in context.


CREATE FUNCTION dbo.GetFirstDayOfMonth (@Day DATETIME)
RETURNS DATETIME
AS
BEGIN
    RETURN
DATEADD(mm,DATEDIFF(mm,0,@Day),0);
END;


CREATE FUNCTION [dbo].[GetLastDayOfMonth] (@Day DATETIME)
RETURNS DATETIME
AS
BEGIN
    RETURN
DATEADD(ss,-1,DATEADD(mm,1,DATEADD(mm,DATEDIFF(mm,0,@Day),0)));
END;


CREATE FUNCTION [dbo].[ComputeFirstLongestMonth]
(
    
@StartDate DATETIME,
    
@EndDate   DATETIME
)
RETURNS DATETIME
AS
BEGIN
    DECLARE
@FirstDate         DATETIME;
    
DECLARE @LastDate          DATETIME;
    
DECLARE @FirstLongestMonth DATETIME;
    
DECLARE @MonthDiff         INT;
    
DECLARE @counter           INT;
    
DECLARE @DateDiff          INT;
    
DECLARE @PrevDateDiff      INT;

    
SET @counter      = 0;
    
SET @DateDiff     = 0;
    
SET @PrevDateDiff = 0;

    
SET @FirstDate = @StartDate;

    
SELECT @MonthDiff = DATEDIFF(mm, @StartDate, @EndDate);

    
WHILE @counter <= @MonthDiff
    
BEGIN
        SET
@LastDate = dbo.GetLastDayOfMonth(@FirstDate);

        
SET @DateDiff = DATEDIFF(dd, @FirstDate, @LastDate);

        
IF @DateDiff > @PrevDateDiff
        
BEGIN
            SET
@FirstLongestMonth = @FirstDate;
            
SET @PrevDateDiff = @DateDiff;
        
END
        ELSE
            BREAK
;

        
SET @FirstDate = dbo.GetFirstDayOfMonth(DATEADD(mm, 1, @FirstDate));
        
SET @counter = @counter + 1;
    
END

    RETURN
@FirstLongestMonth;
END

2 Responses to “Get First and Last Day of Month”

  1. Louis Davidson says:

    I like your code, nice stuff and great stuff to have around when you need it. I would suggest using a calendar table in most cases though, a lot easier to work with and certainly better for use in a JOIN condition or WHERE clause. Add a last_day_of_the_month column, first_day_of_the_month, even a number_of_days_in_month column and it turns into a simple query instead of a math problem…

  2. Jeremiah Peschka says:

    Thanks, @drsql! Using a calendar table is definitely the ideal solution and one that I’m planning on building and transitioning to later in the project.

Leave a Reply