Title: Moment JS start and end of given month
Tags: javascript;momentjs
Question: I need to calculate a JS date given year=2014 and month=9 (September 2014).
I tried this:
var moment = require('moment');
var startDate = moment( year+'-'+month+'-'+01 + ' 00:00:00' );
var endDate = startDate.endOf('month');
console.log(startDate.toDate());
console.log(endDate.toDate());
Both of logs show:
Tue Sep 30 2014 23:59:59 GMT+0200 (CEST)
Tue Sep 30 2014 23:59:59 GMT+0200 (CEST)
End date is correct but... why the start date is not?

Here is the accepted answer: That's because endOf mutates the original value.
Relevant quote:
Mutates the original moment by setting it to the end of a unit of time.
Here's an example function that gives you the output you want:
function getMonthDateRange(year, month) {
var moment = require('moment');
// month in moment is 0 based, so 9 is actually october, subtract 1 to compensate
// array is 'year', 'month', 'day', etc
var startDate = moment([year, month - 1]);
// Clone the value before .endOf()
var endDate = moment(startDate).endOf('month');
// just for demonstration:
console.log(startDate.toDate());
console.log(endDate.toDate());
// make sure to call toDate() for plain JavaScript date type
return { start: startDate, end: endDate };
References:
endOf()
clone()
Date from object
Comment for this answer: `add(-1,"month")` doesn't work when its January and you want to get the last year's month.
Comment for this answer: Absolutely, in fact the default way to clone an object in the documentation is `moment()`. Updated the example to use some of the shorter functions.
Comment for this answer: Looks like `add(-1,"month")` was added in an edit. I've removed it, looks like the code works properly now. In general though, if you use this (or any code from stack overflow), please rewrite and test drive it! (and then let me know what I screwed up so I can fix the answer :))
Comment for this answer: `moment` is idempotent so you could also use `endDate = moment(starDate).endOf("month")` **^.^**
Comment for this answer: first time I've ever seen the word idempotent used on the web!! well done naomik
Comment for this answer: Thank you. I spent two hours trying to figure out why it wasnt working.
Comment for this answer: Good stuff, but last comment happens to me too.

Here is another answer: your startDate is first-day-of-month, In this case we can use
var endDate = moment(startDate).add(1, 'months').subtract(1, 'days');
Hope this helps!!

Here is another answer: Don't really think there is some direct method to get the last day but you could do something like this:
var dateInst = new moment();
* adding 1 month from the present month and then subtracting 1 day,
* So you would get the last day of this month
dateInst.add(1, 'months').date(1).subtract(1, 'days');
/* printing the last day of this month's date */
console.log(dateInst.format('YYYY MM DD'));

Here is another answer: var d = new moment();
var startMonth = d.clone().startOf('month');
var endMonth = d.clone().endOf('month');
console.log(startMonth, endMonth);

Here is another answer: The following code should work:
$('#reportrange').daterangepicker({
startDate: start,
endDate: end,
ranges: {
'Hoy': [moment(), moment()],
'Ayer': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
'Ultimos 7 dias': [moment().subtract(6, 'days'), moment()],
'Ultimos 30 dias': [moment().subtract(29, 'days'), moment()],
'Mes actual': [moment().startOf('month'), moment().endOf('month')],
'Ultimo mes': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')],
'Enero': [moment().month(0).startOf('month') , moment().month(0).endOf('month')],
'Febrero': [moment().month(1).startOf('month') , moment().month(1).endOf('month')],
'Marzo': [moment().month(2).startOf('month') , moment().month(2).endOf('month')],
'Abril': [moment().month(3).startOf('month') , moment().month(3).endOf('month')],
'Mayo': [moment().month(4).startOf('month') , moment().month(4).endOf('month')],
'Junio': [moment().month(5).startOf('month') , moment().month(5).endOf('month')],
'Julio': [moment().month(6).startOf('month') , moment().month(6).endOf('month')],
'Agosto': [moment().month(7).startOf('month') , moment().month(7).endOf('month')],
'Septiembre': [moment().month(8).startOf('month') , moment().month(8).endOf('month')],
'Octubre': [moment().month(9).startOf('month') , moment().month(9).endOf('month')],
'Noviembre': [moment().month(10).startOf('month') , moment().month(10).endOf('month')],
'Diciembre': [moment().month(11).startOf('month') , moment().month(11).endOf('month')]
}
}, cb);

Here is another answer: Try the following code:
const moment=require('moment');
console.log("startDate=&gt;",moment().startOf('month').format("YYYY-DD-MM"));
console.log("endDate=&gt;",moment().endOf('month').format("YYYY-DD-MM"));
Comment for this answer: you should add some context with your code to explain why and how it will solve the problem

Here is another answer: Here is a concise &amp; exact answer:
// month in moment is 0 based, so 0 is actually january, subtract 1 to compensate.
var startDate = moment([year, month - 1]).format()
var endDate = moment(startDate).clone().endOf('month').format()
Example
let month = 1         // January
let year = 2021
var startDate = moment([year, month - 1]).format()
var endDate = moment(startDate).clone().endOf('month').format()
console.log(startDate)
//2021-01-01T00:00:00-07:00
console.log(endDate)
//2021-01-31T23:59:59-07:00
Comment for this answer: Dear @HereticMonkey. The endDate of accepted answer was coming the first date of the next month like for example if the selected month is January, it was displaying the last date as the 1st of February. So I simplified it!
Comment for this answer: This is exactly the same as the accepted answer, except for the unnecessary step of formatting as a string, and the step of parsing that string to a moment.

Here is another answer: Try the following code:
moment(startDate).startOf('months')
moment(startDate).endOf('months')
Comment for this answer: Welcome to Stack Overflow. There are ten other answers to this question; it would be good of you to explain why yours is better or preferable than the others.
Comment for this answer: it is not giving expected o/p

Here is another answer: const dates = getDatesFromDateRange("2014-05-02", "2018-05-12", "YYYY/MM/DD", 1);
console.log(dates);
// you get the whole from-to date ranges as per parameters
var onlyStartDates = dates.map(dateObj =&gt; dateObj["to"]);
console.log(onlyStartDates);
// moreover, if you want only from dates then you can grab by "map" function
function getDatesFromDateRange( startDate, endDate, format, counter ) {
startDate = moment(startDate, format);
endDate = moment(endDate, format);
let dates = [];
let fromDate = startDate.clone();
let toDate = fromDate.clone().add(counter, "month").startOf("month").add(-1, "day");
do {
dates.push({
"from": fromDate.format(format),
"to": ( toDate < endDate ) ? toDate.format(format) : endDate.format(format)
});
fromDate = moment(toDate, format).add(1, "day").clone();
toDate = fromDate.clone().add(counter, "month").startOf("month").add(-1, "day");
} while ( fromDate < endDate );
return dates;
Please note, .clone() is essential in momentjs else it'll override the value. It seems in your case.
It's more generic, to get bunch of dates that fall between dates.

Here is another answer: const year = 2014;
const month = 09;
// months start at index 0 in momentjs, so we subtract 1
const startDate = moment([year, month - 1, 01]).format("YYYY-MM-DD");
// get the number of days for this month
const daysInMonth = moment(startDate).daysInMonth();
// we are adding the days in this month to the start date (minus the first day)
const endDate = moment(startDate).add(daysInMonth - 1, 'days').format("YYYY-MM-DD");
console.log(`start date: ${startDate}`);
console.log(`end date:   ${endDate}`);
<script
src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"&gt;
</script&gt;

Here is another answer: you can use this directly for the end or start date of the month
new moment().startOf('month').format("YYYY-DD-MM");
new moment().endOf("month").format("YYYY-DD-MM");
you can change the format by defining a new format

Here is another answer: When you use .endOf() you are mutating the object it's called on, so startDate becomes Sep 30
You should use .clone() to make a copy of it instead of changing it
var startDate = moment(year + '-' + month + '-' + 01 + ' 00:00:00');
var endDate = startDate.clone().endOf('month');
console.log(startDate.toDate());
console.log(endDate.toDate());
Mon Sep 01 2014 00:00:00 GMT+0700 (ICT)
Tue Sep 30 2014 23:59:59 GMT+0700 (ICT)

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 12, 'CommentCount': 0, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2014:00:09/30/14', 'FavoriteCount': 15.0, 'PostTypeId': 1, 'Tags': '<javascript><momentjs>', 'Title': 'Moment JS start and end of given month', 'ViewCount': 200624, 'id': 26131003, 'user_AboutMe': '<p><a href="http://www.linkedin.com/in/fabiobozzo" rel="nofollow noreferrer">http://www.linkedin.com/in/fabiobozzo</a></p>\n', 'user_AccountId': 230923.0, 'user_DisplayName': 'Fabio B.', 'user_Reputation': 8892.0, 'user_Views': 743.0, 'user_id': 494826.0}}