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
}
Related
I have an app where a user can select two dates (a from date and a to date) and the time between the dates should not exceed 4 months. A user can select the day, month and year for each date. Is there some kind of logic I could use to achieve this, so that an error is returned if the date range is over 4 months. Each input as an integer. For example, a start date of March 31st 2019 would be: from_date_day = 31 from_date_month = 3 and from_date_year = 2019
For example, I something like this would kind of work:
((Math.abs($('#to_date_month').val() - $('#from_date_month').val()) > 2) && $('#from_date_day').val() <= $('#to_date_day').val()
return "error"
The problem with this code is that it doesn't work when the dates straddle two different years. I'm using coffeescript, but a solution in jquery or js would also work.
I'd recommend creating two Javascript Date objects of those two dates. This can be done by feeding the year, the month and finally the day to the constructor of the Date object.
e.g.
var startDate = new Date(2019, 1, 16); // January the 16th
var endDate = new Date(2019, 3, 30); // March the 30th
Using the .getTime() function of the Date object you can get the number of milliseconds passed since 1.1.1970. If you calculate the difference between those two numbers, wrap it inside Math.abs() and divide that number by 1000, 60, 60 and finally 24 you get the number of days. If this number is bigger than ~120, the range is more than four months.
console.log(Math.abs(startDate.getTime() - endDate.getTime()) / 1000/60/60/24);
In your use case the Date object could be set like this:
var startDate = new Date(parseInt($('#from_date_year').val()), parseInt($('#from_date_month').val()), parseInt($('#from_date_day').val()));
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
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
I want to count down the days until a particular event using momentjs but I'm getting an unexpected result.
With today's date being 17th April, and the event date being 14th May, I want the resulting number of days to be 27, however my code gives me a result of 57. What's wrong?
function daysRemaining() {
var eventdate = moment([2015, 5, 14]);
var todaysdate = moment();
return eventdate.diff(todaysdate, 'days');
}
alert(daysRemaining());
When creating a moment object using an array, you have to take note that months, hours, minutes, seconds, and milliseconds are all zero indexed. Years and days of the month are 1 indexed. This is to mirror the native Date parameters.
Reference
So either change the month to 4 to reflect May or parse the date as an ISO 8601 string
function daysRemaining() {
var eventdate = moment("2015-05-14");
var todaysdate = moment();
return eventdate.diff(todaysdate, 'days');
}
alert(daysRemaining());
Just to add for anyone else that comes across this - there's actually a helper that does the phrasing etc for you:
https://momentjs.com/docs/#/displaying/to/
/* Retrieve a string describing the time from now to the provided date */
daysUntil: function(dateToCheckAgainst){
return new moment().to(moment(dateToCheckAgainst));
}
// Sample outputs
"in three months"
"in two months"
"in 25 days"
That's because months are zero indexed. So 5 is actually June ;)
Given a start date, and a number of days, I need to display the end date = start date + number of days.
So I did something like this:
var endDate=new Date(startDate.getTime()+ONE_DAY);
Everything works fine, except that for 25 and 26 October gives one day less.
Ex.:
2014-01-01 + 2 days = 2014-01-03
2014-10-25 + 2 days = 2014-10-26 (here is the case I need to treat).
This difference appear because of the clock going back 1 hour. Practically 2014-10-27 00:00:00 becomes 2014-10-26 23:00:00.
A simple solution would be to compute this at another hour (example 3 AM). But I want to just display a note when this happens.
For example, if user inputs 2014-10-25, I show a popup saying [something].
Now here is the real problem... I can't seem to find any algorithm that says when clocks goes back in year X.
Example... in 2014 the day is 26 October. In 2016 is 30 October (https://www.gov.uk/when-do-the-clocks-change). Why? This date looks random to be, but I don't think it is. So... when does clock go back/forward?
EDIT: All answers/comments are helpful related to how to fix the problem. But... I already passed that stage. Now I only have an itch about "how on earth are the days when clock is changed computed?".
To find the difference between two dates in whole days, create Date objects, subtract one from the other, then divide by the milliseconds in one day and round. The remainder will only be out by 1 hour for daylight saving so will round to the right value.
You may also need a small function to convert strings to Dates:
// Return Date given ISO date as yyyy-mm-dd
function parseISODate(ds) {
var d = ds.split(/\D/);
return new Date(d[0], --d[1], d[2]);
}
Get the difference in days:
function dateDiff(d0, d1) {
return Math.round((d1 - d0)/8.64e7);
}
// 297
console.log(dateDiff(parseISODate('2014-01-01'), parseISODate('2014-10-25')));
If you want to add days to a date, do something like:
// Add 2 days to 2014-10-25
var d = new Date(2014, 9, 25);
d.setDate(d.getDate() + 2);
console.log(d); // 2014-10-27
The built–in Date object takes account of daylight saving (thought there are bugs in some browsers).
I prefer adding days this way:
var startDate = //someDate;
var endDate = new Date(startDate.getFullYear(),
startDate.getMonth(),
startDate.getDate()+1);
This way you don't have to worry about the days in the calendar.
This code add 1 day, if you want to add more, change the startDate.getDate()+1 for startDate.getDate()+NUMBER_OF_DAYS it works fine even if you are on the last day of month i.e. October 31th.
But maybe you can use #RobG solution which is more elegant than mine