Adding months to a date: what happens to January 31
If the target month is too short, the date moves back to that month's last day. January 31, 2026 plus one month is February 28, 2026, and in a leap year it's February 29. Daycount works this way, and so do Python's dateutil library and the EDATE function in Microsoft's DAX formula language. JavaScript's built-in Date behaves differently, as shown further down.
Examples
| Start | Change | Result |
|---|---|---|
| Jan 31, 2026 | +1 month | Feb 28, 2026 |
| Jan 31, 2028 | +1 month | Feb 29, 2028 |
| Mar 31, 2026 | +1 month | Apr 30, 2026 |
| Aug 31, 2026 | +6 months | Feb 28, 2027 |
| Feb 29, 2028 | +12 months | Feb 28, 2029 |
| Mar 31, 2026 | −1 month | Feb 28, 2026 |
Days 1 to 28 exist in every month, so they never move.
Adding one month twice isn't adding two months
Once a date has been pulled back to the 28th, it stays there. January 31 plus one month is February 28, and February 28 plus one month is March 28. But January 31 plus two months is March 31. For anything that repeats monthly, like a bill, a subscription or a payment plan, work out each date from the original start date rather than from the previous due date.
| Payment | Jan 31, 2026 + n months | Previous date + 1 month |
|---|---|---|
| 1 | Feb 28 | Feb 28 |
| 2 | Mar 31 | Mar 28 |
| 3 | Apr 30 | Apr 28 |
| 4 | May 31 | May 28 |
| 5 | Jun 30 | Jun 28 |
Going backwards has the same catch. March 31 minus one month is February 28, and adding the month back gives March 28, not March 31.
One month isn't 30 days
Thirty days after January 31, 2026 is March 2. One month after it is February 28. When a contract says "30 days", put 30 in the Days field of the date calculator; when it says "one month", use the Months field. Mixing them up can move the date by up to two days.
Counting the months between two dates
The same rule decides how many months lie between two dates. Daycount treats a month as complete when the date reaches the same day of the month, or the last day of a shorter month. That makes January 28, 29, 30 and 31, 2026 all exactly one month before February 28, 2026. Exact age in years, months and days is counted the same way.
How other tools handle it
- Python (dateutil): its documentation says that if the result falls after the last day of the month, the last day is used, and shows January 31, 2003 plus one month as February 28, 2003.
- Power BI (DAX): Microsoft documents that
EDATE("2009-01-31", 1)returns February 28, 2009. - JavaScript:
setMonthon aDatecarries the extra days into the next month. Starting from January 31, 2026 and setting the month to February gives March 3, 2026. MDN's documentation shows the same effect, with January 31, 2016 becoming March 2, 2016.
When two systems disagree by a few days around the end of a month, this difference is the usual reason.
Add or subtract months from a date →