Calculate last day of month

Viewed 430343

If you provide 0 as the dayValue in Date.setFullYear you get the last day of the previous month:

d = new Date(); d.setFullYear(2008, 11, 0); //  Sun Nov 30 2008

There is reference to this behaviour at mozilla. Is this a reliable cross-browser feature or should I look at alternative methods?

25 Answers

var month = 0; // January
var d = new Date(2008, month + 1, 0);
console.log(d.toString()); // last day in January

IE 6:                     Thu Jan 31 00:00:00 CST 2008
IE 7:                     Thu Jan 31 00:00:00 CST 2008
IE 8: Beta 2:             Thu Jan 31 00:00:00 CST 2008
Opera 8.54:               Thu, 31 Jan 2008 00:00:00 GMT-0600
Opera 9.27:               Thu, 31 Jan 2008 00:00:00 GMT-0600
Opera 9.60:               Thu Jan 31 2008 00:00:00 GMT-0600
Firefox 2.0.0.17:         Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Firefox 3.0.3:            Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Google Chrome 0.2.149.30: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Safari for Windows 3.1.2: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)

Output differences are due to differences in the toString() implementation, not because the dates are different.

Of course, just because the browsers identified above use 0 as the last day of the previous month does not mean they will continue to do so, or that browsers not listed will do so, but it lends credibility to the belief that it should work the same way in every browser.

I would use an intermediate date with the first day of the next month, and return the date from the previous day:

int_d = new Date(2008, 11+1,1);
d = new Date(int_d - 1);

I recently had to do something similar, this is what I came up with:

/**
* Returns a date set to the begining of the month
* 
* @param {Date} myDate 
* @returns {Date}
*/
function beginningOfMonth(myDate){    
  let date = new Date(myDate);
  date.setDate(1)
  date.setHours(0);
  date.setMinutes(0);
  date.setSeconds(0);   
  return date;     
}

/**
 * Returns a date set to the end of the month
 * 
 * @param {Date} myDate 
 * @returns {Date}
 */
function endOfMonth(myDate){
  let date = new Date(myDate);
  date.setDate(1); // Avoids edge cases on the 31st day of some months
  date.setMonth(date.getMonth() +1);
  date.setDate(0);
  date.setHours(23);
  date.setMinutes(59);
  date.setSeconds(59);
  return date;
}

Pass it in a date, and it will return a date set to either the beginning of the month, or the end of the month.

The begninngOfMonth function is fairly self-explanatory, but what's going in in the endOfMonth function is that I'm incrementing the month to the next month, and then using setDate(0) to roll back the day to the last day of the previous month which is a part of the setDate spec:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setDate https://www.w3schools.com/jsref/jsref_setdate.asp

I then set the hour/minutes/seconds to the end of the day, so that if you're using some kind of API that is expecting a date range you'll be able to capture the entirety of that last day. That part might go beyond what the original post is asking for but it could help someone else looking for a similar solution.

Edit: You can also go the extra mile and set milliseconds with setMilliseconds() if you want to be extra precise.

How NOT to do it

Beware of any answers for the last of the month that look like this:

var last = new Date(date)
last.setMonth(last.getMonth() + 1) // This is the wrong way to do it.
last.setDate(0)

This works for most dates, but fails if date is already the last day of the month, on a month that has more days than the following month.

Example:

Suppose date is 07/31/21.

Then last.setMonth(last.getMonth() + 1) increments the month, but keeps the day set at 31.

You get a Date object for 08/31/21,

which is actually 09/01/21.

So then last.setDate(0) results in 08/31/21 when what we really wanted was 07/31/21.

Try this:

function _getEndOfMonth(time_stamp) {
    let time = new Date(time_stamp * 1000);
    let month = time.getMonth() + 1;
    let year = time.getFullYear();
    let day = time.getDate();
    switch (month) {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            day = 31;
            break;
        case 4:
        case 6:
        case 9:
        case 11:
            day = 30;
            break;
        case 2:
            if (_leapyear(year))
                day = 29;
            else
                day = 28;
            break
    }
    let m = moment(`${year}-${month}-${day}`, 'YYYY-MM-DD')
    return m.unix() + constants.DAY - 1;
}

function _leapyear(year) {
    return (year % 100 === 0) ? (year % 400 === 0) : (year % 4 === 0);
}

You can get the First and Last Date in the current month by following the code:

var dateNow = new Date();  
var firstDate = new Date(dateNow.getFullYear(), dateNow.getMonth(), 1);  
var lastDate = new Date(dateNow.getFullYear(), dateNow.getMonth() + 1, 0);

or if you want to format the date in your custom format then you can use moment js

var dateNow= new Date();  
var firstDate=moment(new Date(dateNow.getFullYear(),dateNow.getMonth(), 1)).format("DD-MM-YYYY");  
var currentDate = moment(new Date()).format("DD-MM-YYYY"); //to  get the current date var lastDate = moment(new
 Date(dateNow.getFullYear(), dateNow.getMonth() + 1, 0)).format("DD-MM-YYYY"); //month last date

Here is an answer that conserves GMT and time of the initial date

var date = new Date();

var first_date = new Date(date); //Make a copy of the date we want the first and last days from
first_date.setUTCDate(1); //Set the day as the first of the month

var last_date = new Date(first_date); //Make a copy of the calculated first day
last_date.setUTCMonth(last_date.getUTCMonth() + 1); //Add a month
last_date.setUTCDate(0); //Set the date to 0, this goes to the last day of the previous month

console.log(first_date.toJSON().substring(0, 10), last_date.toJSON().substring(0, 10)); //Log the dates with the format yyyy-mm-dd

const today = new Date();

let beginDate = new Date();

let endDate = new Date();

// fist date of montg

beginDate = new Date(

  `${today.getFullYear()}-${today.getMonth() + 1}-01 00:00:00`

);

// end date of month 

// set next Month first Date

endDate = new Date(

  `${today.getFullYear()}-${today.getMonth() + 2}-01 :23:59:59`

);

// deducting 1 day

endDate.setDate(0);

If you need exact end of the month in miliseconds (for example in a timestamp):

d = new Date()
console.log(d.toString())
d.setDate(1)
d.setHours(23, 59, 59, 999)
d.setMonth(d.getMonth() + 1)
d.setDate(d.getDate() - 1)
console.log(d.toString())

The accepted answer doesn't work for me, I did it as below.

$( function() {
  $( "#datepicker" ).datepicker();
  $('#getLastDateOfMon').on('click', function(){
    var date = $('#datepicker').val();

    // Format 'mm/dd/yy' eg: 12/31/2018
    var parts = date.split("/");

    var lastDateOfMonth = new Date();
                lastDateOfMonth.setFullYear(parts[2]);
                lastDateOfMonth.setMonth(parts[0]);
                lastDateOfMonth.setDate(0);

     alert(lastDateOfMonth.toLocaleDateString());
  });
});
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <link rel="stylesheet" href="/resources/demos/style.css">
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
 
<p>Date: <input type="text" id="datepicker"></p>
<button id="getLastDateOfMon">Get Last Date of Month </button>
 
 
</body>
</html>

This will give you last day of current month.

notes: on ios device include time. #gshoanganh

var date = new Date();
console.log(new Date(date.getFullYear(), date.getMonth() + 1, 0, 23, 59, 59));

In my case, this code was useful

end_date = new Date(2018, 3, 1).toISOString().split('T')[0]
console.log(end_date)

Related