function parseDate(s){
var parts = s.split('/')
return new Date(parts[2], parts[1], parts[0])
}
function calcDaysBetween(startDate, endDate){
return Math.floor((endDate-startDate)/86400000);
}
function yarro(){
var startDate = parseDate($('#pickupdate').val());
var endDate = parseDate($('#dropoffdate').val());
var days = calcDaysBetween(startDate, endDate);
$('#newp').html('Days Count: <b>'+days);
}
31/3/2012 , 1/4/2012
Days Count: 0 //wrong
or
31/1/2012 , 1/2/2012
Days Count: -1 //wrong
1/1/2012 , 2/1/2012
Days Count: 1 //ok
Why?
Knowing that JS months are 0-based is very important to this. Your code is parsing the date 31/1/2012 into 31 February 2012, which is technically an invalid date but is interpreted as 2 March 2012 (the 2nd because 2012 is a leap year). What you need to do is subtract 1 from the parts[1] value before passing it to the Date constructor.
You are getting -1 days between 31/1/2012 and 1/2/2012 because those dates are interpreted as 31 February 2012 (2 March 2012) and 1 March 2012. When you subtract those dates, you get a -1-day difference.
You are getting 0 days between 31/3/2012 and 1/4/2012 because those dates are interpreted as 31 April 2012 (1 May 2012) and 1 May 2012, which are the same date, resulting in a 0-day difference.
You are getting 1 day between 1/1/2012 and 2/1/2012 because those dates are interpreted as 1 February 2012 and 2 February 2012, resulting in a 1-day difference.
Related
Does anyone have any thoughts on why this might have happened? Today, I found that a date conversion function I wrote started returning the wrong month. For instance, when attempting to convert "2017-06-02" to "Fri Jun 02 2017 00:00:00 GMT-0600 (Mountain Daylight Time)", it actually returned July instead of June. When I re-arranged the order of some of the statements in the function, the correct date was finally returned. This code has been in place for many months, so this spontaneous...maybe due to the current month changing, as today is 5/31/17? This might only be broken when ran on todays date, or end-of-month? (I'm sure there's a better way to convert dates, but here's the code in question anyway):
<!doctype html>
<body onload="testDate()">
<div id="resultbad"></div>
<div id="resultgood"></div>
<script>
function testDate() {
document.getElementById("resultbad").innerHTML = "Bad Result: Converting 2017-06-02 returns: " + badDate("2017-06-02");
//returns: Bad Result: Converting 2017-06-02 returns: Sun Jul 02 2017 00:00:00 GMT-0600 (Mountain Daylight Time)
document.getElementById("resultgood").innerHTML = "Good Result: Converting 2017-06-02 returns: " + goodDate("2017-06-02");
//returns: Good Result: Converting 2017-06-02 returns: Fri Jun 02 2017 00:00:00 GMT-0600 (Mountain Daylight Time)
}
function badDate(d) {
var td = d.split('-');
var nd = new Date();
//originally ordered: Year, Month then Day
nd.setFullYear(td[0]);
nd.setMonth(td[1] - 1);
nd.setDate(td[2]);
//set time
nd.setHours(0);
nd.setMinutes(0,0,0);
return nd;
}
function goodDate(d) {
var td = d.split('-');
var nd = new Date();
//new order: Day, Month then Year
nd.setDate(td[2]);
nd.setMonth(td[1] - 1);
nd.setFullYear(td[0]);
//set time
nd.setHours(0);
nd.setMinutes(0,0,0);
return nd;
}
</script>
</body>
This code overrides the date elements based on today's date. So, if you are running the code on the 31st day of the month, the "bad" version of this code will overwrite the month first, and if that month only has 30 days, it will roll over to the next month.
Basically, after setMonth but before setDate, you are trying to create the date June 31, 2017, which JS will convert for you into July 1, 2017.
Instead, do this as one call:
new Date(td[0], td[1]-1, td[2], 0, 0, 0, 0)
You figured out the problem fairly well - it has to do with today being the 31st of the month.
The issue is that new Date() creates a date object with the fields filled in. You're then changing those fields one by one.
So right now we can think of it as having a pseudo-structure like this, remembering that month is 0-based:
{
year: 2017
month: 4
date: 31
}
when you call setMonth(), you're just changing the month field, so you'd think for June it would set it to
{
year: 2017
month: 5
date: 31
}
but it knows there aren't 31 days in June. The 31st "day" of June would be the 1st of July. So it helps you out and adjusts it to
{
year: 2017
month: 6
date: 1
}
You're then setting the date to the 2nd with setDate():
{
year: 2017
month: 6
date: 2
}
In the function that works, you're setting the date before the month, so you're not having it recompute what the day is in case you've specified a date that is larger than the number of days in the month.
This question already has answers here:
`date.setMonth` causes the month to be set too high if `date` is at the end of the month
(8 answers)
Closed 1 year ago.
I am facing very strange behavior of setMonth function of JS.
On click of a image i am showing a calendar, having all days of current month and some next and previous month's date (in Grey color).
Whenever current date selected is 31st date of any month. suppose 31 may 2017 I select i will set in a textfield. If I click on 2 june 2017 rather then setting textfield to 2 june 2017 it sets 2 July 2017 ?
please suggest whats wrong is going here.
Code snippet used as follows
var tempDate = new Date(current); //Suppose : current --> Wed May 31 16:09:00 UTC+0530 2017
var dayOfMonth = parseInt(element.text(), 10); //Suppose : element.text() --> 2
tempDate.setMonth(tempDate.getMonth() + (dayOfMonth > 15 ? -1 : 1)); //tempDate.getMonth() + (dayOfMonth > 15 ? -1 : 1) returns 10
tempDate.setDate(dayOfMonth);
//Output Expected : 02 June 2017 but it gives 02 July 2017
In javascript date object, Month is starting form 0, so if you want to generate any month, then do accordingly. Refer this url for Date: MDN Date
As your code , I think you made mistake at
dayOfMonth > 15 ? 1 : -1
var dayOfMonth = 13;
alert((dayOfMonth > 15 ? 1 : -1))
var tempDate = new Date();
tempDate.setMonth(tempDate.getMonth() + (dayOfMonth > 15 ? 1 : -1));
tempDate.setDate(dayOfMonth);
alert(tempDate)
I think that is for the standard behavior of the operation when the month does not have the day (31) the operation take the next month that have that day
>var date = new Date('2018/10/31');
undefined
>date
Wed Oct 31 2018 00:00:00 GMT-0600 (hora estándar central)
>date.setMonth(date.getMonth() + 1);
1543644000000
>date
Sat Dec 01 2018 00:00:00 GMT-0600 (hora estándar central)
I have this code:
var nextDate = new Date("2016 01 31");
nextDate.setMonth(nextDate.getMonth() + 1);
I'm expecting the result to be Feb 28 2016, but it shows Mar 02 2016 instead.
Why? Is there any solution for it?
There is only 29 day in February, therefore, February 31 February will translate to Mars 2.
You need to update the days in your date object to the last day of that month. You can get the last day of the month by specifying a function that sets the date to 0:
function daysInMonth(month,year) {
return new Date(year, month, 0).getDate();
}
This is because February has 29 days, and when you set new month from January, which has 31 day, to February then the difference of the days are transferred to another month.
Easy way to do it is just create new Date instance.
You might need to implement some logic to get corresponding dates right
Possible work around with a helper function: after setMonth, check if the results doesn't contain a month equal to the expected month and if so, use setDate(0), which sets the date to last day of the previous month. e.g.
Date.prototype.addMonths = function(months){
var m = this.getMonth() + (months || 1);
this.setMonth(m);
if(this.getMonth() !== (m % 11)) //11: month is 0 based
this.setDate(0);
}
var nextDate = new Date("2016 01 31");
nextDate.addMonths(1);
document.writeln(nextDate);
months || 1 only is meant to have a default value if no month was submitted. m % 11 is needed in case of year transitions. 11 and not 12 because javascripts month (and thus getMonth) is 0 based.
I am having some issues with the Moment JS NPM. I have a date in the past set to Jan 31st for testing. It is returning as 1 from today's date. Take a look at my code and screenshots below:
var tz = -5,
thisYear = moment().utc(tz).year(),
// plus one because Moment starts month at 0
thisMonth = moment().utc(tz).month() + 1,
today = moment().utc(tz).date(),
thisHour = moment().utc(tz).hour(),
start = moment([2015, 1, 31, 15]),
now = moment([thisYear, thisMonth, today, thisHour]),
daysPast = now.diff(start, 'days');
console.log(thisYear, thisMonth, today, thisHour);
console.log(2015, 1, 31, 15);
console.log(daysPast);
This is what is getting returned in the console:
When I change the date to the first of February, it returns correctly:
Anyone have any ideas why Moment is returning incorrectly with the past month?
In js months start with 0. So 2015, 1, 31 == 31st of February
Which is interpreted as March, 3rd which is exactly one day behind March, 4th
If you want to manipulate with dates - use the corresponding momentjs methods instead: http://momentjs.com/docs/#/manipulating/
Just to clarify zerkms answer, where you have:
thisMonth = moment().utc(tz).month() + 1,
you are setting thisMonth to 2 (if run in Feburary), then when you do:
start = moment([2015, 1, 31, 15]),
you are creating a date for 31 February, which doesn't exist so a date for 3 March is created.
Then when you do:
now = moment([thisYear, thisMonth, today, thisHour]),
remember that you incremented thisMonth by one, so it creates a date for 4 March, not 4 February (i.e. a month number of 2 creates a date for March).
The difference between 3 March and 4 March is one day.
Why do these two dates are differents :
var date1 = new Date();
date1.setFullYear(2012); // year (four digits)
date1.setMonth(10); // month (from 0-11)
date1.setDate(1); // day of the month (from 1-31)
var date2 = new Date(2012, 10, 1, 0, 0, 0, 0);
Result :
Date 1 : Sat Dec 01 2012 14:56:16 GMT+0100
Date 2 : Thu Nov 01 2012 00:00:00 GMT+0100
whereas these two dates are equals :
var date3 = new Date();
date3.setFullYear(2012); // year (four digits)
date3.setMonth(9); // month (from 0-11)
date3.setDate(1); // day of the month (from 1-31)
var date4 = new Date(2012, 9, 1, 0, 0, 0, 0);
Result :
Date 3 : Mon Oct 01 2012 14:56:16 GMT+0200
Date 4 : Mon Oct 01 2012 00:00:00 GMT+0200
Another question is why do date1.setMonth(10) gives a date in December (should be November).
Finally got it. new Date() sets the date to the current date and time. In other words, October 31st (at the time of this writing).
When you then try to set the month to November, what's it to do? November only has 30 days... so it wraps it round to December.
If you change the order so that you set the day-of-month before the month, it works:
var date1 = new Date();
date1.setFullYear(2012); // year (four digits)
date1.setDate(1); // day of the month (from 1-31)
date1.setMonth(10); // month (from 0-11)
Or as implied by jbabey's answer:
var date1 = new Date();
date1.setFullYear(2012); // year (four digits)
date1.setMonth(10, 1); // month (from 0-11) and day (1-31)
The documentation isn't terribly clear, but it's at least suggestive:
If a parameter you specify is outside of the expected range, setMonth attempts to update the date information in the Date object accordingly. For example, if you use 15 for monthValue, the year will be incremented by 1 (year + 1), and 3 will be used for month.
("Accordingly" is far from precise, but it means the implementation is at least arguably correct...)
setMonth accepts a second parameter:
If you do not specify the dayValue parameter, the value returned from the getDate method is used.
When you set the month to 10 (November), it grabs the current day value (31) and sets that as the day. Since there are only 30 days in November, it rolls you over to December 1st.
You're creating a var containing the current date (new Date()) and then you're changing some of it's keys (year, month and day).
On the other hand new Date(2012, 10, 1, 0, 0, 0, 0) means "create a date object with those exact values".
And that's why your date objects aren't equal.