Adding months to a date is harder than it sounds
Adding 7 days to a date is simple. You get a number, you add 7, done. Adding a month is a different problem entirely.
The trouble is that months have different lengths. January has 31 days. February has 28, sometimes 29. If you're on January 31 and you add one month, you land on February 31 — which doesn't exist.
Every calendar library, spreadsheet, and database has an opinion on what to do next.
What most tools do
The most common behavior is to snap to the last day of the target month. January 31 + 1 month = February 28 (or 29 in a leap year). March 31 + 1 month = April 30.
This is called end-of-month clamping and it's what Excel, Google Sheets, Python's dateutil, and most date libraries do by default.
It's sensible, but it creates a subtle problem: the operation isn't reversible. If you add one month to January 31, you get February 28. If you then subtract one month, you get January 28 — not January 31. You've lost three days.
The overflow approach
Some systems let the date overflow into the next month instead of clamping. January 31 + 1 month = March 3 (or March 2 in a leap year, since February has 29 days).
This preserves the total day count but the result lands in a completely different month than you intended. It's surprising and usually wrong from the user's perspective.
SQL's INTERVAL syntax in some databases does this depending on configuration. It's easy to get burned if you're not aware of which behavior you're working with.
Adding years has the same issue
February 29 exists only in leap years. Add one year to February 29, 2024, and you get February 29, 2025 — which doesn't exist. Clamping gives you February 28, 2025.
Same behavior, same tradeoffs.
When this actually causes bugs
Subscription billing is the classic example. A user signs up on January 31. Their next billing date is February 28. Then March 28. Then April 28. Every month after the first, they're billed 2-3 days earlier than they'd expect.
Recurring calendar events have the same issue. "Every month on the 31st" silently becomes "every month on the last day" for months that don't reach 31.
Loan repayment schedules, payroll dates, and anything with "monthly" recurrence all hit this edge case eventually.
Adding days doesn't have this problem
If you need to express "30 days from now" rather than "one month from now," just add 30 days. The result is unambiguous and reversible.
The distinction matters: a 30-day billing cycle and a monthly billing cycle are not the same thing, and they diverge quickly over time.
What to check in your tool or library
Before relying on date addition in any system, it's worth knowing:
- Does it clamp or overflow on month-end dates?
- Does it preserve the day-of-month across multiple additions, or re-clamp each time?
- For leap year edge cases, what happens on Feb 29 + 1 year?
The Date Calculator shows you the exact result for any date and offset — useful for sanity-checking before you commit to a calculation in code.