Our PHP TimeTraveler to address DateTime::modify() pitfalls
Everybody knows the PHP native method DateTime::modify()
The DateTime
extension supports awesome modifiers like "2 days ago", "last day of this month", ... or basic ones like "+1 month".
But the last one is actually tricky: it increments the month value of the date.
For instance 2023-01-01 (January first) becomes 2023-(01+1)-01 => 2023-02-01
But as not all months last 31 days: incrementing one month on 2023-08-31 results to 2023-09-31 which doesn't exist and is thus corrected to 2023-10-01.
If you keep playing, you will notice that modify('+1 year')
returns a different date than calling 12 times modify('+1 month')
🤯
(new DateTime('2023-01-31'))->modify('+1 year'); // 2024-01-31
(new DateTime('2023-01-31'))
->modify('+1 month') // 2023-03-03 which is the root cause
...
->modify('+1 month'); // 2024-02-03
At AssoConnect, we deal with monthly and yearly subscriptions, memberships, ... so we need reliable and predictable date operations.
The latest release of our https://github.com/assoconnect/php-date library brings a month & year traveler with 3 main features:
The last day of the month is sticky
September, 30th + 1 month = October, 31st instead of 30th
A month is never skipped
January, 30th + 1 month = February, 28th (or 29th) instead of March, 1st
February, 29th + 1 year = February, 28th instead of March, 1st
The year-over-year result is consistent with the initial reference
January, 30th + (1 month) x 12 = January, 30th instead of February, 2nd
We published this library under the MIT license so feel free to use it!
Subscribe to my newsletter
Read articles from Sylvain Fabre directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Sylvain Fabre
Sylvain Fabre
10+ years experience as CTO at AssoConnect. We are helping nonprofits change the world with an all-in-one software to save time on daily management.