關於時間 PHP 處理包遇到的問題時間序列化差值問題

echo_dump發表於2020-06-18

關於時間PHP處理包遇到的問題

  1. 問題描述,最近在寫專案的時候,因為是一個多語言的專案,而且對於本地化時間也做了處理,再加上在宣傳頁面,不同的地方,做了不同格式的展示時間的
    處理,最重要一點,這是一個使用laravel開發的專案,安裝一個方便的時間處理包真的是太方便了,而且carbon還是這麼的強大。

  2. 後臺的使用者在釋出一個宣傳文章的時候,有時候會使用一個預釋出的功能,那麼前臺在預釋出的時間之後,就會顯示這個宣傳文章,現在的問題就是,比如
    我選擇一個早上八點之前的預釋出時間,那麼使用carbon處理時間之後,這個顯示的時間,會比預釋出的時間晚一天。如果選擇早上八點之後,最後格式話的
    時間就是正常的。

  3. 在配置檔案裡,app.php我配置的時區是 PRC,做本地化處理的時候,

//這個地方是根據站點的切換來動態切換
Carbon::setLocale('en');

$time1 = Carbon::parse(strtotime('2020-06-12 06:00:00'))->isoFormat('LL');
var_dump($time1);
$time2 = Carbon::parse(strtotime('2020-06-12 07:00:00'))->isoFormat('LL');
var_dump($time2);
$time3 = Carbon::parse(strtotime('2020-06-12 09:00:00'))->isoFormat('LL');
var_dump($time3);

//June 11, 2020
//June 11, 2020
//June 12, 2020
  1. 這個例子得到的處理之後的時間就是晚一天的,它會減去八個小時

  2. 如果是我這樣處理就不會有問題

//這個第二個引數就是動態切換的
$carbon = new Carbon('2020-08-06 06:00:00', 'en');
$carbon->isoFormat('LL');
//or
$time1 = Carbon::parse('2020-06-12 06:00:00')->isoFormat('LL');
var_dump($time1);
$time2 = Carbon::parse('2020-06-12 06:00:00')->isoFormat('LL');
var_dump($time2);
$time3 = Carbon::parse('2020-06-12 06:00:00')->isoFormat('LL');
var_dump($time3);

這個列印出來時間就是正常的,問題就是出在是否使用了php的自帶函式strtotime()。我如果傳一個時間戳過去,這個時候時間的轉換就會出現差錯,如果
傳一個時間戳,就會走到這一步:

public function __construct($time = null, $tz = null)
    {
        if (is_int($time)) {
            $time = "@$time";
        }

        $originalTz = $tz;

        // If the class has a test now set and we are trying to create a now()
        // instance then override as required
        $isNow = empty($time) || $time === 'now';

        if (method_exists(static::class, 'hasTestNow') &&
            method_exists(static::class, 'getTestNow') &&
            static::hasTestNow() &&
            ($isNow || static::hasRelativeKeywords($time))
        ) {
            static::mockConstructorParameters($time, $tz);
        }

        /** @var CarbonTimeZone $timezone */
        $timezone = $this->autoDetectTimeZone($tz, $originalTz);

        // Work-around for PHP bug https://bugs.php.net/bug.php?id=67127
        if (strpos((string) .1, '.') === false) {
            $locale = setlocale(LC_NUMERIC, '0');
            setlocale(LC_NUMERIC, 'C');
        }

        parent::__construct($time ?: 'now', $timezone);

        if (isset($locale)) {
            setlocale(LC_NUMERIC, $locale);
        }

        static::setLastErrors(parent::getLastErrors());
    }

這個__construct方法會繼承父類的__construct(),而它在傳遞給父類的時候,會檢測時間戳是否是一個int型別,如果是就會轉換為字串的型別
這個時候,父類DateTime::__construct DateTime在處理的時候,再格式話
輸出時間的時候,就會出現時間查。

  1. 總結,追了一圈才發現不是carbon的bug,同時也發現了這個問題,再下次使用時間戳的時候,需要注意,禁忌
本作品採用《CC 協議》,轉載必須註明作者和本文連結
LIYi ---- github地址

相關文章