How would I work out the difference for two Date() objects in JavaScript, while only return the number of months in the difference?
Any help would be great :)
The definition of "the number of months in the difference" is subject to a lot of interpretation. :-)
You can get the year, month, and day of month from a JavaScript date object. Depending on what information you're looking for, you can use those to figure out how many months are between two points in time.
For instance, off-the-cuff:
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth();
months += d2.getMonth();
return months <= 0 ? 0 : months;
}
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth();
months += d2.getMonth();
return months <= 0 ? 0 : months;
}
function test(d1, d2) {
var diff = monthDiff(d1, d2);
console.log(
d1.toISOString().substring(0, 10),
"to",
d2.toISOString().substring(0, 10),
":",
diff
);
}
test(
new Date(2008, 10, 4), // November 4th, 2008
new Date(2010, 2, 12) // March 12th, 2010
);
// Result: 16
test(
new Date(2010, 0, 1), // January 1st, 2010
new Date(2010, 2, 12) // March 12th, 2010
);
// Result: 2
test(
new Date(2010, 1, 1), // February 1st, 2010
new Date(2010, 2, 12) // March 12th, 2010
);
// Result: 1
(Note that month values in JavaScript start with 0 = January.)
Including fractional months in the above is much more complicated, because three days in a typical February is a larger fraction of that month (~10.714%) than three days in August (~9.677%), and of course even February is a moving target depending on whether it's a leap year.
There are also some date and time libraries available for JavaScript that probably make this sort of thing easier.
Note: There used to be a + 1 in the above, here:
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
// −−−−−−−−−−−−−−−−−−−−^^^^
months += d2.getMonth();
That's because originally I said:
...this finds out how many full months lie between two dates, not counting partial months (e.g., excluding the month each date is in).
I've removed it for two reasons:
Not counting partial months turns out not to be what many (most?) people coming to the answer want, so I thought I should separate them out.
It didn't always work even by that definition. :-D (Sorry.)
If you do not consider the day of the month, this is by far the simpler solution
function monthDiff(dateFrom, dateTo) {
return dateTo.getMonth() - dateFrom.getMonth() +
(12 * (dateTo.getFullYear() - dateFrom.getFullYear()))
}
//examples
console.log(monthDiff(new Date(2000, 01), new Date(2000, 02))) // 1
console.log(monthDiff(new Date(1999, 02), new Date(2000, 02))) // 12 full year
console.log(monthDiff(new Date(2009, 11), new Date(2010, 0))) // 1
Be aware that month index is 0-based. This means that January = 0 and December = 11.
Here's a function that accurately provides the number of months between 2 dates.
The default behavior only counts whole months, e.g. 3 months and 1 day will result in a difference of 3 months. You can prevent this by setting the roundUpFractionalMonths param as true, so a 3 month and 1 day difference will be returned as 4 months.
The accepted answer above (T.J. Crowder's answer) isn't accurate, it returns wrong values sometimes.
For example, monthDiff(new Date('Jul 01, 2015'), new Date('Aug 05, 2015')) returns 0 which is obviously wrong. The correct difference is either 1 whole month or 2 months rounded-up.
Here's the function I wrote:
function getMonthsBetween(date1,date2,roundUpFractionalMonths)
{
//Months will be calculated between start and end dates.
//Make sure start date is less than end date.
//But remember if the difference should be negative.
var startDate=date1;
var endDate=date2;
var inverse=false;
if(date1>date2)
{
startDate=date2;
endDate=date1;
inverse=true;
}
//Calculate the differences between the start and end dates
var yearsDifference=endDate.getFullYear()-startDate.getFullYear();
var monthsDifference=endDate.getMonth()-startDate.getMonth();
var daysDifference=endDate.getDate()-startDate.getDate();
var monthCorrection=0;
//If roundUpFractionalMonths is true, check if an extra month needs to be added from rounding up.
//The difference is done by ceiling (round up), e.g. 3 months and 1 day will be 4 months.
if(roundUpFractionalMonths===true && daysDifference>0)
{
monthCorrection=1;
}
//If the day difference between the 2 months is negative, the last month is not a whole month.
else if(roundUpFractionalMonths!==true && daysDifference<0)
{
monthCorrection=-1;
}
return (inverse?-1:1)*(yearsDifference*12+monthsDifference+monthCorrection);
};
Sometimes you may want to get just the quantity of the months between two dates totally ignoring the day part. So for instance, if you had two dates- 2013/06/21 and 2013/10/18- and you only cared about the 2013/06 and 2013/10 parts, here are the scenarios and possible solutions:
var date1=new Date(2013,5,21);//Remember, months are 0 based in JS
var date2=new Date(2013,9,18);
var year1=date1.getFullYear();
var year2=date2.getFullYear();
var month1=date1.getMonth();
var month2=date2.getMonth();
if(month1===0){ //Have to take into account
month1++;
month2++;
}
var numberOfMonths;
1.If you want just the number of the months between the two dates excluding both month1 and month2
numberOfMonths = (year2 - year1) * 12 + (month2 - month1) - 1;
2.If you want to include either of the months
numberOfMonths = (year2 - year1) * 12 + (month2 - month1);
3.If you want to include both of the months
numberOfMonths = (year2 - year1) * 12 + (month2 - month1) + 1;
If you need to count full months, regardless of the month being 28, 29, 30 or 31 days. Below should work.
var months = to.getMonth() - from.getMonth()
+ (12 * (to.getFullYear() - from.getFullYear()));
if(to.getDate() < from.getDate()){
months--;
}
return months;
This is an extended version of the answer https://stackoverflow.com/a/4312956/1987208 but fixes the case where it calculates 1 month for the case from 31st of January to 1st of February (1day).
This will cover the following;
1st Jan to 31st Jan ---> 30days ---> will result in 0 (logical since it is not a full month)
1st Feb to 1st Mar ---> 28 or 29 days ---> will result in 1 (logical since it is a full month)
15th Feb to 15th Mar ---> 28 or 29 days ---> will result in 1 (logical since a month passed)
31st Jan to 1st Feb ---> 1 day ---> will result in 0 (obvious but the mentioned answer in the post results in 1 month)
Difference in Months between two dates in JavaScript:
start_date = new Date(year, month, day); //Create start date object by passing appropiate argument
end_date = new Date(new Date(year, month, day)
total months between start_date and end_date :
total_months = (end_date.getFullYear() - start_date.getFullYear())*12 + (end_date.getMonth() - start_date.getMonth())
I know this is really late, but posting it anyway just in case it helps others. Here is a function I came up with that seems to do a good job of counting differences in months between two dates. It is admittedly a great deal raunchier than Mr.Crowder's, but provides more accurate results by stepping through the date object. It is in AS3 but you should just be able to drop the strong typing and you'll have JS. Feel free to make it nicer looking anyone out there!
function countMonths ( startDate:Date, endDate:Date ):int
{
var stepDate:Date = new Date;
stepDate.time = startDate.time;
var monthCount:int;
while( stepDate.time <= endDate.time ) {
stepDate.month += 1;
monthCount += 1;
}
if ( stepDate != endDate ) {
monthCount -= 1;
}
return monthCount;
}
You could also consider this solution, this function returns the month difference in integer or number
Passing the start date as the first or last param, is fault tolerant. Meaning, the function would still return the same value.
const diffInMonths = (end, start) => {
var timeDiff = Math.abs(end.getTime() - start.getTime());
return Math.round(timeDiff / (2e3 * 3600 * 365.25));
}
const result = diffInMonths(new Date(2015, 3, 28), new Date(2010, 1, 25));
// shows month difference as integer/number
console.log(result);
To expand on #T.J.'s answer, if you're looking for simple months, rather than full calendar months, you could just check if d2's date is greater than or equal to than d1's. That is, if d2 is later in its month than d1 is in its month, then there is 1 more month. So you should be able to just do this:
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth();
// edit: increment months if d2 comes later in its month than d1 in its month
if (d2.getDate() >= d1.getDate())
months++
// end edit
return months <= 0 ? 0 : months;
}
monthDiff(
new Date(2008, 10, 4), // November 4th, 2008
new Date(2010, 2, 12) // March 12th, 2010
);
// Result: 16; 4 Nov – 4 Dec '08, 4 Dec '08 – 4 Dec '09, 4 Dec '09 – 4 March '10
This doesn't totally account for time issues (e.g. 3 March at 4:00pm and 3 April at 3:00pm), but it's more accurate and for just a couple lines of code.
Consider each date in terms of months, then subtract to find the difference.
var past_date = new Date('11/1/2014');
var current_date = new Date();
var difference = (current_date.getFullYear()*12 + current_date.getMonth()) - (past_date.getFullYear()*12 + past_date.getMonth());
This will get you the difference of months between the two dates, ignoring the days.
There are two approaches, mathematical & quick, but subject to vagaries in the calendar, or iterative & slow, but handles all the oddities (or at least delegates handling them to a well-tested library).
If you iterate through the calendar, incrementing the start date by one month & seeing if we pass the end date. This delegates anomaly-handling to the built-in Date() classes, but could be slow IF you're doing this for a large number of dates. James' answer takes this approach. As much as I dislike the idea, I think this is the "safest" approach, and if you're only doing one calculation, the performance difference really is negligible. We tend to try to over-optimize tasks which will only be performed once.
Now, if you're calculating this function on a dataset, you probably don't want to run that function on each row (or god forbid, multiple times per record). In that case, you can use almost any of the other answers here except the accepted answer, which is just wrong (difference between new Date() and new Date() is -1)?
Here's my stab at a mathematical-and-quick approach, which accounts for differing month lengths and leap years. You really should only use a function like this if you'll be applying this to a dataset (doing this calculation over & over). If you just need to do it once, use James' iterative approach above, as you're delegating handling all the (many) exceptions to the Date() object.
function diffInMonths(from, to){
var months = to.getMonth() - from.getMonth() + (12 * (to.getFullYear() - from.getFullYear()));
if(to.getDate() < from.getDate()){
var newFrom = new Date(to.getFullYear(),to.getMonth(),from.getDate());
if (to < newFrom && to.getMonth() == newFrom.getMonth() && to.getYear() %4 != 0){
months--;
}
}
return months;
}
Calculate the difference between two dates include fraction of month (days).
var difference = (date2.getDate() - date1.getDate()) / 30 +
date2.getMonth() - date1.getMonth() +
(12 * (date2.getFullYear() - date1.getFullYear()));
For example:
date1: 24/09/2015 (24th Sept 2015)
date2: 09/11/2015 (9th Nov 2015)
the difference: 2.5 (months)
Here you go other approach with less looping:
calculateTotalMonthsDifference = function(firstDate, secondDate) {
var fm = firstDate.getMonth();
var fy = firstDate.getFullYear();
var sm = secondDate.getMonth();
var sy = secondDate.getFullYear();
var months = Math.abs(((fy - sy) * 12) + fm - sm);
var firstBefore = firstDate > secondDate;
firstDate.setFullYear(sy);
firstDate.setMonth(sm);
firstBefore ? firstDate < secondDate ? months-- : "" : secondDate < firstDate ? months-- : "";
return months;
}
This should work fine:
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months += d2.getMonth() - d1.getMonth();
return months;
}
Number Of Months When Day & Time Doesn't Matter
In this case, I'm not concerned with full months, part months, how long a month is, etc. I just need to know the number of months. A relevant real world case would be where a report is due every month, and I need to know how many reports there should be.
Example:
January = 1 month
January - February = 2 months
November - January = 3 months
This is an elaborated code example to show where the numbers are going.
Let's take 2 timestamps that should result in 4 months
November 13, 2019's timestamp: 1573621200000
February 20, 2020's timestamp: 1582261140000
May be slightly different with your timezone / time pulled. The day, minutes, and seconds don't matter and can be included in the timestamp, but we will disregard it with our actual calculation.
Step 1: convert the timestamp to a JavaScript date
let dateRangeStartConverted = new Date(1573621200000);
let dateRangeEndConverted = new Date(1582261140000);
Step 2: get integer values for the months / years
let startingMonth = dateRangeStartConverted.getMonth();
let startingYear = dateRangeStartConverted.getFullYear();
let endingMonth = dateRangeEndConverted.getMonth();
let endingYear = dateRangeEndConverted.getFullYear();
This gives us
Starting month: 11
Starting Year: 2019
Ending month: 2
Ending Year: 2020
Step 3: Add (12 * (endYear - startYear)) + 1 to the ending month.
This makes our starting month stay at 11
This makes our ending month equal 15 2 + (12 * (2020 - 2019)) + 1 = 15
Step 4: Subtract the months
15 - 11 = 4; we get our 4 month result.
29 Month Example Example
November 2019 through March 2022 is 29 months. If you put these into an excel spreadsheet, you will see 29 rows.
Our starting month is 11
Our ending month is 40 3 + (12 * (2022-2019)) + 1
40 - 11 = 29
function calcualteMonthYr(){
var fromDate =new Date($('#txtDurationFrom2').val()); //date picker (text fields)
var toDate = new Date($('#txtDurationTo2').val());
var months=0;
months = (toDate.getFullYear() - fromDate.getFullYear()) * 12;
months -= fromDate.getMonth();
months += toDate.getMonth();
if (toDate.getDate() < fromDate.getDate()){
months--;
}
$('#txtTimePeriod2').val(months);
}
Following code returns full months between two dates by taking nr of days of partial months into account as well.
var monthDiff = function(d1, d2) {
if( d2 < d1 ) {
var dTmp = d2;
d2 = d1;
d1 = dTmp;
}
var months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth();
if( d1.getDate() <= d2.getDate() ) months += 1;
return months;
}
monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 20))
> 1
monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 19))
> 0
monthDiff(new Date(2015, 01, 20), new Date(2015, 01, 22))
> 0
function monthDiff(d1, d2) {
var months, d1day, d2day, d1new, d2new, diffdate,d2month,d2year,d1maxday,d2maxday;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth();
months = (months <= 0 ? 0 : months);
d1day = d1.getDate();
d2day = d2.getDate();
if(d1day > d2day)
{
d2month = d2.getMonth();
d2year = d2.getFullYear();
d1new = new Date(d2year, d2month-1, d1day,0,0,0,0);
var timeDiff = Math.abs(d2.getTime() - d1new.getTime());
diffdate = Math.abs(Math.ceil(timeDiff / (1000 * 3600 * 24)));
d1new = new Date(d2year, d2month, 1,0,0,0,0);
d1new.setDate(d1new.getDate()-1);
d1maxday = d1new.getDate();
months += diffdate / d1maxday;
}
else
{
if(!(d1.getMonth() == d2.getMonth() && d1.getFullYear() == d2.getFullYear()))
{
months += 1;
}
diffdate = d2day - d1day + 1;
d2month = d2.getMonth();
d2year = d2.getFullYear();
d2new = new Date(d2year, d2month + 1, 1, 0, 0, 0, 0);
d2new.setDate(d2new.getDate()-1);
d2maxday = d2new.getDate();
months += diffdate / d2maxday;
}
return months;
}
below logic will fetch difference in months
(endDate.getFullYear()*12+endDate.getMonth())-(startDate.getFullYear()*12+startDate.getMonth())
function monthDiff(date1, date2, countDays) {
countDays = (typeof countDays !== 'undefined') ? countDays : false;
if (!date1 || !date2) {
return 0;
}
let bigDate = date1;
let smallDate = date2;
if (date1 < date2) {
bigDate = date2;
smallDate = date1;
}
let monthsCount = (bigDate.getFullYear() - smallDate.getFullYear()) * 12 + (bigDate.getMonth() - smallDate.getMonth());
if (countDays && bigDate.getDate() < smallDate.getDate()) {
--monthsCount;
}
return monthsCount;
}
This is the simplest solution I could find. This will directly return the number of months. Although, it always gives an absolute value.
new Date(new Date(d2) - new Date(d1)).getMonth();
For non-absolute values, you can use the following solution:
function diff_months(startDate, endDate) {
let diff = new Date( new Date(endDate) - new Date(startDate) ).getMonth();
return endDate >= startDate ? diff : -diff;
}
See what I use:
function monthDiff() {
var startdate = Date.parseExact($("#startingDate").val(), "dd/MM/yyyy");
var enddate = Date.parseExact($("#endingDate").val(), "dd/MM/yyyy");
var months = 0;
while (startdate < enddate) {
if (startdate.getMonth() === 1 && startdate.getDate() === 28) {
months++;
startdate.addMonths(1);
startdate.addDays(2);
} else {
months++;
startdate.addMonths(1);
}
}
return months;
}
It also counts the days and convert them in months.
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12; //calculates months between two years
months -= d1.getMonth() + 1;
months += d2.getMonth(); //calculates number of complete months between two months
day1 = 30-d1.getDate();
day2 = day1 + d2.getDate();
months += parseInt(day2/30); //calculates no of complete months lie between two dates
return months <= 0 ? 0 : months;
}
monthDiff(
new Date(2017, 8, 8), // Aug 8th, 2017 (d1)
new Date(2017, 12, 12) // Dec 12th, 2017 (d2)
);
//return value will be 4 months
getMonthDiff(d1, d2) {
var year1 = dt1.getFullYear();
var year2 = dt2.getFullYear();
var month1 = dt1.getMonth();
var month2 = dt2.getMonth();
var day1 = dt1.getDate();
var day2 = dt2.getDate();
var months = month2 - month1;
var years = year2 -year1
days = day2 - day1;
if (days < 0) {
months -= 1;
}
if (months < 0) {
months += 12;
}
return months + years*!2;
}
Any value is returned along with its absolute value.
function differenceInMonths(firstDate, secondDate) {
if (firstDate > secondDate) [firstDate, secondDate] = [secondDate, firstDate];
let diffMonths = (secondDate.getFullYear() - firstDate.getFullYear()) * 12;
diffMonths -= firstDate.getMonth();
diffMonths += secondDate.getMonth();
return diffMonths;
}
The following code snippet helped me to find months between two dates
Find Months Count Between two dates JS
Months Between two dates JS
Code Snippet
function diff_months_count(startDate, endDate) {
var months;
var d1 = new Date(startDate);
var d2 = new Date(endDate);
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth();
months += d2.getMonth();
return months <= 0 ? 0 : months;
}
#Here is a nice piece of code i wrote for getting number of days and months
from given dates
[1]: jsfiddle link
/**
* Date a end day
* Date b start day
* #param DateA Date #param DateB Date
* #returns Date difference
*/
function getDateDifference(dateA, DateB, type = 'month') {
const END_DAY = new Date(dateA)
const START_DAY = new Date(DateB)
let calculatedDateBy
let returnDateDiff
if (type === 'month') {
const startMonth = START_DAY.getMonth()
const endMonth = END_DAY.getMonth()
calculatedDateBy = startMonth - endMonth
returnDateDiff = Math.abs(
calculatedDateBy + 12 * (START_DAY.getFullYear() - END_DAY.getFullYear())
)
} else {
calculatedDateBy = Math.abs(START_DAY - END_DAY)
returnDateDiff = Math.ceil(calculatedDateBy / (1000 * 60 * 60 * 24))
}
const out = document.getElementById('output')
out.innerText = returnDateDiff
return returnDateDiff
}
// Gets number of days from given dates
/* getDateDifference('2022-03-31','2022-04-08','day') */
// Get number of months from given dates
getDateDifference('2021-12-02','2022-04-08','month')
<div id="output"> </div>
anyVar = (((DisplayTo.getFullYear() * 12) + DisplayTo.getMonth()) - ((DisplayFrom.getFullYear() * 12) + DisplayFrom.getMonth()));
One approach would be to write a simple Java Web Service (REST/JSON) that uses JODA library
http://joda-time.sourceforge.net/faq.html#datediff
to calculate difference between two dates and call that service from javascript.
This assumes your back end is in Java.
Related
How can i get the hours difference between two years (With leap year) in javascript
I have two year 2015 and 2014
var year1="2015";
var year="2016";
I want to get the total hours different between those above years by one line code(with leap year and without leap year)!.
I have tried this below code
// get hours from one year
var date = new Date;
var Hours= date.getFullYear().getHours();
// get hours between two years
var Hours= (date.getFullYear()-dat2.getFullYear()).getHours()
But It's something wrong for me.
You could use a function similar to this:
function getHoursBetweenYears(startYear, endYear) {
var startDate = new Date(startYear, 0, 1),
endDate = new Date(endYear, 0 ,1);
return (+endDate - +startDate) / 3600000;
}
Usage like this:
getHoursBetweenYears(2012, 2013) // 8784
Date object is your saver.
Get time differance. then multiply with min, s, ms.
Gives you time diff total hour between years.
var year=2015,
year1=2016,
timeDiff =(new Date("01/01/"+year1)-new Date("01/01/"+year))/(1000*60*60);
The leap year should be specified by year and also month. So
March d + 59 Add 1 if leap year
….up to
December d + 334 Add 1 if leap year
You can try something like this.
hours = ((new Date()).setFullYear( 2016 ) - (new Date()).setFullYear( 2015 ))/(1000*3600);
View demo jsFiddle
var start = new Date(2015, 0, 0);
var end = new Date(2016, 0, 0);
var diff = end - start;
var oneDay = 1000 * 60 * 60;
var day = Math.floor(diff / oneDay);
alert("Hours: " + day);
Answer
Hours: 8760
Calculate the diffference in milliseconds from two dates (including the first day of the start year and the last day of the end year) and divide the result by 3600000 (1000 * 60 * 60 = milliseconds in one hour):
// difference in hours for two whole years (2015-2016)
var hourdiff = (new Date('2017/01/01') - new Date('2014/12/31'))/(1000*60*60);
You can create a Date extension to calculate hours in a certain year:
Date.prototype.hoursInYear = function() {
return ( (new Date(this.getFullYear()+1, 0, 1)) -
(new Date(this.getFullYear()-1, 11, 31)) ) / 3600000; }
// usage
new Date(1997, 0, 1).hoursInYear(); // => 8784
new Date(2008, 0, 1).hoursInYear(); // => 8808 (leap year)
Or even (the number of hours in a (leap)year is constant)
Date.prototype.hoursInYear = function() {
return new Date(this.getFullYear(), 1, 29).getMonth() == 1
? 8808 : 8784;
}
And finally, using the Date extension, this could be a method to calculate the number of hours in [n years] starting with [startyear]:
function calcHours(startyear, numyears) {
return isNaN(new Date(startyear, 0, 1))
? null // invalid year value
: Array.apply(null, {0: startyear, length: numyears})
.map(function(v, i) {return v == this ? v : this + 1;}, startyear)
.reduce( function(a, b) {
return a + new Date(b, 0, 1)
.hoursInYear();}, 0);
}
// usage
calcHours(2000, 2); //=> 17592 (2000 is leap year)
calcHours(2001, 2); //=> 17568
Get the seconds of both years. setFullYear gives you the unix timestamp in millis. Divide by 1000 and you have seconds. Get the difference between the two years and divide this through 3600 (seconds per hour). Then you have your difference in hours.
function getDiffHours (year1, year2) {
var d1 = new Date().setFullYear(year1) / 1000;
var d2 = new Date().setFullYear(year2) / 1000;
var diff = Math.abs(d2 - d1);
return Math.floor(diff / 3600);
}
Moment js has a function to get the number of days in a month : http://momentjs.com/docs/#/displaying/days-in-month/
However I could not find a function to find the number of iso weeks in a year (52 or 53).
Here's an answer that isn't dependent on a library. It uses a function to calculate the week in the year that 31 December falls in for the required year. If the week is 1 (i.e. 31 December is in the first week of the following year), it moves the day number lower until it gets a different value, which will be the last week of the required year.
function getWeekNumber(d) {
// Copy date so don't modify original
d = new Date(+d);
d.setHours(0, 0, 0, 0);
// Set to nearest Thursday: current date + 4 - current day number
// Make Sunday's day number 7
d.setDate(d.getDate() + 4 - (d.getDay() || 7));
// Get first day of year
var yearStart = new Date(d.getFullYear(), 0, 1);
// Calculate full weeks to nearest Thursday
var weekNo = Math.ceil((((d - yearStart) / 86400000) + 1) / 7)
// Return array of year and week number
return [d.getFullYear(), weekNo];
}
function weeksInYear(year) {
var month = 11,
day = 31,
week;
// Find week that 31 Dec is in. If is first week, reduce date until
// get previous week.
do {
d = new Date(year, month, day--);
week = getWeekNumber(d)[1];
} while (week == 1);
return week;
}
[2015, 2016, 2029, new Date().getFullYear()].forEach(year =>
console.log(`${year} has ${weeksInYear(year)} weeks`)
);
The getWeekNumber code is from here: Get week of year in JavaScript like in PHP.
Edit
Alternatively, if 31 December is in week 1 of the following year, then the subject year has 52 weeks and otherwise has 53 weeks.
function getWeekNumber(d) {
d = new Date(+d);
d.setHours(0, 0, 0, 0);
d.setDate(d.getDate() + 4 - (d.getDay() || 7));
var yearStart = new Date(d.getFullYear(), 0, 1);
var weekNo = Math.ceil((((d - yearStart) / 86400000) + 1) / 7)
return [d.getFullYear(), weekNo];
}
function weeksInYear(year) {
var d = new Date(year, 11, 31);
var week = getWeekNumber(d)[1];
return week == 1 ? 52 : week;
}
[2015, 2016, 2029, new Date().getFullYear()].forEach(year =>
console.log(`${year} has ${weeksInYear(year)} weeks`)
);
Use isoWeek on the last day of the year to get the number of weeks e.g. :
function weeksInYear(year) {
return Math.max(
moment(new Date(year, 11, 31)).isoWeek()
, moment(new Date(year, 11, 31-7)).isoWeek()
);
}
Feb. 4th 2014 the weeksInYear & isoWeeksInYear functions were added to moment.js
So today you can just use moment().isoWeeksInYear()or moment().weeksInYear()
For more into see the docs
Thought I would post a much simpler version that I derived from the wikipedia article.
https://en.wikipedia.org/wiki/ISO_week_date
The statement in the article is:
"The number of weeks in a given year is equal to the corresponding
week number of 28 December, because it is the only date that is always
in the last week of the year since it is a week before 4 January which
is always in the first week of the following year.
Using only the ordinal year number y, the number of weeks in that year
can be determined from a function, that
returns the day of the week of 31 December"
Therefore getWeekFor(new Date(2022, 11, 28) replacing the year with any year you want will always give you the number of weeks for that year.
// modified from https://stackoverflow.com/questions/6117814/get-week-of-year-in-javascript-like-in-php
const getWeekFor = (date) => {
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
const dayNum = d.getUTCDay() || 7;
const utc = new Date(d.setUTCDate(d.getUTCDate() + 4 - dayNum));
const yearStart = new Date(Date.UTC(utc.getUTCFullYear(), 0, 1)).getTime();
return Math.ceil(((d.getTime() - yearStart) / 86400000 + 1) / 7);
};
const weeks = getWeekFor(new Date(2020, 11, 28)) // 53.
console.log(weeks);
Get all weeks and periods of that week for a year, for whom it may interest
function getWeekPeriodsInYear(year) {
weeks = [];
// Get the first and last day of the year
currentDay = moment([year, 1]).startOf('year');
dayOfWeek = moment(currentDay).day();
lastDay = moment([year, 1]).endOf('year');
weeksInYear = moment(`${year}-01-01`).isoWeeksInYear();
daysToAdd = 7 - dayOfWeek;
for (let weekNumber = 1; weekNumber < weeksInYear + 1; weekNumber++) {
let endOfWeek = moment(currentDay).add(daysToAdd, 'days');
if (moment(endOfWeek).year() !== year) {
endOfWeek = lastDay;
}
weeks.push({ weekNumber, start: currentDay.toDate(), end: endOfWeek.toDate() });
currentDay = endOfWeek.add(1, 'day');
daysToAdd = 6;
}
return weeks;
}
getWeekPeriodsInYear(new Date().getFullYear()).forEach(period =>
document.write(`Week ${period.weekNumber} from ${moment(period.start).format('DD-MM-YYYY')} up to and including ${moment(period.end).format('DD-MM-YYYY')}<br/>`)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
How do I use JavaScript to calculate the day of the year, from 1 - 366?
For example:
January 3 should be 3.
February 1 should be 32.
Following OP's edit:
var now = new Date();
var start = new Date(now.getFullYear(), 0, 0);
var diff = now - start;
var oneDay = 1000 * 60 * 60 * 24;
var day = Math.floor(diff / oneDay);
console.log('Day of year: ' + day);
Edit: The code above will fail when now is a date in between march 26th and October 29th andnow's time is before 1AM (eg 00:59:59). This is due to the code not taking daylight savings time into account. You should compensate for this:
var now = new Date();
var start = new Date(now.getFullYear(), 0, 0);
var diff = (now - start) + ((start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000);
var oneDay = 1000 * 60 * 60 * 24;
var day = Math.floor(diff / oneDay);
console.log('Day of year: ' + day);
I find it very interesting that no one considered using UTC since it is not subject to DST. Therefore, I propose the following:
function daysIntoYear(date){
return (Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) - Date.UTC(date.getFullYear(), 0, 0)) / 24 / 60 / 60 / 1000;
}
You can test it with the following:
[new Date(2016,0,1), new Date(2016,1,1), new Date(2016,2,1), new Date(2016,5,1), new Date(2016,11,31)]
.forEach(d =>
console.log(`${d.toLocaleDateString()} is ${daysIntoYear(d)} days into the year`));
Which outputs for the leap year 2016 (verified using http://www.epochconverter.com/days/2016):
1/1/2016 is 1 days into the year
2/1/2016 is 32 days into the year
3/1/2016 is 61 days into the year
6/1/2016 is 153 days into the year
12/31/2016 is 366 days into the year
This works across Daylight Savings Time changes in all countries (the "noon" one above doesn't work in Australia):
Date.prototype.isLeapYear = function() {
var year = this.getFullYear();
if((year & 3) != 0) return false;
return ((year % 100) != 0 || (year % 400) == 0);
};
// Get Day of Year
Date.prototype.getDOY = function() {
var dayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
var mn = this.getMonth();
var dn = this.getDate();
var dayOfYear = dayCount[mn] + dn;
if(mn > 1 && this.isLeapYear()) dayOfYear++;
return dayOfYear;
};
Date.prototype.dayOfYear= function(){
var j1= new Date(this);
j1.setMonth(0, 0);
return Math.round((this-j1)/8.64e7);
}
alert(new Date().dayOfYear())
Luckily this question doesn't specify if the number of the current day is required, leaving room for this answer.
Also some answers (also on other questions) had leap-year problems or used the Date-object. Although javascript's Date object covers approximately 285616 years (100,000,000 days) on either side of January 1 1970, I was fed up with all kinds of unexpected date inconsistencies across different browsers (most notably year 0 to 99). I was also curious how to calculate it.
So I wrote a simple and above all, small algorithm to calculate the correct (Proleptic Gregorian / Astronomical / ISO 8601:2004 (clause 4.3.2.1), so year 0 exists and is a leap year and negative years are supported) day of the year based on year, month and day.
Note that in AD/BC notation, year 0 AD/BC does not exist: instead year 1 BC is the leap-year! IF you need to account for BC notation then simply subtract one year of the (otherwise positive) year-value first!!
I modified (for javascript) the short-circuit bitmask-modulo leapYear algorithm and came up with a magic number to do a bit-wise lookup of offsets (that excludes jan and feb, thus needing 10 * 3 bits (30 bits is less than 31 bits, so we can safely save another character on the bitshift instead of >>>)).
Note that neither month or day may be 0. That means that if you need this equation just for the current day (feeding it using .getMonth()) you just need to remove the -- from --m.
Note this assumes a valid date (although error-checking is just some characters more).
function dayNo(y,m,d){
return --m*31-(m>1?(1054267675>>m*3-6&7)-(y&3||!(y%25)&&y&15?0:1):0)+d;
}
<!-- some examples for the snippet -->
<input type=text value="(-)Y-M-D" onblur="
var d=this.value.match(/(-?\d+)[^\d]+(\d\d?)[^\d]+(\d\d?)/)||[];
this.nextSibling.innerHTML=' Day: ' + dayNo(+d[1], +d[2], +d[3]);
" /><span></span>
<br><hr><br>
<button onclick="
var d=new Date();
this.nextSibling.innerHTML=dayNo(d.getFullYear(), d.getMonth()+1, d.getDate()) + ' Day(s)';
">get current dayno:</button><span></span>
Here is the version with correct range-validation.
function dayNo(y,m,d){
return --m>=0 && m<12 && d>0 && d<29+(
4*(y=y&3||!(y%25)&&y&15?0:1)+15662003>>m*2&3
) && m*31-(m>1?(1054267675>>m*3-6&7)-y:0)+d;
}
<!-- some examples for the snippet -->
<input type=text value="(-)Y-M-D" onblur="
var d=this.value.match(/(-?\d+)[^\d]+(\d\d?)[^\d]+(\d\d?)/)||[];
this.nextSibling.innerHTML=' Day: ' + dayNo(+d[1], +d[2], +d[3]);
" /><span></span>
Again, one line, but I split it into 3 lines for readability (and following explanation).
The last line is identical to the function above, however the (identical) leapYear algorithm is moved to a previous short-circuit section (before the day-number calculation), because it is also needed to know how much days a month has in a given (leap) year.
The middle line calculates the correct offset number (for max number of days) for a given month in a given (leap)year using another magic number: since 31-28=3 and 3 is just 2 bits, then 12*2=24 bits, we can store all 12 months. Since addition can be faster then subtraction, we add the offset (instead of subtract it from 31). To avoid a leap-year decision-branch for February, we modify that magic lookup-number on the fly.
That leaves us with the (pretty obvious) first line: it checks that month and date are within valid bounds and ensures us with a false return value on range error (note that this function also should not be able to return 0, because 1 jan 0000 is still day 1.), providing easy error-checking: if(r=dayNo(/*y, m, d*/)){}.
If used this way (where month and day may not be 0), then one can change --m>=0 && m<12 to m>0 && --m<12 (saving another char).
The reason I typed the snippet in it's current form is that for 0-based month values, one just needs to remove the -- from --m.
Extra:
Note, don't use this day's per month algorithm if you need just max day's per month. In that case there is a more efficient algorithm (because we only need leepYear when the month is February) I posted as answer this question: What is the best way to determine the number of days in a month with javascript?.
If used moment.js, we can get or even set the day of the year.
moment().dayOfYear();
//for getting
moment().dayOfYear(Number);
//for setting
moment.js is using this code for day of year calculation
If you don't want to re-invent the wheel, you can use the excellent date-fns (node.js) library:
var getDayOfYear = require('date-fns/get_day_of_year')
var dayOfYear = getDayOfYear(new Date(2017, 1, 1)) // 1st february => 32
This is my solution:
Math.floor((Date.now() - new Date(new Date().getFullYear(), 0, 0)) / 86400000)
Demo:
const getDateOfYear = (date) =>
Math.floor((date.getTime() - new Date(date.getFullYear(), 0, 0)) / 864e5);
const dayOfYear = getDateOfYear(new Date());
console.log(dayOfYear);
const dayOfYear = date => {
const myDate = new Date(date);
const year = myDate.getFullYear();
const firstJan = new Date(year, 0, 1);
const differenceInMillieSeconds = myDate - firstJan;
return (differenceInMillieSeconds / (1000 * 60 * 60 * 24) + 1);
};
const result = dayOfYear("2019-2-01");
console.log(result);
Well, if I understand you correctly, you want 366 on a leap year, 365 otherwise, right? A year is a leap year if it's evenly divisible by 4 but not by 100 unless it's also divisible by 400:
function daysInYear(year) {
if(year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) {
// Leap year
return 366;
} else {
// Not a leap year
return 365;
}
}
Edit after update:
In that case, I don't think there's a built-in method; you'll need to do this:
function daysInFebruary(year) {
if(year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) {
// Leap year
return 29;
} else {
// Not a leap year
return 28;
}
}
function dateToDay(date) {
var feb = daysInFebruary(date.getFullYear());
var aggregateMonths = [0, // January
31, // February
31 + feb, // March
31 + feb + 31, // April
31 + feb + 31 + 30, // May
31 + feb + 31 + 30 + 31, // June
31 + feb + 31 + 30 + 31 + 30, // July
31 + feb + 31 + 30 + 31 + 30 + 31, // August
31 + feb + 31 + 30 + 31 + 30 + 31 + 31, // September
31 + feb + 31 + 30 + 31 + 30 + 31 + 31 + 30, // October
31 + feb + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, // November
31 + feb + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30, // December
];
return aggregateMonths[date.getMonth()] + date.getDate();
}
(Yes, I actually did that without copying or pasting. If there's an easy way I'll be mad)
This is a simple way to find the current day in the year, and it should account for leap years without a problem:
Javascript:
Math.round((new Date().setHours(23) - new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0))/1000/60/60/24);
Javascript in Google Apps Script:
Math.round((new Date().setHours(23) - new Date(new Date().getYear(), 0, 1, 0, 0, 0))/1000/60/60/24);
The primary action of this code is to find the number of milliseconds that have elapsed in the current year and then convert this number into days. The number of milliseconds that have elapsed in the current year can be found by subtracting the number of milliseconds of the first second of the first day of the current year, which is obtained with new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0) (Javascript) or new Date(new Date().getYear(), 0, 1, 0, 0, 0) (Google Apps Script), from the milliseconds of the 23rd hour of the current day, which was found with new Date().setHours(23). The purpose of setting the current date to the 23rd hour is to ensure that the day of year is rounded correctly by Math.round().
Once you have the number of milliseconds of the current year, then you can convert this time into days by dividing by 1000 to convert milliseconds to seconds, then dividing by 60 to convert seconds to minutes, then dividing by 60 to convert minutes to hours, and finally dividing by 24 to convert hours to days.
Note: This post was edited to account for differences between JavaScript and JavaScript implemented in Google Apps Script. Also, more context was added for the answer.
I think this is more straightforward:
var date365 = 0;
var currentDate = new Date();
var currentYear = currentDate.getFullYear();
var currentMonth = currentDate.getMonth();
var currentDay = currentDate.getDate();
var monthLength = [31,28,31,30,31,30,31,31,30,31,30,31];
var leapYear = new Date(currentYear, 1, 29);
if (leapYear.getDate() == 29) { // If it's a leap year, changes 28 to 29
monthLength[1] = 29;
}
for ( i=0; i < currentMonth; i++ ) {
date365 = date365 + monthLength[i];
}
date365 = date365 + currentDay; // Done!
This method takes into account timezone issue and daylight saving time
function dayofyear(d) { // d is a Date object
var yn = d.getFullYear();
var mn = d.getMonth();
var dn = d.getDate();
var d1 = new Date(yn,0,1,12,0,0); // noon on Jan. 1
var d2 = new Date(yn,mn,dn,12,0,0); // noon on input date
var ddiff = Math.round((d2-d1)/864e5);
return ddiff+1;
}
(took from here)
See also this fiddle
Math.round((new Date().setHours(23) - new Date(new Date().getFullYear(), 0, 1, 0, 0, 0))/1000/86400);
further optimizes the answer.
Moreover, by changing setHours(23) or the last-but-two zero later on to another value may provide day-of-year related to another timezone.
For example, to retrieve from Europe a resource located in America.
This might be useful to those who need the day of the year as a string and have jQuery UI available.
You can use jQuery UI Datepicker:
day_of_year_string = $.datepicker.formatDate("o", new Date())
Underneath it works the same way as some of the answers already mentioned ((date_ms - first_date_of_year_ms) / ms_per_day):
function getDayOfTheYearFromDate(d) {
return Math.round((new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime()
- new Date(d.getFullYear(), 0, 0).getTime()) / 86400000);
}
day_of_year_int = getDayOfTheYearFromDate(new Date())
maybe help anybody
let day = (date => {
return Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24)
})(new Date())
I've made one that's readable and will do the trick very quickly, as well as handle JS Date objects with disparate time zones.
I've included quite a few test cases for time zones, DST, leap seconds and Leap years.
P.S. ECMA-262 ignores leap seconds, unlike UTC. If you were to convert this to a language that uses real UTC, you could just add 1 to oneDay.
// returns 1 - 366
findDayOfYear = function (date) {
var oneDay = 1000 * 60 * 60 * 24; // A day in milliseconds
var og = { // Saving original data
ts: date.getTime(),
dom: date.getDate(), // We don't need to save hours/minutes because DST is never at 12am.
month: date.getMonth()
}
date.setDate(1); // Sets Date of the Month to the 1st.
date.setMonth(0); // Months are zero based in JS's Date object
var start_ts = date.getTime(); // New Year's Midnight JS Timestamp
var diff = og.ts - start_ts;
date.setDate(og.dom); // Revert back to original date object
date.setMonth(og.month); // This method does preserve timezone
return Math.round(diff / oneDay) + 1; // Deals with DST globally. Ceil fails in Australia. Floor Fails in US.
}
// Tests
var pre_start_dst = new Date(2016, 2, 12);
var on_start_dst = new Date(2016, 2, 13);
var post_start_dst = new Date(2016, 2, 14);
var pre_end_dst_date = new Date(2016, 10, 5);
var on_end_dst_date = new Date(2016, 10, 6);
var post_end_dst_date = new Date(2016, 10, 7);
var pre_leap_second = new Date(2015, 5, 29);
var on_leap_second = new Date(2015, 5, 30);
var post_leap_second = new Date(2015, 6, 1);
// 2012 was a leap year with a leap second in june 30th
var leap_second_december31_premidnight = new Date(2012, 11, 31, 23, 59, 59, 999);
var january1 = new Date(2016, 0, 1);
var january31 = new Date(2016, 0, 31);
var december31 = new Date(2015, 11, 31);
var leap_december31 = new Date(2016, 11, 31);
alert( ""
+ "\nPre Start DST: " + findDayOfYear(pre_start_dst) + " === 72"
+ "\nOn Start DST: " + findDayOfYear(on_start_dst) + " === 73"
+ "\nPost Start DST: " + findDayOfYear(post_start_dst) + " === 74"
+ "\nPre Leap Second: " + findDayOfYear(pre_leap_second) + " === 180"
+ "\nOn Leap Second: " + findDayOfYear(on_leap_second) + " === 181"
+ "\nPost Leap Second: " + findDayOfYear(post_leap_second) + " === 182"
+ "\nPre End DST: " + findDayOfYear(pre_end_dst_date) + " === 310"
+ "\nOn End DST: " + findDayOfYear(on_end_dst_date) + " === 311"
+ "\nPost End DST: " + findDayOfYear(post_end_dst_date) + " === 312"
+ "\nJanuary 1st: " + findDayOfYear(january1) + " === 1"
+ "\nJanuary 31st: " + findDayOfYear(january31) + " === 31"
+ "\nNormal December 31st: " + findDayOfYear(december31) + " === 365"
+ "\nLeap December 31st: " + findDayOfYear(leap_december31) + " === 366"
+ "\nLast Second of Double Leap: " + findDayOfYear(leap_second_december31_premidnight) + " === 366"
);
I would like to provide a solution that does calculations adding the days for each previous month:
function getDayOfYear(date) {
var month = date.getMonth();
var year = date.getFullYear();
var days = date.getDate();
for (var i = 0; i < month; i++) {
days += new Date(year, i+1, 0).getDate();
}
return days;
}
var input = new Date(2017, 7, 5);
console.log(input);
console.log(getDayOfYear(input));
This way you don't have to manage the details of leap years and daylight saving.
A alternative using UTC timestamps. Also as others noted the day indicating 1st a month is 1 rather than 0. The month starts at 0 however.
var now = Date.now();
var year = new Date().getUTCFullYear();
var year_start = Date.UTC(year, 0, 1);
var day_length_in_ms = 1000*60*60*24;
var day_number = Math.floor((now - year_start)/day_length_in_ms)
console.log("Day of year " + day_number);
You can pass parameter as date number in setDate function:
var targetDate = new Date();
targetDate.setDate(1);
// Now we can see the expected date as: Mon Jan 01 2018 01:43:24
console.log(targetDate);
targetDate.setDate(365);
// You can see: Mon Dec 31 2018 01:44:47
console.log(targetDate)
For those among us who want a fast alternative solution.
(function(){"use strict";
function daysIntoTheYear(dateInput){
var fullYear = dateInput.getFullYear()|0;
// "Leap Years are any year that can be exactly divided by 4 (2012, 2016, etc)
// except if it can be exactly divided by 100, then it isn't (2100, 2200, etc)
// except if it can be exactly divided by 400, then it is (2000, 2400)"
// (https://www.mathsisfun.com/leap-years.html).
var isLeapYear = ((fullYear & 3) | (fullYear/100 & 3)) === 0 ? 1 : 0;
// (fullYear & 3) = (fullYear % 4), but faster
//Alternative:var isLeapYear=(new Date(currentYear,1,29,12)).getDate()===29?1:0
var fullMonth = dateInput.getMonth()|0;
return ((
// Calculate the day of the year in the Gregorian calendar
// The code below works based upon the facts of signed right shifts
// • (x) >> n: shifts n and fills in the n highest bits with 0s
// • (-x) >> n: shifts n and fills in the n highest bits with 1s
// (This assumes that x is a positive integer)
(31 & ((-fullMonth) >> 4)) + // January // (-11)>>4 = -1
((28 + isLeapYear) & ((1-fullMonth) >> 4)) + // February
(31 & ((2-fullMonth) >> 4)) + // March
(30 & ((3-fullMonth) >> 4)) + // April
(31 & ((4-fullMonth) >> 4)) + // May
(30 & ((5-fullMonth) >> 4)) + // June
(31 & ((6-fullMonth) >> 4)) + // July
(31 & ((7-fullMonth) >> 4)) + // August
(30 & ((8-fullMonth) >> 4)) + // September
(31 & ((9-fullMonth) >> 4)) + // October
(30 & ((10-fullMonth) >> 4)) + // November
// There are no months past December: the year rolls into the next.
// Thus, fullMonth is 0-based, so it will never be 12 in Javascript
(dateInput.getDate()|0) // get day of the month
)&0xffff);
}
// Demonstration:
var date = new Date(2100, 0, 1)
for (var i=0; i<12; i=i+1|0, date.setMonth(date.getMonth()+1|0))
console.log(date.getMonth()+":\tday "+daysIntoTheYear(date)+"\t"+date);
date = new Date(1900, 0, 1);
for (var i=0; i<12; i=i+1|0, date.setMonth(date.getMonth()+1|0))
console.log(date.getMonth()+":\tday "+daysIntoTheYear(date)+"\t"+date);
// Performance Benchmark:
console.time("Speed of processing 65536 dates");
for (var i=0,month=date.getMonth()|0; i<65536; i=i+1|0)
date.setMonth(month=month+1+(daysIntoTheYear(date)|0)|0);
console.timeEnd("Speed of processing 65536 dates");
})();
The size of the months of the year and the way that Leap Years work fits perfectly into keeping our time on track with the sun. Heck, it works so perfectly that all we ever do is just adjust mere seconds here and there. Our current system of leap years has been in effect since February 24th, 1582, and will likely stay in effect for the foreseeable future.
DST, however, is very subject to change. It may be that 20 years from now, some country may offset time by a whole day or some other extreme for DST. A whole DST day will almost certainly never happen, but DST is still nevertheless very up-in-the-air and indecisive. Thus, the above solution is future proof in addition to being very very fast.
The above code snippet runs very fast. My computer can process 65536 dates in ~52ms on Chrome.
This is a solution that avoids the troublesome Date object and timezone issues, it requires that your input date be in the format "yyyy-dd-mm". If you want to change the format, then modify date_str_to_parts function:
function get_day_of_year(str_date){
var date_parts = date_str_to_parts(str_date);
var is_leap = (date_parts.year%4)==0;
var acct_for_leap = (is_leap && date_parts.month>2);
var day_of_year = 0;
var ary_months = [
0,
31, //jan
28, //feb(non leap)
31, //march
30, //april
31, //may
30, //june
31, //july
31, //aug
30, //sep
31, //oct
30, //nov
31 //dec
];
for(var i=1; i < date_parts.month; i++){
day_of_year += ary_months[i];
}
day_of_year += date_parts.date;
if( acct_for_leap ) day_of_year+=1;
return day_of_year;
}
function date_str_to_parts(str_date){
return {
"year":parseInt(str_date.substr(0,4),10),
"month":parseInt(str_date.substr(5,2),10),
"date":parseInt(str_date.substr(8,2),10)
}
}
A straightforward solution with complete explanation.
var dayOfYear = function(date) {
const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
const [yyyy, mm, dd] = date.split('-').map(Number);
// Checks if February has 29 days
const isLeap = (year) => new Date(year, 1, 29).getDate() === 29;
// If it's a leap year, changes 28 to 29
if (isLeap(yyyy)) daysInMonth[1] = 29;
let daysBeforeMonth = 0;
// Slice the array and exclude the current Month
for (const i of daysInMonth.slice(0, mm - 1)) {
daysBeforeMonth += i;
}
return daysBeforeMonth + dd;
};
console.log(dayOfYear('2020-1-3'));
console.log(dayOfYear('2020-2-1'));
I wrote these two javascript functions which return the day of the year (Jan 1 = 1).
Both of them account for leap years.
function dayOfTheYear() {
// for today
var M=[31,28,31,30,31,30,31,31,30,31,30,31]; var x=new Date(); var m=x.getMonth();
var y=x.getFullYear(); if (y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)) {++M[1];}
var Y=0; for (var i=0;i<m;++i) {Y+=M[i];}
return Y+x.getDate();
}
function dayOfTheYear2(m,d,y) {
// for any day : m is 1 to 12, d is 1 to 31, y is a 4-digit year
var m,d,y; var M=[31,28,31,30,31,30,31,31,30,31,30,31];
if (y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)) {++M[1];}
var Y=0; for (var i=0;i<m-1;++i) {Y+=M[i];}
return Y+d;
}
One Line:
Array.from(new Array(new Date().getMonth()), (x, i) => i).reduce((c, p, idx, array)=>{
let returnValue = c + new Date(new Date().getFullYear(), p, 0).getDate();
if(idx == array.length -1){
returnValue = returnValue + new Date().getDate();
}
return returnValue;
}, 0)
I needed a reliable (leap year and time zone resistant) algorithm for an application that makes heavy use of this feature, I found some algorithm written in the 90s and found that there is still no such efficient and stable solution here:
function dayOfYear1 (date) {
const year = date.getFullYear();
const month = date.getMonth()+1;
const day = date.getDate();
const N1 = Math.floor(275 * month / 9);
const N2 = Math.floor((month + 9) / 12);
const N3 = (1 + Math.floor((year - 4 * Math.floor(year / 4) + 2) / 3));
const N = N1 - (N2 * N3) + day - 30;
return N;
}
Algorithm works correctly in leap years, it does not depend on time zones with Date() and on top of that it is more efficient than any of the lower ones:
function dayOfYear2 (date) {
const monthsDays = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
const year = date.getFullYear();
const month = date.getMonth();
const day = date.getDate();
let N = monthsDays[month] + day;
if ( month>1 && year%4==0 )
N++;
return N;
}
function dayOfYear3 (date) {
const yearDate = new Date(date.getFullYear(), 0, 0);
const timeZoneDiff = yearDate.getTimezoneOffset() - date.getTimezoneOffset();
const N = Math.floor(((date - yearDate )/1000/60 + timeZoneDiff)/60/24);
return N;
}
All of them are correct and work under the conditions mentioned above.
Performance comparison in 100k loop:
dayOfYear1 - 15 ms
dayOfYear2 - 17 ms
dayOfYear3 - 80 ms
It always get's me worried when mixing maths with date functions (it's so easy to miss some leap year other detail). Say you have:
var d = new Date();
I would suggest using the following, days will be saved in day:
for(var day = d.getDate(); d.getMonth(); day += d.getDate())
d.setDate(0);
Can't see any reason why this wouldn't work just fine (and I wouldn't be so worried about the few iterations since this will not be used so intensively).
I want to get the number of years between two dates. I can get the number of days between these two days, but if I divide it by 365 the result is incorrect because some years have 366 days.
This is my code to get date difference:
var birthday = value;//format 01/02/1900
var dateParts = birthday.split("/");
var checkindate = new Date(dateParts[2], dateParts[0] - 1, dateParts[1]);
var now = new Date();
var difference = now - checkindate;
var days = difference / (1000*60*60*24);
var thisyear = new Date().getFullYear();
var birthyear = dateParts[2];
var number_of_long_years = 0;
for(var y=birthyear; y <= thisyear; y++){
if( (y % 4 == 0 && y % 100 == 0) || y % 400 == 0 ) {
number_of_long_years++;
}
}
The day count works perfectly. I am trying to do add the additional days when it is a 366-day year, and I'm doing something like this:
var years = ((days)*(thisyear-birthyear))
/((number_of_long_years*366) + ((thisyear-birthyear-number_of_long_years)*365) );
I'm getting the year count. Is this correct, or is there a better way to do this?
Sleek foundation javascript function.
function calculateAge(birthday) { // birthday is a date
var ageDifMs = Date.now() - birthday;
var ageDate = new Date(ageDifMs); // miliseconds from epoch
return Math.abs(ageDate.getUTCFullYear() - 1970);
}
Probably not the answer you're looking for, but at 2.6kb, I would not try to reinvent the wheel and I'd use something like moment.js. Does not have any dependencies.
The diff method is probably what you want: http://momentjs.com/docs/#/displaying/difference/
Using pure javascript Date(), we can calculate the numbers of years like below
document.getElementById('getYearsBtn').addEventListener('click', function () {
var enteredDate = document.getElementById('sampleDate').value;
// Below one is the single line logic to calculate the no. of years...
var years = new Date(new Date() - new Date(enteredDate)).getFullYear() - 1970;
console.log(years);
});
<input type="text" id="sampleDate" value="1980/01/01">
<div>Format: yyyy-mm-dd or yyyy/mm/dd</div><br>
<button id="getYearsBtn">Calculate Years</button>
No for-each loop, no extra jQuery plugin needed... Just call the below function.. Got from Difference between two dates in years
function dateDiffInYears(dateold, datenew) {
var ynew = datenew.getFullYear();
var mnew = datenew.getMonth();
var dnew = datenew.getDate();
var yold = dateold.getFullYear();
var mold = dateold.getMonth();
var dold = dateold.getDate();
var diff = ynew - yold;
if (mold > mnew) diff--;
else {
if (mold == mnew) {
if (dold > dnew) diff--;
}
}
return diff;
}
I use the following for age calculation.
I named it gregorianAge() because this calculation gives exactly how we denote age using Gregorian calendar. i.e. Not counting the end year if month and day is before the month and day of the birth year.
/**
* Calculates human age in years given a birth day. Optionally ageAtDate
* can be provided to calculate age at a specific date
*
* #param string|Date Object birthDate
* #param string|Date Object ageAtDate optional
* #returns integer Age between birthday and a given date or today
*/
gregorianAge = function(birthDate, ageAtDate) {
// convert birthDate to date object if already not
if (Object.prototype.toString.call(birthDate) !== '[object Date]')
birthDate = new Date(birthDate);
// use today's date if ageAtDate is not provided
if (typeof ageAtDate == "undefined")
ageAtDate = new Date();
// convert ageAtDate to date object if already not
else if (Object.prototype.toString.call(ageAtDate) !== '[object Date]')
ageAtDate = new Date(ageAtDate);
// if conversion to date object fails return null
if (ageAtDate == null || birthDate == null)
return null;
var _m = ageAtDate.getMonth() - birthDate.getMonth();
// answer: ageAt year minus birth year less one (1) if month and day of
// ageAt year is before month and day of birth year
return (ageAtDate.getFullYear()) - birthDate.getFullYear()
- ((_m < 0 || (_m === 0 && ageAtDate.getDate() < birthDate.getDate()))?1:0)
}
<input type="text" id="birthDate" value="12 February 1982">
<div style="font-size: small; color: grey">Enter a date in an acceptable format e.g. 10 Dec 2001</div><br>
<button onClick='js:alert(gregorianAge(document.getElementById("birthDate").value))'>What's my age?</button>
Little out of date but here is a function you can use!
function calculateAge(birthMonth, birthDay, birthYear) {
var currentDate = new Date();
var currentYear = currentDate.getFullYear();
var currentMonth = currentDate.getMonth();
var currentDay = currentDate.getDate();
var calculatedAge = currentYear - birthYear;
if (currentMonth < birthMonth - 1) {
calculatedAge--;
}
if (birthMonth - 1 == currentMonth && currentDay < birthDay) {
calculatedAge--;
}
return calculatedAge;
}
var age = calculateAge(12, 8, 1993);
alert(age);
You can get the exact age using timesstamp:
const getAge = (dateOfBirth, dateToCalculate = new Date()) => {
const dob = new Date(dateOfBirth).getTime();
const dateToCompare = new Date(dateToCalculate).getTime();
const age = (dateToCompare - dob) / (365 * 24 * 60 * 60 * 1000);
return Math.floor(age);
};
let currentTime = new Date().getTime();
let birthDateTime= new Date(birthDate).getTime();
let difference = (currentTime - birthDateTime)
var ageInYears=difference/(1000*60*60*24*365)
Yep, moment.js is pretty good for this:
var moment = require('moment');
var startDate = new Date();
var endDate = new Date();
endDate.setDate(endDate.getFullYear() + 5); // Add 5 years to second date
console.log(moment.duration(endDate - startDate).years()); // This should returns 5
getYears(date1, date2) {
let years = new Date(date1).getFullYear() - new Date(date2).getFullYear();
let month = new Date(date1).getMonth() - new Date(date2).getMonth();
let dateDiff = new Date(date1).getDay() - new Date(date2).getDay();
if (dateDiff < 0) {
month -= 1;
}
if (month < 0) {
years -= 1;
}
return years;
}
for(var y=birthyear; y <= thisyear; y++){
if( (y % 4 == 0 && y % 100 == 0) || y % 400 == 0 ) {
days = days-366;
number_of_long_years++;
} else {
days=days-365;
}
year++;
}
can you try this way??
function getYearDiff(startDate, endDate) {
let yearDiff = endDate.getFullYear() - startDate.getFullYear();
if (startDate.getMonth() > endDate.getMonth()) {
yearDiff--;
} else if (startDate.getMonth() === endDate.getMonth()) {
if (startDate.getDate() > endDate.getDate()) {
yearDiff--;
} else if (startDate.getDate() === endDate.getDate()) {
if (startDate.getHours() > endDate.getHours()) {
yearDiff--;
} else if (startDate.getHours() === endDate.getHours()) {
if (startDate.getMinutes() > endDate.getMinutes()) {
yearDiff--;
}
}
}
}
return yearDiff;
}
alert(getYearDiff(firstDate, secondDate));
getAge(month, day, year) {
let yearNow = new Date().getFullYear();
let monthNow = new Date().getMonth() + 1;
let dayNow = new Date().getDate();
if (monthNow === month && dayNow < day || monthNow < month) {
return yearNow - year - 1;
} else {
return yearNow - year;
}
}
If you are using moment
/**
* Convert date of birth into age
* param {string} dateOfBirth - date of birth
* param {string} dateToCalculate - date to compare
* returns {number} - age
*/
function getAge(dateOfBirth, dateToCalculate) {
const dob = moment(dateOfBirth);
return moment(dateToCalculate).diff(dob, 'years');
};
If you want to calculate the years and keep the remainder of the time left for further calculations you can use this function most of the other answers discard the remaining time.
It returns the years and the remainder in milliseconds. This is useful if you want to calculate the time (days or minutes) left after you calculate the years.
The function works by first calculating the difference in years directly using *date.getFullYear()*.
Then it checks if the last year between the two dates is up to a full year by setting the two dates to the same year.
Eg:
oldDate= 1 July 2020,
newDate= 1 June 2022,
years =2020 -2022 =2
Now set old date to new date's year 2022
oldDate = 1 July, 2022
If the last year is not up to a full year then the year is subtracted by 1, the old date is set to the previous year and the interval from the previous year to the current date is calculated to give the remainder in milliseconds.
In the example since old date July 2022 is greater than June 2022 then it means a full year has not yet elapsed (from July 2021 to June 2022) therefore the year count is greater by 1. So years should be decreased by 1. And the actual year count from July 2020 to June 2022 is 1 year ,... months.
If the last year is a full year then the year count by *date.getFullYear()* is correct and the time that has elapsed from the current old date to new date is calculated as the remainder.
If old date= 1 April, 2020, new date = 1 June, 2022 and old date is set to April 2022 after calculating the year =2.
Eg: from April 2020 to June 2022 a duration of 2 years has passed with the remainder being the time from April 2022 to June 2022.
There are also checks for cases where the two dates are in the same year and if the user enters the dates in the wrong order the new Date is less recent than the old Date.
let getYearsAndRemainder = (newDate, oldDate) => {
let remainder = 0;
// get initial years between dates
let years = newDate.getFullYear() - oldDate.getFullYear();
if (years < 0) {// check to make sure the oldDate is the older of the two dates
console.warn('new date is lesser than old date in year difference')
years = 0;
} else {
// set the old date to the same year as new date
oldDate.setFullYear(newDate.getFullYear());
// check if the old date is less than new date in the same year
if (oldDate - newDate > 0) {
//if true, the old date is greater than the new date
// the last but one year between the two dates is not up to a year
if (years != 0) {// dates given in inputs are in the same year, no need to calculate years if the number of years is 0
console.log('Subtracting year');
//set the old year to the previous year
years--;
oldDate.setFullYear(oldDate.getFullYear() - 1);
}
}
}
//calculate the time difference between the old year and newDate.
remainder = newDate - oldDate;
if (remainder < 0) { //check for negative dates due to wrong inputs
console.warn('old date is greater than new Date');
console.log('new date', newDate, 'old date', oldDate);
}
return { years, remainder };
}
let old = new Date('2020-07-01');
console.log( getYearsAndRemainder(new Date(), old));
Date calculation work via the Julian day number. You have to take the first of January of the two years. Then you convert the Gregorian dates into Julian day numbers and after that you take just the difference.
Maybe my function can explain better how to do this in a simple way without loop, calculations and/or libs
function checkYearsDifference(birthDayDate){
var todayDate = new Date();
var thisMonth = todayDate.getMonth();
var thisYear = todayDate.getFullYear();
var thisDay = todayDate.getDate();
var monthBirthday = birthDayDate.getMonth();
var yearBirthday = birthDayDate.getFullYear();
var dayBirthday = birthDayDate.getDate();
//first just make the difference between years
var yearDifference = thisYear - yearBirthday;
//then check months
if (thisMonth == monthBirthday){
//if months are the same then check days
if (thisDay<dayBirthday){
//if today day is before birthday day
//then I have to remove 1 year
//(no birthday yet)
yearDifference = yearDifference -1;
}
//if not no action because year difference is ok
}
else {
if (thisMonth < monthBirthday) {
//if actual month is before birthday one
//then I have to remove 1 year
yearDifference = yearDifference -1;
}
//if not no action because year difference is ok
}
return yearDifference;
}
Bro, moment.js is awesome for this:
The diff method is what you want: http://momentjs.com/docs/#/displaying/difference/
The below function return array of years from the year to the current year.
const getYears = (from = 2017) => {
const diff = moment(new Date()).diff(new Date(`01/01/${from}`), 'years') ;
return [...Array(diff >= 0 ? diff + 1 : 0).keys()].map((num) => {
return from + num;
});
}
console.log(getYears(2016));
<script src="https://momentjs.com/downloads/moment.js"></script>
function dateDiffYearsOnly( dateNew,dateOld) {
function date2ymd(d){ w=new Date(d);return [w.getFullYear(),w.getMonth(),w.getDate()]}
function ymd2N(y){return (((y[0]<<4)+y[1])<<5)+y[2]} // or 60 and 60 // or 13 and 32 // or 25 and 40 //// with ...
function date2N(d){ return ymd2N(date2ymd(d))}
return (date2N(dateNew)-date2N(dateOld))>>9
}
test:
dateDiffYearsOnly(Date.now(),new Date(Date.now()-7*366*24*3600*1000));
dateDiffYearsOnly(Date.now(),new Date(Date.now()-7*365*24*3600*1000))
I went for the following very simple solution. It does not assume you were born in 1970 and it also takes into account the hour of the given birthday date.
function age(birthday) {
let now = new Date();
let year = now.getFullYear();
let years = year - birthday.getFullYear();
birthday = new Date(birthday.getTime()); // clone
birthday.setFullYear(year);
return now >= birthday ? years : years - 1;
}
This one Help you...
$("[id$=btnSubmit]").click(function () {
debugger
var SDate = $("[id$=txtStartDate]").val().split('-');
var Smonth = SDate[0];
var Sday = SDate[1];
var Syear = SDate[2];
// alert(Syear); alert(Sday); alert(Smonth);
var EDate = $("[id$=txtEndDate]").val().split('-');
var Emonth = EDate[0];
var Eday = EDate[1];
var Eyear = EDate[2];
var y = parseInt(Eyear) - parseInt(Syear);
var m, d;
if ((parseInt(Emonth) - parseInt(Smonth)) > 0) {
m = parseInt(Emonth) - parseInt(Smonth);
}
else {
m = parseInt(Emonth) + 12 - parseInt(Smonth);
y = y - 1;
}
if ((parseInt(Eday) - parseInt(Sday)) > 0) {
d = parseInt(Eday) - parseInt(Sday);
}
else {
d = parseInt(Eday) + 30 - parseInt(Sday);
m = m - 1;
}
// alert(y + " " + m + " " + d);
$("[id$=lblAge]").text("your age is " + y + "years " + m + "month " + d + "days");
return false;
});
if someone needs for interest calculation year in float format
function floatYearDiff(olddate, newdate) {
var new_y = newdate.getFullYear();
var old_y = olddate.getFullYear();
var diff_y = new_y - old_y;
var start_year = new Date(olddate);
var end_year = new Date(olddate);
start_year.setFullYear(new_y);
end_year.setFullYear(new_y+1);
if (start_year > newdate) {
start_year.setFullYear(new_y-1);
end_year.setFullYear(new_y);
diff_y--;
}
var diff = diff_y + (newdate - start_year)/(end_year - start_year);
return diff;
}
I Am trying to form a date which is 3 months before the current date. I get the current month by the below code
var currentDate = new Date();
var currentMonth = currentDate.getMonth()+1;
Can you guys provide me the logic to calculate and form a date (an object of the Date data type) considering that when the month is January (1), 3 months before date would be OCtober (10)?
var d = new Date();
d.setMonth(d.getMonth() - 3);
This works for January. Run this snippet:
var d = new Date("January 14, 2012");
console.log(d.toLocaleDateString());
d.setMonth(d.getMonth() - 3);
console.log(d.toLocaleDateString());
There are some caveats...
A month is a curious thing. How do you define 1 month? 30 days? Most people will say that one month ago means the same day of the month on the previous month citation needed. But more than half the time, that is 31 days ago, not 30. And if today is the 31st of the month (and it isn't August or Decemeber), that day of the month doesn't exist in the previous month.
Interestingly, Google agrees with JavaScript if you ask it what day is one month before another day:
It also says that one month is 30.4167 days long:
So, is one month before March 31st the same day as one month before March 28th, 3 days earlier? This all depends on what you mean by "one month before". Go have a conversation with your product owner.
If you want to do like momentjs does, and correct these last day of the month errors by moving to the last day of the month, you can do something like this:
const d = new Date("March 31, 2019");
console.log(d.toLocaleDateString());
const month = d.getMonth();
d.setMonth(d.getMonth() - 1);
while (d.getMonth() === month) {
d.setDate(d.getDate() - 1);
}
console.log(d.toLocaleDateString());
If your requirements are more complicated than that, use some math and write some code. You are a developer! You don't have to install a library! You don't have to copy and paste from stackoverflow! You can develop the code yourself to do precisely what you need!
I recommend using a library called Moment.js.
It is well tested, works cross browser and on server side(I am using it both in Angular and Node projects). It has great support for locale dates.
http://momentjs.com/
var threeMonthsAgo = moment().subtract(3, 'months');
console.log(threeMonthsAgo.format()); // 2015-10-13T09:37:35+02:00
.format() returns string representation of date formatted in ISO 8601 format. You can also use it with custom date format like this:.format('dddd, MMMM Do YYYY, h:mm:ss a')
A "one liner" (on many line for easy read)) to be put directly into a variable:
var oneMonthAgo = new Date(
new Date().getFullYear(),
new Date().getMonth() - 1,
new Date().getDate()
);
This should handle addition/subtraction, just put a negative value in to subtract and a positive value to add. This also solves the month crossover problem.
function monthAdd(date, month) {
var temp = date;
temp = new Date(date.getFullYear(), date.getMonth(), 1);
temp.setMonth(temp.getMonth() + (month + 1));
temp.setDate(temp.getDate() - 1);
if (date.getDate() < temp.getDate()) {
temp.setDate(date.getDate());
}
return temp;
}
To make things really simple you can use DateJS, a date library for JavaScript:
http://www.datejs.com/
Example code for you:
Date.today().add({ months: -1 });
If the setMonth method offered by gilly3 isn't what you're looking for, consider:
var someDate = new Date(); // add arguments as needed
someDate.setTime(someDate.getTime() - 3*28*24*60*60);
// assumes the definition of "one month" to be "four weeks".
Can be used for any amount of time, just set the right multiples.
I like the simplicity of gilly3's answer, but users will probably be surprised that a month before March 31 is March 3. I chose to implement a version that sticks to the end of the month, so a month before March 28, 29, 30, and 31 will all be Feb 28 when it's not a leap year.
function addMonths(date, months) {
var result = new Date(date),
expectedMonth = ((date.getMonth() + months) % 12 + 12) % 12;
result.setMonth(result.getMonth() + months);
if (result.getMonth() !== expectedMonth) {
result.setDate(0);
}
return result;
}
var dt2004_05_31 = new Date("2004-05-31 0:00"),
dt2001_05_31 = new Date("2001-05-31 0:00"),
dt2001_03_31 = new Date("2001-03-31 0:00"),
dt2001_02_28 = new Date("2001-02-28 0:00"),
result = addMonths(dt2001_05_31, -2);
console.assert(dt2001_03_31.getTime() == result.getTime(), result.toDateString());
result = addMonths(dt2001_05_31, -3);
console.assert(dt2001_02_28.getTime() == result.getTime(), result.toDateString());
result = addMonths(dt2001_05_31, 36);
console.assert(dt2004_05_31.getTime() == result.getTime(), result.toDateString());
result = addMonths(dt2004_05_31, -38);
console.assert(dt2001_03_31.getTime() == result.getTime(), result.toDateString());
console.log('Done.');
Do this
let currentdate = new Date();
let last3months = new Date(currentdate.setMonth(currentdate.getMonth()-3));
Javascript's setMonth method also takes care of the year. For instance, the above code will return 2020-01-29 if currentDate is set as new Date("2020-01-29")
For get date three monts prior to today :
let d = new Date(new Date().setMonth(new Date().getMonth() - 3))
console.log(d.toISOString().slice(0, 10))
// 2022-05-24 (today is 2022-08-24)
var d = new Date("2013/01/01");
console.log(d.toLocaleDateString());
d.setMonth(d.getMonth() + 18);
console.log(d.toLocaleDateString());
This is the Smallest and easiest code.
var minDate = new Date();
minDate.setMonth(minDate.getMonth() - 3);
Declare variable which has current date.
then just by using setMonth inbuilt function we can get 3 month back date.
There is an elegant answer already but I find that its hard to read so I made my own function. For my purposes I didn't need a negative result but it wouldn't be hard to modify.
var subtractMonths = function (date1,date2) {
if (date1-date2 <=0) {
return 0;
}
var monthCount = 0;
while (date1 > date2){
monthCount++;
date1.setMonth(date1.getMonth() -1);
}
return monthCount;
}
As I don't seem to see it already suggested....
const d = new Date();
const day = d.getDate();
const goBack = 3;
for (let i = 0; i < goBack; i++) d.setDate(0);
d.setDate(day);
This will give you the date of today's date 3 months ago as .setDate(0) sets the date to the last day of last month irrespective of how many days a month contains. day is used to restore today's date value.
var todayDate = new Date().toISOString().slice(0, 10);
var d = new Date(todayDate);
d.setMonth(d.getMonth() -3);
console.log(todayDate)
console.log(d.toISOString().slice(0, 10));
d.setMonth changed local time in browser try
const calcDate = (m) => {
let date = new Date();
let day = date.getDate();
let month = date.getMonth() + 1;
let year = date.getFullYear();
let days = 0;
if (m > 0) {
for (let i = 1; i < m; i++) {
month += 1;
if (month > 12) {
year += 1;
month = 1;
}
days += new Date(year, month, 0).getDate();
}
} else {
for (let i = m; i < 0; i++) {
month -= 1;
if (month < 1) {
year -= 1;
month = 12;
}
days -= new Date(year, month, 0).getDate();
}
}
const newTime = date.getTime() + 3600 * 24 * 1000 * days;
return new Date(newTime);
};
calcDate(3)//+3 month
Since "Feb 31th" is auto converted to "March 3" or "March 2", as a month before "March 31th", which is quite counterintuitive, I decided to do it just like how I do it in my mind.
Similar to #Don Kirkby 's answer, I also revise the date with the last day of the target month.
function nMonthsAgo(date, n) {
// get the target year, month, date
const y = date.getFullYear() - Math.trunc(n / 12)
const m = date.getMonth() - n % 12
let d = date.getDate()
if (d > 27) { // get a valid date
const lastDateofMonth = new Date(y, m + 1, 0).getDate()
d = Math.min(d, lastDateofMonth)
}
return new Date(y, m, d)
}
d = new Date('2022-03-31')
nMonthsAgo(d, 1).toLocaleDateString()
Finally, I love what #gilly3 said in his answer:
If your requirements are more complicated than that, use some math and write some code. You are a developer! You don't have to install a library! You don't have to copy and paste from stackoverflow! You can develop the code yourself to do precisely what you need!
for (let monthOfYear = 0; monthOfYear < 12; monthOfYear++) {
const maxDate = new Date();
const minDate = new Date();
const max = maxDate.setMonth(maxDate.getMonth() - (monthOfYear - 1), 0);
const min = maxDate.setMonth(minDate.getMonth() - (monthOfYear), 1);
console.log('max: ', new Date(max));
console.log('min: ', new Date(min));
}
In my case I needed to substract 1 month to current date. The important part was the month number, so it doesn't care in which day of the current month you are at, I needed last month. This is my code:
var dateObj = new Date('2017-03-30 00:00:00'); //Create new date object
console.log(dateObj); // Thu Mar 30 2017 00:00:00 GMT-0300 (ART)
dateObj.setDate(1); //Set first day of the month from current date
dateObj.setDate(-1); // Substract 1 day to the first day of the month
//Now, you are in the last month
console.log(dateObj); // Mon Feb 27 2017 00:00:00 GMT-0300 (ART)
Substract 1 month to actual date it's not accurate, that's why in first place I set first day of the month (first day of any month always is first day) and in second place I substract 1 day, which always send you to last month.
Hope to help you dude.
var dateObj = new Date('2017-03-30 00:00:00'); //Create new date object
console.log(dateObj); // Thu Mar 30 2017 00:00:00 GMT-0300 (ART)
dateObj.setDate(1); //Set first day of the month from current date
dateObj.setDate(-1); // Substract 1 day to the first day of the month
//Now, you are in the last month
console.log(dateObj); // Mon Feb 27 2017 00:00:00 GMT-0300 (ART)
var date=document.getElementById("date");
var d = new Date();
document.write(d + "<br/>");
d.setMonth(d.getMonth() - 6);
document.write(d);
if(d<date)
document.write("lesser then 6 months");
else
document.write("greater then 6 months");
Pass a JS Date object and an integer of how many months you want to add/subtract. monthsToAdd can be positive or negative. Returns a JS date object.
If your originalDateObject is March 31, and you pass -1 as monthsToAdd, then your output date will be February 28.
If you pass a large number of months, say 36, it will handle the year adjustment properly as well.
const addMonthsToDate = (originalDateObject, monthsToAdd) => {
const originalDay = originalDateObject.getUTCDate();
const originalMonth = originalDateObject.getUTCMonth();
const originalYear = originalDateObject.getUTCFullYear();
const monthDayCountMap = {
"0": 31,
"1": 28,
"2": 31,
"3": 30,
"4": 31,
"5": 30,
"6": 31,
"7": 31,
"8": 30,
"9": 31,
"10": 30,
"11": 31
};
let newMonth;
if (newMonth > -1) {
newMonth = (((originalMonth + monthsToAdd) % 12)).toString();
} else {
const delta = (monthsToAdd * -1) % 12;
newMonth = originalMonth - delta < 0 ? (12+originalMonth) - delta : originalMonth - delta;
}
let newDay;
if (originalDay > monthDayCountMap[newMonth]) {
newDay = monthDayCountMap[newMonth].toString();
} else {
newDay = originalDay.toString();
}
newMonth = (+newMonth + 1).toString();
if (newMonth.length === 1) {
newMonth = '0' + newMonth;
}
if (newDay.length === 1) {
newDay = '0' + newDay;
}
if (monthsToAdd <= 0) {
monthsToAdd -= 11;
}
let newYear = (~~((originalMonth + monthsToAdd) / 12)) + originalYear;
let newTime = originalDateObject.toISOString().slice(10, 24);
const newDateISOString = `${newYear}-${newMonth}-${newDay}${newTime}`;
return new Date(newDateISOString);
};
Following code give me Just Previous Month From Current Month even the date is 31/30 of current date and last month is 30/29/28 days:
<!DOCTYPE html>
<html>
<body>
<p>Click the button to display the date after changing the month.</p>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>
<script>
function myFunction() {
var d = new Date("March 29, 2017"); // Please Try the result also for "March 31, 2017" Or "March 30, 2017"
var OneMonthBefore =new Date(d);
OneMonthBefore.setMonth(d.getMonth(),0);
if(OneMonthBefore.getDate() < d.getDate() )
{
d.setMonth(d.getMonth(),0);
}else
{
d.setMonth(d.getMonth()-1);
}
document.getElementById("demo").innerHTML = d;
}
</script>
</body>
</html>
var d = new Date();
document.write(d + "<br/>");
d.setMonth(d.getMonth() - 6);
document.write(d);