Q&A: How do I figure out what the last day of the month is?

I was trying to write a roll-your-own timezone converter and I needed a way of determining what the last possible day of the month was. Upon some research, I discovered the formulas for finding a leap year.

It's a small contribution, but maybe I'll save someone else the 20 minutes it took me to figure out and apply it.

This code accepts a signed short month, indexed at 0 (0 is January) and an int year that is indexed as 0 as well (2012 is 2012).

It returns a 1 indexed day (the 27th is the 27th, but in SYSTEMTIME structures, etc., you usually need 0 indexed - just a head's up).


Solution 1:

short _get_max_day(short month, int year) {
    if(month == 0 || month == 2 || month == 4 || month == 6 || month == 7 || month == 9 || month == 11)
        return 31;
    else if(month == 3 || month == 5 || month == 8 || month == 10)
        return 30;
    else {
        if(year % 4 == 0) {
            if(year % 100 == 0) {
                if(year % 400 == 0)
                    return 29;
                return 28;
            }
            return 29;
        }
        return 28;
    }
}

Solution 2:

What about

#include <time.h>
#include <iostream>

int LastDay (int iMonth, int iYear)
{
    struct tm when;
    time_t lastday;

    // Set up current month
    when.tm_hour = 0;
    when.tm_min = 0;
    when.tm_sec = 0;
    when.tm_mday = 1;

    // Next month 0=Jan
    if (iMonth == 12)
    {
        when.tm_mon = 0;
        when.tm_year = iYear - 1900 + 1;
    }
    else
    {
        when.tm_mon = iMonth;
        when.tm_year = iYear - 1900;
    }
    // Get the first day of the next month
    lastday = mktime (&when);

    // Subtract 1 day
    lastday -= 86400;

    // Convert back to date and time
    when = *localtime (&lastday);

    return when.tm_mday;
}

int _tmain(int argc, _TCHAR* argv[])
{
    for (int m = 1; m <= 12; m++)
        std::cout << "Last day of " << m << " is " << LastDay (m, 2002) << std::endl;

    return 0;
}

It prints out (for year 2002)...

Last day of 1 is 31
Last day of 2 is 28
Last day of 3 is 31
Last day of 4 is 30
Last day of 5 is 31
Last day of 6 is 30
Last day of 7 is 31
Last day of 8 is 31
Last day of 9 is 30
Last day of 10 is 31
Last day of 11 is 30
Last day of 12 is 31