I am having issues with Carbon and timezones when the timezone set by date_default_timezone_set()
differs from the timezone Carbon is using.
In the example below, I have a while loop that adds a month and reverts to the start of that month until the $end_date
is greater than $current_date
:
date_default_timezone_set('Australia/Brisbane');
$tz = new DateTimeZone('Australia/Brisbane');
$start_date = \Carbon\Carbon::instance(new DateTime('2019-03-01 00:00:00', $tz));
$end_date = \Carbon\Carbon::instance(new DateTime('2021-03-21 23:59:00', $tz));
$current_date = $start_date->copy();
while ($end_date->gte($current_date)) {
echo $current_date->toDateTimeString() . "
";
$current_date->addMonth()->startOfMonth();
}
As you can see the output is correct.
2019-03-01 00:00:00
2019-04-01 00:00:00
2019-05-01 00:00:00
2019-06-01 00:00:00
2019-07-01 00:00:00
2019-08-01 00:00:00
2019-09-01 00:00:00
2019-10-01 00:00:00
2019-11-01 00:00:00
2019-12-01 00:00:00
2020-01-01 00:00:00
As soon as I change the default timezone to UTC
I get an infinite loop. For the sake of this example, I've adjusted the code to stop after 10 loops:
date_default_timezone_set('UTC'); // <---- Changed to UTC
$tz = new DateTimeZone('Australia/Brisbane');
$start_date = \Carbon\Carbon::instance(new DateTime('2019-03-01 00:00:00', $tz));
$end_date = \Carbon\Carbon::instance(new DateTime('2021-03-21 23:59:00', $tz));
$current_date = $start_date->copy();
$x = 0;
while ($end_date->gte($current_date)) {
echo $current_date->toDateTimeString() . "
";
$current_date->addMonth()->startOfMonth();
$x++;
if ($x === 10)
break;
}
And here is the output.
2019-03-01 00:00:00
2019-03-01 00:00:00
2019-03-01 00:00:00
2019-03-01 00:00:00
2019-03-01 00:00:00
2019-03-01 00:00:00
2019-03-01 00:00:00
2019-03-01 00:00:00
2019-03-01 00:00:00
2019-03-01 00:00:00
My expectation is that because I am passing Australia/Brisbane
as the timezone for $start_date
and $end_date
there shouldn't be any issue here.
Finally, if I rebuild my code to use DateTime
instead of Carbon, I have no problem.
date_default_timezone_set('UTC');
$tz = new DateTimeZone('Australia/Brisbane');
$start_date = new DateTime('2019-03-01 00:00:00', $tz);
$end_date = new DateTime('2020-03-21 23:59:00', $tz);
$current_date = clone $start_date;
while ($current_date->getTimestamp() < $end_date->getTimestamp()) {
echo $current_date->format('Y-m-d H:i:s') . "
";
$current_date->add(new DateInterval('P1M'));
$current_date->modify('first day of this month');
}
Have I missed something vital to how Carbon handles timezones?