0

How to create a function in javascript that will return a date 12 months one day ahead of current date? It should handle edge cases like if i select date as 2024-02-29 then it should return 2025-03-01. If i select date as 2024-07-31 then it should return 2025-08-01?

let currentDate = new Date();
let currentYear = currentDate.getFullYear();
let currentMonth = currentDate.getMonth();
let currentDateOfMonth = currentDate.getDate();


let targetMonth = currentMonth + 12;
let targetDate = currentDateOfMonth + 1;

if (targetMonth >= 12) {
  currentYear++;
  targetMonth -= 12;
}

let daysInTargetMonth = new Date(currentYear, targetMonth + 1, 0).getDate();


if (targetDate > daysInTargetMonth) {
  targetDate = targetDate - daysInTargetMonth;
  targetMonth++;
    if (targetMonth >= 12) {
    currentYear++;
    targetMonth -= 12;
  }
}

let targetDateObj = new Date(currentYear, targetMonth, 
targetDate);


console.log(targetDateObj.toLocaleDateString()); 

Tried the above code but when i pass the date as 2024-02-29 it returns me 3/2/2025 instead of 1/3/2025. What is wrong with the code?

  • Use the [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) methods and let javascript handle it for you. – freedomn-m Apr 19 '23 at 06:34
  • Some unneeded code: eg `+12` if `>12` - well it will always be >12 so just +1 to year instead. There's no need to handle edge cases around daysinmonth as the date constructor will do this for you. eg consider `console.log(new Date(2024, 05-1, 32))` for 32nd of May. – freedomn-m Apr 19 '23 at 06:40
  • *when i pass the date as 2024-02-29* - how exactly do you "pass in" this date? If you change the first line to `let currentDate = new Date(2024,01,29);` then +1 year is an invalid date, so javascript moves it to the next date. – freedomn-m Apr 19 '23 at 06:46
  • This is more of a concept/philosophy question than a coding issue. If you're on a leap day, then which day is +1 year? It can't be 2025-02-29 as that date doesn't exist - so is it 2025-02-28 (as you seem to be assuming) or is it 2025-03-01 as everyone else assumes. The solution appears to be: **add 1 day *then* add 1 year**, don't do both at once. This would give you 2024-03-01 then 2025-03-01, your expected date. – freedomn-m Apr 19 '23 at 06:47
  • Final code (taken from existing answers): `let date = new Date(2024,01,29); date.setDate(date.getDate() + 1); date.setFullYear(date.getFullYear() + 1); ` – freedomn-m Apr 19 '23 at 06:52
  • [Maybe helpfull](https://github.com/KooiInc/datefiddler) – KooiInc Apr 19 '23 at 07:19

1 Answers1

0

To answer your question, your code fails when the leap day is considered. This happens because of the line

let daysInTargetMonth = new Date(currentYear, targetMonth + 1, 0).getDate();

This line happens after the execution of the line

currentYear++;

So for input 2024-2-29, currentYear would've changed to 2025. And daysInTargetMonth would be calculated for Feb of 2025, which is 28 days. So when you calculate the targetDate, you get

targetDate = targetDate - 28

instead of,

targetDate = targetDate - 29

This is why you get one extra day when leap day is considered.

To fix this, you can add one additional condition in you if block

if (targetDate > daysInTargetMonth) {
        targetDate = targetDate - daysInTargetMonth;
        if(currentMonth==1 && currentDateOfMonth==29) {
                //Reduce one extra day for leap year
                targetDate--;
        }
        targetMonth++;
        if (targetMonth >= 12) {
            currentYear++;
            targetMonth -= 12;
        }
    }

This should fix the issue.

However, for a more optimized approach, you can use one of the referral links provided in comments.

To apply the same code for multiple years instead of 1:

Recalculate targetMonth based on the number of years

targetMonth = currentMonth + 12 * n;

The if condition has to be modified as follows:

targetYear = new Date(currentYear, targetMonth + 1, 0).getYear();
if(currentMonth==1 && currentDateOfMonth==29 && !((targetYear%100 !=0 && targetYear%4 == 0)|| targetYear %400 == 0)) {
                targetDate--;
        }
Saranya
  • 36
  • 4
  • This will work fine for +1day +1year - but if you use the same code for +1day +4years, it will give the wrong date. – freedomn-m Apr 22 '23 at 13:21
  • Yes, this would work for 1 year. If you're trying for n number of years, add a condition to check if the target year is leap year. The code that I've added must be executed only if the target year isn't leap year. – Saranya Apr 22 '23 at 17:51