Last day of Month

  • This is probably the fastest and shortest method for finding the last day of the month, given the year and month as integers, since it uses only a single DATEADD function call.

    It works for the full range of the DATETIME datatype from 1753 thru 9999 and handles leap year correctly.

    select

    *,

    LastDayOfMonth = dateadd(month,(12*[Year])-22800+[Month],-1)

    from

    (--Test Data

    select [Year] = 1753, [Month] = 1union all

    select [Year] = 2011, [Month] = 1union all

    select [Year] = 2011, [Month] = 2union all

    select [Year] = 2011, [Month] = 3union all

    select [Year] = 2011, [Month] = 4union all

    select [Year] = 2011, [Month] = 5union all

    select [Year] = 2011, [Month] = 6union all

    select [Year] = 2011, [Month] = 7union all

    select [Year] = 2011, [Month] = 8union all

    select [Year] = 2011, [Month] = 9union all

    select [Year] = 2011, [Month] = 10union all

    select [Year] = 2011, [Month] = 11union all

    select [Year] = 2011, [Month] = 12union all

    select [Year] = 2012, [Month] = 1union all

    select [Year] = 2012, [Month] = 2union all

    select [Year] = 9999, [Month] = 12

    ) a

    Year Month LastDayOfMonth

    ----------- ----------- -----------------------

    1753 1 1753-01-31 00:00:00.000

    2011 1 2011-01-31 00:00:00.000

    2011 2 2011-02-28 00:00:00.000

    2011 3 2011-03-31 00:00:00.000

    2011 4 2011-04-30 00:00:00.000

    2011 5 2011-05-31 00:00:00.000

    2011 6 2011-06-30 00:00:00.000

    2011 7 2011-07-31 00:00:00.000

    2011 8 2011-08-31 00:00:00.000

    2011 9 2011-09-30 00:00:00.000

    2011 10 2011-10-31 00:00:00.000

    2011 11 2011-11-30 00:00:00.000

    2011 12 2011-12-31 00:00:00.000

    2012 1 2012-01-31 00:00:00.000

    2012 2 2012-02-29 00:00:00.000

    9999 12 9999-12-31 00:00:00.000

    Based on code from this thread:

    Converting Year, Month, and Day to DateTime

    The functions on this link will take input parameters of Year, Month, and Day and return a datetime.

    Make Date function (like in VB):

    http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=22339

  • @michael-2 Pretty slick script!:cool:

    Thanks for posting.:-)

    For better, quicker answers on T-SQL questions, click on the following...
    http://www.sqlservercentral.com/articles/Best+Practices/61537/

    For better answers on performance questions, click on the following...
    http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • -Syd- (12/2/2011)


    Here is what you need in your store procedure

    declare @uptoMonth as int

    declare @year as int

    declare @LASTDAY VARCHAR(10)

    declare @lear as int

    set @leap = (select case datepart(mm, dateadd(dd, 1, cast((cast(@year as varchar(4)) + '0228') as datetime))) when 2 then 1 else 0 end)

    IF @uptoMonth IN (1,3,5,7,8,10,12)

    BEGIN

    SET @LASTDAY = CAST(@year as varchar(4))+'-'+CAST(@uptoMonth as varchar(2))+'-31'

    END

    IF @uptoMonth IN (4,6,9,11)

    BEGIN

    SET @LASTDAY = CAST(@year as varchar(4))+'-'+CAST(@uptoMonth as varchar(2))+'-30'

    END

    IF @uptoMonth = 2

    BEGIN

    IF @leap = 1

    BEGIN

    SET @LASTDAY = CAST(@year as varchar(4))+'-'+CAST(@uptoMonth as varchar(2))+'-29'

    END

    ELSE

    BEGIN

    SET @LASTDAY = CAST(@year as varchar(4))+'-'+CAST(@uptoMonth as varchar(2))+'-28'

    END

    END

    Just show the variable @LASTDAY and its done!

    Syd, take a look at the set-based methods that Jeff Williams and Michael Valentine Jones posted. Lot's less code, as well and no special calculation required for Leap Years.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • declare @year int

    declare @uptomonth int

    declare @Date datetime

    set @year=2011

    set @uptomonth=12

    set @date=convert(datetime,convert(varchar(10),@year)+'-'+convert(varchar(10),@uptomonth)+'-'+'01')

    select dateadd(dd,-1,dateadd(mm,1,@date))

  • declare @year int

    declare @uptomonth int

    declare @Date datetime

    set @year=2011

    set @uptomonth=12

    set @date=convert(datetime,convert(varchar(10),@year)+'-'+convert(varchar(10),@uptomonth)+'-'+'01')

    select dateadd(dd,-1,dateadd(mm,1,@date))

  • select dateadd(DD,-1,dateadd(MM,@uptomonth,cast(str(@year,4)+'-01-01'as date)))

    Tom

  • Jeffrey Williams 3188 (12/2/2011)


    Select dateadd(month, datediff(month, -1, cast(@year as char(4)) + '-' + cast(@month as varchar(2)) + '-01'), -1)

    Jeff,

    I missed your post. Very nice.:cool:

    For better, quicker answers on T-SQL questions, click on the following...
    http://www.sqlservercentral.com/articles/Best+Practices/61537/

    For better answers on performance questions, click on the following...
    http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • Just a point of interest... Michael is correct. Anything you can do to stay away from character based conversions on these types of calculations will increase the performance of those calculations.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Jeffrey Williams 3188 (12/2/2011)


    Select dateadd(month, datediff(month, -1, cast(@year as char(4)) + '-' + cast(@month as varchar(2)) + '-01'), -1)

    That code is sensitive to the setting of DATEFORMAT. In the following example, it gives January 31 as the last day of the month for every month.

    set dateformat ydm

    select

    *,

    LastDayOfMonth =

    dateadd(month, datediff(month, -1, cast([Year] as char(4)) + '-' + cast([Month] as varchar(2)) + '-01'), -1)

    from

    (--Test Data

    select [Year] = 2000, [Month] = 2union all

    select [Year] = 2011, [Month] = 1union all

    select [Year] = 2011, [Month] = 2union all

    select [Year] = 2011, [Month] = 12union all

    select [Year] = 2012, [Month] = 1union all

    select [Year] = 2012, [Month] = 2union all

    select [Year] = 9999, [Month] = 12

    ) a

    Results:

    Year Month LastDayOfMonth

    ----------- ----------- -----------------------

    2000 2 2000-01-31 00:00:00.000

    2011 1 2011-01-31 00:00:00.000

    2011 2 2011-01-31 00:00:00.000

    2011 12 2011-01-31 00:00:00.000

    2012 1 2012-01-31 00:00:00.000

    2012 2 2012-01-31 00:00:00.000

    9999 12 9999-01-31 00:00:00.000

  • Michael Valentine Jones (12/2/2011)


    This is probably the fastest and shortest method for finding the last day of the month, given the year and month as integers, since it uses only a single DATEADD function call.

    It works for the full range of the DATETIME datatype from 1753 thru 9999 and handles leap year correctly.

    Yes, but in this day and age shouldn't we be doing something that will work with the full range of the DATE type? it's easy enough to adapt this code to so so, just requires a double cast on that -1 to get it from INT to DATE.

    So, in the form that would be needed in a SP with the two specified parameters, it would be

    select DATEADD(MM,(12*@year)-22800+@uptomonth,CAST(CAST (-1 as DATETIME)as DATE))

    edit: tried to get the coloring right with this somewhat disfunctional tag - but failed

    Tom

  • Michael Valentine Jones (12/3/2011)


    Jeffrey Williams 3188 (12/2/2011)


    Select dateadd(month, datediff(month, -1, cast(@year as char(4)) + '-' + cast(@month as varchar(2)) + '-01'), -1)

    That code is sensitive to the setting of DATEFORMAT. In the following example, it gives January 31 as the last day of the month for every month.

    set dateformat ydm

    select

    *,

    LastDayOfMonth =

    dateadd(month, datediff(month, -1, cast([Year] as char(4)) + '-' + cast([Month] as varchar(2)) + '-01'), -1)

    from

    (--Test Data

    select [Year] = 2000, [Month] = 2union all

    select [Year] = 2011, [Month] = 1union all

    select [Year] = 2011, [Month] = 2union all

    select [Year] = 2011, [Month] = 12union all

    select [Year] = 2012, [Month] = 1union all

    select [Year] = 2012, [Month] = 2union all

    select [Year] = 9999, [Month] = 12

    ) a

    Results:

    Year Month LastDayOfMonth

    ----------- ----------- -----------------------

    2000 2 2000-01-31 00:00:00.000

    2011 1 2011-01-31 00:00:00.000

    2011 2 2011-01-31 00:00:00.000

    2011 12 2011-01-31 00:00:00.000

    2012 1 2012-01-31 00:00:00.000

    2012 2 2012-01-31 00:00:00.000

    9999 12 9999-01-31 00:00:00.000

    This can be corrected with a little change - but, it requires more functions:

    SELECT dateadd(month, datediff(month, -1, cast([Year] As char(4)) + right('0' + cast([Month] As varchar(2)), 2) + '01'), -1)

    I will say I like Michael's solution better though - simpler and better performing.

    Jeffrey Williams
    “We are all faced with a series of great opportunities brilliantly disguised as impossible situations.”

    ― Charles R. Swindoll

    How to post questions to get better answers faster
    Managing Transaction Logs

  • I used a variation of the code in numerous places provided to detemine the last day of the current month.

    SELECT dateadd(month, datediff(month, -1, cast(DATEPART(yyyy, GETDATE() )

    As char(4)) + right('0' + cast(DATEPART(mm, GETDATE())

    As varchar(2)), 2) + '01'), -1)AS LastDayCurMonth

    For better, quicker answers on T-SQL questions, click on the following...
    http://www.sqlservercentral.com/articles/Best+Practices/61537/

    For better answers on performance questions, click on the following...
    http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • Post withdrawn... Books Online was totally wrong about what would happen on something and I'm testing more on the subject of datatype precedence.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Post withdrawn... Books Online was totally wrong about what would happen on something and I'm testing more on the subject of datatype precedence.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • bhaveshp.dba (12/2/2011)


    Hello All,

    How can I calculate last day of month?

    I have two parameter in stored procedure

    create procedure

    (@year int,

    @uptomonth)

    as

    begin

    ....................................

    end

    I want to calculate last day of the Month ....

    based on parameter passing in stored procedure.

    If I am passing

    @year =2011

    @uptoMonnth =9

    then ouput like '2011-09-30'

    another example like

    If I am passing

    @year =2011

    @uptoMonnth =10

    then ouput like '2011-10-31'

    Thanks

    Bhavesh

    Question no one has asked, how is this value being used in the query run in the stored procedure?

    This will have an impact on how you actually want to calculate the value. Also, what is the datatyoe of the column being compared in the query?

Viewing 15 posts - 16 through 30 (of 44 total)

You must be logged in to reply to this topic. Login to reply