JavaScript Date Overflow Edge Case
Today's date is 1/30/2025 (it's important to the story, I promise).
Today I was notified that one of the end-to-end UI tests for an app that I maintain was failing.
What does the test do?
For the sake of brevity, let's simplify things a bit and say this particular test case uses a date picker to choose a future date, submits a form and validates that the submitted date renders properly on the screen.
First, the test will navigate to the target page with our form.
Next, the test will fill out the date picker. Since we need a future date we:
- open the picker
- click the button to navigate to the next month
- click on the 10th of the month

Other than the fact that there is a 10th day of every month, the decision to use 10
was arbitrary. On this particular day, the test scenario is expected to save 02/10/2025.
The next step submits the form and waits for the server's successful response that everything was properly saved.
At this point, the application renders the form's submitted questions/answers on the screen. Now we want to assert that the date we selected is properly showing on the page.
This is the logic we use to get our expected date string:
const expectedDate = new Date();expectedDate.setMonth(expectedDate.getMonth() + 1);expectedDate.setDate(10);const expectedDateString = expectedDate.toLocaleDateString('en-US', {month: '2-digit',day: '2-digit',year: 'numeric',});
The test failure
When we assert that expectedDate
is in the DOM we get the following error.
expected '02/10/2025' to equal '03/10/2025'
So the DOM correctly renders 02/10/2025 but the test code is expecting a date that is a month later. How could this be?
Uncovering the solution
If you run the code step-by-step you see that the getMonth()
call returns 0
as expected since the number representation of a month in JS is 0-indexed.
console.log(expectedDate.getMonth()); // --> 0
So that's fine. Let's keep going and check the output of the following subset of code.
expectedDate.setMonth(expectedDate.getMonth() + 1);const expectedDateString = expectedDate.toLocaleDateString('en-US', {month: '2-digit',day: '2-digit',year: 'numeric',});console.log(expectedDateString); // --> '03/02/2025' 🤯
So why is this happening?
We are trying to increment the month by 1 on January 30th but there are only 28 days in February so February 30th does not exist. In this case, the JavaScript Date
overflows and sets the date to March 2nd (the next valid date).
Once I realized this, the fix was simple; just set the day before setting the month.
// broken on dates like 1/29/25, 1/30/25, etc.expectedDate.setMonth(expectedDate.getMonth() + 1);expectedDate.setDate(10);// fixedexpectedDate.setDate(10);expectedDate.setMonth(expectedDate.getMonth() + 1);
This way, we set 1/30/25 to 1/10/25 then set 1/10/25 to 2/10/25. Problem solved.