duankang5882 2017-04-05 06:50
浏览 50
已采纳

碳时区问题

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?

  • 写回答

1条回答 默认 最新

  • douju5062 2017-04-05 11:27
    关注

    if you want to keep Carbon structure , you may use add function directly as follows :

    $x = 0;
    while ($end_date->gte($current_date)) {
       echo $current_date->toDateTimeString() . "
    ";
       $current_date->add(new \DateTimeinterval('P1M'))->startOfMonth();
       $x++;
       if ($x === 10)
           break;
    }
    

    Update

    The following method is the method that's addMonth method uses to increments the current date by one month

    /**
     * Consider the timezone when modifying the instance.
     *
     * @param string $modify
     *
     * @return static
     */
    public function modify($modify)
    {
        if ($this->local) {
            return parent::modify($modify);
        }
    
        $timezone = $this->getTimezone();
        $this->setTimezone('UTC');
        $instance = parent::modify($modify);
        $this->setTimezone($timezone);
    
        return $instance;
    }
    

    As you can see, this function reset so to speak the timezone to UTC before modifying your date then modify , and finally convert it into the given timezone -in this context it is a Australia/Brisbane-

    Actually It's not clear enough why Carbon authors resets the timezone to UTC in that function but this is the cause of your issue.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
  • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)