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 3 years ago.
I found it when i set month
Today is 08-31
If i increase month, then today will be 09-30
But it return 10-01
If i decrease month, then it returns 09-01
date = new Date()
console.log( date )
// Fri Aug 31 2018 11: 28: 47 GMT + 0900(한국 표준시)
console.log( date.getMonth() )
// 7
console.log( date.setMonth(date.getMonth() + 1) )
// 1538360927857
console.log( date.toISOString() )
// "2018-10-01T02:28:47.857Z"
console.log( date.setMonth(date.getMonth() - 1) )
//1535768927857
console.log( date.toISOString() )
//"2018-09-01T02:28:47.857Z"
Can anyone explain me why it happens?
When the current date is 08-31, it is not entirely clear what is should mean to set the month to 9 because 09-31 is an invalid date.
That's why at some time someone had to define what setMonth should do in such situations. It seems that the defined behavior differs from the one you expect (you expected the date to become 09-30).
MDN (for setMonth) has some information about this:
The current day of month will have an impact on the behaviour of this method. Conceptually it will add the number of days given by the current day of the month to the 1st day of the new month specified as the parameter, to return the new date.
It also refers to the actual specification which gives the exact algorithm which is used to calculate the result.
The reasons for the specification being as it is now are manifold, usually simplicity of the algorithm as well as the behavior on non-edge-cases are important factors.
A good explanation can be find on MDN
The current day of month will have an impact on the behaviour of this method. Conceptually it will add the number of days given by the current day of the month to the 1st day of the new month specified as the parameter, to return the new date. For example, if the current value is 31st August 2016, calling setMonth with a value of 1 will return 2nd March 2016. This is because in 2016 February had 29 days.
In your case setting setMonth(getMonth()+1) will return October 1st because September has only 30 days. Then, when you tries to decrease month to one you back to September 1st.
Javascript Date object - monthIndex is Zero (0) based, just like arrays(zero indexed).
MDN
Related
This question already has answers here:
unexpected javascript date behavior
(3 answers)
Closed 6 years ago.
I am adding days in today date and getting timestamps in milliseconds.
for(i=1;i<=shippingDays;i++){
var result = new Date();
result.setTime( result.getTime() + i * 86400000 );
console.log(result);
console.log(result.getMonth()+'-'+result.getDate()+'-'+result.getFullYear());
newDate = new Date(result.getMonth()+'-'+result.getDate()+'-'+result.getFullYear());
console.log(newDate);
};
The first console returns Thu Apr 07 2016 18:34:33 GMT+0500 (PKT) but later on result.getMonth() always returns previous month value. So the second console always returns 3-7-2016 and third console always returns Mon Mar 07 2016 00:00:00 GMT+0500 (PKT).
My ultimate goal is to get milliseconds of next days from 00:00:00. Like today is 04-06-2016. I want to get milliseconds timestamp of next few days. And time stamp should be calculated from start of that date, i.e, 00:00:00
Can any body let me know what am I doing wrong?
Months from Data.getMonth are zero based (so January is 0, feb is 1, etc).
So if you want to use the month value to make a new date just add one.
getMonth is zero based so 0=January, 1=February, 3=April etc. So the output of console.log is correct
You need to add 1 to the getMonth() function.
Example:
console.log((result.getMonth() + 1)+'-'+result.getDate()+'-'+result.getFullYear());
Will return the correct month / date. It's because the getMonth function returns a value of 0 - 11 (0 for January and 11 for December)
http://www.w3schools.com/jsref/jsref_getmonth.asp
Hi I have following code that is suppose to extract day,month and year part separately.
$scope.$watch('inlineDatepicker.date', function() {
alert('hey, myVar has changed!' +$scope.inlineDatepicker.date);
alert($scope.inlineDatepicker.date.getDay());
alert($scope.inlineDatepicker.date.getMonth());
alert($scope.inlineDatepicker.date.getUTCFullYear());
});
Problem with the code is I can extract year correctly but day and month do not extract correctly. I tried as well
alert($scope.inlineDatepicker.date.getUTCDady());
alert($scope.inlineDatepicker.date.getUTCMonth())
Still wrong day and month.
Please let me know how I can change it to get correct month and day values. Thanks. Here is the plunker for it.
http://plnkr.co/edit/8v75gsz8ODUrTfu8S0sh?p=preview
To get day of month, use getUTCDate()
Month is zero based, so 0 means January, 11 December
Sample
$scope.inlineDatepicker.date.getUTCDate(); //prints day of month
$scope.inlineDatepicker.date.getUTCMonth() + 1; //prints month, 0 based, so add 1
$scope.inlineDatepicker.date.getUTCFullYear(); //prints 2015
Get day returns the day of the week. Use getDate() to return the day of the month. If you do getMonth(), january is 0 and december is 11.
You can see the reference documents here: http://www.w3schools.com/jsref/jsref_obj_date.asp
In short: Can someone please explain to me what is going on with this function:
function daysInMonth(month, year){
return new Date(year, month, 0).getDate();
}
alert(daysInMonth(1, 2013));
What I'm really interested in understanding is, why there is a "0" after month? I just can't seem to get my head round it, I've tried to omit it, and also replacing it with "day" but both with different outcome. This function only seems to work when the "0" is passed in the Object.
Also another tricky part when calling the function, passing "0" and "1" to represent January both return the same number of days where as passing "12" and "11" to represent December return different number of days (12 returns 31 (December) and 11 returns 30 (November)).
JavaScript Date objects "fix" date settings that make no sense. Requesting a Date instance for day 0 in a month instead gives you a Date for the last day in the previous month.
Months are numbered from zero, but that function is written as if months were numbered from 1. You therefore get the same answer when you pass 0 or 1 as the month number because you're getting the number of days in the months December and January, and both of those months have 31 days.
Personally I would not have written that function that way; since it's necessary to keep in mind that months are numbered from zero in JavaScript, I'd have written the function like this:
function daysInMonth(month, year){
return new Date(year, month + 1, 0).getDate();
}
Then to get the number of days in January, you'd call it like this:
var janDays = daysInMonth(0, 2015);
The key is the JS Date object constructor. This function takes multiple parameters, but three are required: year, month, day. The day param is the day of the month, with the first day of the month being numbered as 1. The code above is really tricky. According to JS reference passing 0 for date, actually results in the last day of the PREVIOUS month. So this actually explains both the day question you have as well as the month question at the end.
See for more info: http://www.w3schools.com/jsref/jsref_setdate.asp
Passing 0 and 1 do not actually both represent January -- 1 represents january and 0 represents december of the previous year, which also has 31 days! (try running this function the year AFTER a year with a leap day, they wont have the same number of days).
Edit: Example
To get a better grasp of what is actually happening, try running this function:
function check() {
console.log(new Date(2015, 0, 0).toISOString()); // 2014-12-31T08:00:00.000Z
console.log(new Date(2015, 1, 0).toISOString()); // 2015-01-31T08:00:00.000Z
console.log(new Date(2015, 11, 0).toISOString()); // 2015-11-30T08:00:00.000Z
console.log(new Date(2015, 12, 0).toISOString()); // 2015-12-31T08:00:00.000Z
}
I am having trouble understanding why a Date in Javascript come out wrong. For example...
$scope.campaign.date_start = new Date(19/11/2014);
Wed Nov 19 2014 00:00:00 GMT+0000 (GMT) - correct
$scope.campaign.date_start.getDay() = 19 - correct
So far so good, however getting the Month and the year gives me incorrect values....
$scope.campaign.date_start.getMonth() = 10 - incorrect should be 11
$scope.campaign.date_start.getYear() = 114 incorrect should be 2014
What I'm I going wrong here?
JavaScript getMonth() will always return actual month-1. For the year, you will need to use getFullYear() to get the 4 digit year
getMonth is 0 based, so you need to +1 to get the number of the current month.
getYear is deprecated, and may break at some point in future, it (generally) returns the number of years since 1900. The correct method to use is getFullYear
Date.getMonth() is 0-base (January is month 0).
Date.getYear() is deprecated and is years since 1900 (hence 114).
http://www.w3schools.com/jsref/jsref_obj_date.asp
getMonth() is zero-based. So you will need getMonth()+1
getYear() was not Y2K compliant, so a new function getFullYear() was created to return 4-digit years.
I have an HTML form where I am allowing users to enter a date to print out a report. However, if that date is within 3 days of the current date, I have it set to tell the user that they must wait 3 days. For some reason the code works when I enter something like "09/30/2012" but when I enter "10/01/2012", the error check skips. It seems at though, if it's a double digit month (10, 11, and 12), it complete skips the error check. Please let me know if you have any ideas. Thanks
JS Code:
var date = myForm.SC_date.value;
var d = new Date(date);
var varBegin = (d.getMonth()+1) + "-" + (d.getDate()-3) + "-" + d.getFullYear()
re = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
if (myForm.SC_date.value == "")
window.alert("Please enter the requested date of variance. NOTE: Date must be 3 days prior to today's date.")
//Here is where I am having issues
/*else if(new Date(date) > new Date(varBegin))
window.alert("Invalid date. You must wait at least 3 days before you can request a report.")*/
else if(!myForm.SC_date.value.match(re))
window.alert("Invalid date. Please enter the date as follows: mm/dd/yyyy.")
HTML Code:
<td>Date of Variance </td>
<td colspan="2"><input name="SC_date:*" id="SC_date" type="text" tabindex="06">
</textarea><b><span class="style3">*</span> </b><span class="style2">(mm/dd/yyyy)</span>
</td>
I don't think you want to construct your "3 days ago" date by manipulating a string. I.e., this snippet here:
var varBegin = (d.getMonth()+1) + "-" + (d.getDate()-3) + "-" + d.getFullYear()
First, I'm not sure why you're using hyphens as delimiters here, when you are using forward-slashes as delimiters in your input field?
In any case, that's not a reliable way to construct the date. When you feed a string into the constructor of a Date object, you are effectively calling Date.parse(). That behaves differently on different browsers.
Check this out:
> new Date('1-1-2012');
Sun Jan 01 2012 00:00:00 GMT-0800 (PST)
> new Date('01-01-2012');
Sun Jan 01 2012 00:00:00 GMT-0800 (PST)
> new Date('2012-1-1');
Sun Jan 01 2012 00:00:00 GMT-0800 (PST)
Looks pretty good, right? But that's on Chrome.
Now check out what happens in an up-to-date version of Firefox, with the exact same calls:
> new Date('1-1-2012');
Date {Invalid Date}
> new Date('01-01-2012');
Date {Invalid Date}
> new Date('2012-1-1');
Date {Invalid Date}
> new Date('2012-01-01');
Date {Sat Dec 31 2011 16:00:00 GMT-0800 (PST)}
Furthermore, look at this behavior, in both browsers:
> new Date('2012-01-01');
Sat Dec 31 2011 16:00:00 GMT-0800 (PST)
Simply prepending zeroes to the month and date digits causes a time warp! You have to set the time and a timezone (for me, PST) to make that go away:
> new Date('2012-01-01T00:00:00-08:00')
Sun Jan 01 2012 00:00:00 GMT-0800 (PST)
Basically, dealing with date string parsing is a headache. You don't want to have to digest and account for specs like this, this, and this.
So, here's a better alternative -- pass the year, month, and date values (in that order) to the constructor of the Date object. That will reliably create the date for you, so your comparisons are valid.
Like this, for your specific example:
var WARNING_PERIOD_IN_DAYS = 3;
// Extract month, day, year from form input, 'trimming' whitespace.
var re = /^\s*(\d{1,2})\/(\d{1,2})\/(\d{4})\s*$/;
var match = re.exec(inputVal); // from "myForm.SC_date.value".
if (match) {
var month = parseInt(match[1]) - 1; // Zero-indexed months.
var date = parseInt(match[2]);
var year = parseInt(match[3]);
var inputDate = new Date(year, month, date);
var currentDate = new Date();
var threeDaysAgo = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDay() - WARNING_PERIOD_IN_DAYS);
console.log((inputDate > threeDaysAgo) ? 'Within warning period' : 'No warning needed');
}
Speaking of specs, there's one cool thing to note here, which is that in JavaScript, you can "wrap" the date value (it can be too large, or negative), and the resulting Date will still be valid and correct. Here's why:
From the ECMAScript 262 spec, here's what happens when you call setDate():
**15.9.5.36 Date.prototype.setDate (date)**
1. Let t be the result of LocalTime(this time value).
2. Let dt be ToNumber(date).
3. Let newDate be MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t)).
4. Let u be TimeClip(UTC(newDate)).
5. Set the [[PrimitiveValue]] internal property of this Date object to u.
6. Return u.
This is the key bit: MakeDay(YearFromTime(t), MonthFromTime(t), dt)
MakeDay gets the year and the month from the current time value of the Date object (in milliseconds of epoch time), and does this:
**15.9.1.12 MakeDay (year, month, date)**
The operator MakeDay calculates a number of days from its three arguments, which must be ECMAScript Number values. This operator functions as follows:
1. If year is not finite or month is not finite or date is not finite, return NaN.
2. Let y be ToInteger(year).
3. Let m be ToInteger(month).
4. Let dt be ToInteger(date).
5. Let ym be y + floor(m /12).
6. Let mn be m modulo 12.
7. Find a value t such that YearFromTime(t) == ym and MonthFromTime(t) == mn and DateFromTime(t) == 1;
but if this is not possible (because some argument is out of range), return NaN.
8. Return Day(t) + dt - 1.
This looks rather involved, but basically it's:
The floor, modulo, and date==1 bits handle month rollovers (months that are negative or greater than 12).
The resulting instant in epoch time is converted to a number of days.
Your date value is added to that number of days. If your date value is negative, that's fine, it will just be subtracted.
The result is passed back to setDate().
setDate calls MakeDate(), which converts the number of days plus the intra-day time into milliseconds in epoch time.
The Date object's internal time is set to this new epoch time.
That's why you can do stuff like this (comments taken from the MakeDay() function in the V8 JS engine project):
// MakeDay(2007, -4, 20) --> MakeDay(2006, 8, 20)
// MakeDay(2007, -33, 1) --> MakeDay(2004, 3, 1)
// MakeDay(2007, 14, -50) --> MakeDay(2007, 8, 11)
Ok, so that was almost certainly too much detail for this particular problem... but I just wanted to make clear what's really going on behind the scenes. Thanks for your patience.
And... just one last thing...
You have a random </textarea> hanging out in that HTML snippet. If there is an opening <textarea> somewhere before it, then it's incorrectly enclosing some of your other elements. If there is no opening <textarea>, then delete it.
If you don't care about the time of the day, I recommend you do the following:
var dUser = new Date(date); //just like you did before
var dVarBegin = new Date("10/05/2012"); //here you do whatever is the date you are setting.
var diff = dVarBegin.getTime() - dUser.getTime();
//now diff is the difference in milliseconds!
I don't fully understand your requirements in relation to the 3 days. However, if what you needed was to compare dates, now you can! I hope this works for you. If you need something more, please ellaborate a little bit on the 3 days thing.
Use a library that lets you control the date formats accepted, e.g. Globalize.js or Date.js. Then define the exact test you wish to carry out especially whether time of the day is significant and whether the test should be relative to current time in user’s system (which is what you get with new Date() without arguments). You can then e.g. calculate a time difference as outlined by #Mamsaac and convert milliseconds to days with simple arithmetic.
It is illogical to use Date() and then, without checking the result, start doing pattern matching on the input. Moreover, Date() is by definition system-dependent and should seldom be used. There is no guarantee that it will accept a format like mm/dd/yyyy at all.