Search code examples
phpdatestrtotimephp-7.4

strtotime miscalculates date when adding days that cross year


I need to add days to a date. I have been happily using the following and it's worked up until the end of the year:

date('o-m-d', strtotime("{$start_date} +6 days"));

As an example, when $start_date equals 2022-12-19, the result is 2022-12-25:

date('o-m-d', strtotime("2022-12-19 +6 days")); // 2022-12-25

This falls to pieces when the number of days lands on the first day of the year - so for 2022-12-26 the result is 2022-01-01 (2022, rather than 2023!)

date('o-m-d', strtotime("2022-12-26 +6 days")); // 2022-01-01, which is incorrect!

Playing around I found it's only if the date lands on the first day of the year - here are some examples:

date('o-m-d', strtotime("2022-12-30 +1 days")); // 2022-12-31, correct
date('o-m-d', strtotime("2022-12-30 +2 days")); // 2022-01-01, incorrect!
date('o-m-d', strtotime("2022-12-30 +3 days")); // 2023-01-02, correct

date('o-m-d', strtotime("2023-01-03 -1 days")); // 2023-01-02, correct
date('o-m-d', strtotime("2023-01-03 -2 days")); // 2022-01-01, incorrect!
date('o-m-d', strtotime("2023-01-03 -3 days")); // 2022-12-31, correct

I've seen when I include the h:m:s, I get a weird time of day, but that would surely impact all the date calculations. Anyone have an idea what's going on here? (I'm using [email protected])

I've tried all sorts of variations, like adding the base date as the second parameter to strtotime, even trying relative to today (-11 days at time of writing) and always the same error..

To be clear, adding two days to 2022-12-30 should result in 2023-01-01, not 2022-01-01.

I've looked through other answers to similar questions, such as using

$date = new \DateTime('2022-12-26');
$end_date = date_add($date, date_interval_create_from_date_string("6 days"))->format('o-m-d');

which results in exactly the same error.


Solution

  • Use Y for the year, not o. o is:

    ISO 8601 week-numbering year. This has the same value as Y, except that if the ISO week number (W) belongs to the previous or next year, that year is used instead.

    http://www.php.net/manual/en/datetime.format.php