Laravel - Carbon

# Introduction

學習一個框架, Ray 的想法是, 在深入理解底層實作的原理之前, 應該先知道這個框架的 使用方法; 先學習怎麼使用這個前人造的輪子, 再學習怎麼樣一個輪子。
所以本篇文章重點在於細讀官方文件, 並將內容理解後以 Q&A 的方式記錄下來, 加速學習以及查詢。



Laravel Carbon 是 extends 哪個 PHP class?

DateTime class

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $mutable = Carbon::now();
    $immutable = CarbonImmutable::now();
    $modifiedMutable = $mutable->add(1, 'day');
    $modifiedImmutable = CarbonImmutable::now()->add(1, 'day');

    var_dump($modifiedMutable === $mutable); // bool(true)
    var_dump($mutable->isoFormat('dddd D')); // string(12) "Wednesday 10"
    var_dump($modifiedMutable->isoFormat('dddd D')); // string(12) "Wednesday 10"

    var_dump($modifiedImmutable === $immutable); // bool(false)
    var_dump($immutable->isoFormat('dddd D')); // string(9) "Tuesday 9"
    var_dump($modifiedImmutable->isoFormat('dddd D')); // string(12) "Wednesday 10"

    $mutable = CarbonImmutable::now()->toMutable();
    var_dump($mutable->isMutable()); // bool(true)
    var_dump($mutable->isImmutable()); // bool(false)
    $immutable = Carbon::now()->toImmutable();
    var_dump($immutable->isMutable()); // bool(false)
    var_dump($immutable->isImmutable()); // bool(true)
  • Answer:
    Carbon::now() 所取得的 object 可被修改, 即同一個 object
    CarbonImmutable::now() 取得的 object 不可被修改, 每次取都是新的
    mutable 與 immutable 可互相轉換
以下的 Laravel example code, 意思相同嗎?
  • Example:
    <?php
    $time = Carbon::now;
    $time = new Carbon();
  • Answer:
    一樣
以下的 Laravel example code 的意思是?
  • Example:

    <?php
    $now = Carbon::now();

    $nowInLondonTz = Carbon::now(new DateTimeZone('Europe/London'));

    $nowInLondonTz = Carbon::now('Europe/London');
    echo $nowInLondonTz->tzName;
    echo "\n";

    $date = Carbon::now('+13:30');
    echo $date->tzName;
    echo "\n";

    echo $date->utcOffset();
    echo "\n";

    $date->utcOffset(180);

    echo $date->tzName;
    echo "\n";
    echo $date->utcOffset();
  • Answer:

    <?php
    $now = Carbon::now(); // 使用 default timezone
    // 建議使用 UTC, 然後透過轉換時區轉成使用者的時區

    $nowInLondonTz = Carbon::now(new DateTimeZone('Europe/London'));

    // 直接設定時區
    $nowInLondonTz = Carbon::now('Europe/London');
    echo $nowInLondonTz->tzName; // Europe/London
    echo "\n";

    // 直接帶入 offset 設定時區
    $date = Carbon::now('+13:30');
    echo $date->tzName; // +13:30
    echo "\n";

    // 取得距 UTC 的 offset (分鐘)
    echo $date->utcOffset(); // 810
    echo "\n";

    // 重設為距 UTC 180 分鐘
    $date->utcOffset(180);

    // timezone 變為距 UTC 180 分鐘, 即 3 小時
    echo $date->tzName; // +03:00
    echo "\n";
    echo $date->utcOffset(); // 180
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    echo (new Carbon('first day of December 2008'))->addWeeks(2);
    echo "\n";
    echo Carbon::parse('first day of December 2008')->addWeeks(2);
  • Answer:
    都是 // 2008-12-15 00:00:00, 使用 parse 少一個 bracket
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $string = 'first day of next month';
    if (strtotime($string) === false) {
    echo "'$string' is not a valid date/time string.";
    } elseif (Carbon::hasRelativeKeywords($string)) {
    echo "'$string' is a relative valid date/time string, it will returns different dates depending on the current date.";
    } else {
    echo "'$string' is an absolute date/time string, it will always returns the same date.";
    }
  • Answer:
    使用 hasRelativeKeywords() 來判斷帶入的 string 是否為 relative
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $now = Carbon::now();
    echo $now; // 2021-02-09 18:29:22
    echo "\n";
    $today = Carbon::today();
    echo $today; // 2021-02-09 00:00:00
    echo "\n";
    $tomorrow = Carbon::tomorrow('Europe/London');
    echo $tomorrow; // 2021-02-10 00:00:00
    echo "\n";
    $yesterday = Carbon::yesterday();
    echo $yesterday; // 2021-02-08 00:00:00

  • Answer:
    可使用 Carbon 的 today(), yesterday(), tomorrow() 取得相對應的日期, 也可帶入 timezone
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $year = 2000; $month = 4; $day = 19;
    $hour = 20; $minute = 30; $second = 15; $tz = 'Europe/Madrid';
    echo Carbon::createFromDate($year, $month, $day, $tz)."\n";
    echo Carbon::createMidnightDate($year, $month, $day, $tz)."\n";
    echo Carbon::createFromTime($hour, $minute, $second, $tz)."\n";
    echo Carbon::createFromTimeString("$hour:$minute:$second", $tz)."\n";
    echo Carbon::create($year, $month, $day, $hour, $minute, $second, $tz)."\n";
  • Answer:
    000-04-19 06:58:09
    2000-04-19 00:00:00
    2021-04-11 20:30:15
    2021-04-11 20:30:15
    2000-04-19 20:30:15
    createFromDate, 時間為預設
    createMidnightDate, 時間為 00:00:00
    createFromTime, 年月日為預設
    createFromTimeString, 年月日為預設
    create(), 帶 null 皆為預設
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    $xmasThisYear = Carbon::createFromDate(null, 12, 25);
    $Y2K = Carbon::create(2000, 1, 1, 0, 0, 0);
    $alsoY2K = Carbon::create(1999, 12, 31, 24);
    $noonLondonTz = Carbon::createFromTime(12, 0, 0, 'Europe/London');
    $teaTime = Carbon::createFromTimeString('17:00:00', 'Europe/London');

    try { Carbon::create(1975, 5, 21, 22, -2, 0); } catch(InvalidArgumentException $x) { echo $x->getMessage(); }
    // minute must be between 0 and 99, -2 given

    // Be careful, as Carbon::createFromDate() default values to current date, it can trigger overflow:
    // For example, if we are the 15th of June 2020, the following will set the date on 15:
    Carbon::createFromDate(2019, 4); // 2019-04-15
    // If we are the 31th of October, as 31th April does not exist, it overflows to May:
    Carbon::createFromDate(2019, 4); // 2019-05-01
    // That's why you simply should not use Carbon::createFromDate() with only 2 parameters (1 or 3 are safe, but no 2)
  • Answer:
    <?php
    $xmasThisYear = Carbon::createFromDate(null, 12, 25); // Year 為 default
    $Y2K = Carbon::create(2000, 1, 1, 0, 0, 0); // 等同 Carbon::createMidnightDate(2000, 1, 1)
    $alsoY2K = Carbon::create(1999, 12, 31, 24);
    $noonLondonTz = Carbon::createFromTime(12, 0, 0, 'Europe/London');
    $teaTime = Carbon::createFromTimeString('17:00:00', 'Europe/London');

    try { Carbon::create(1975, 5, 21, 22, -2, 0); } catch(InvalidArgumentException $x) { echo $x->getMessage(); }
    // minute 需為 0-99, 帶入 -2 會報錯, 若帶 99 為 22 時加上 99 分, 即 23:39

    // Be careful, as Carbon::createFromDate() default values to current date, it can trigger overflow:
    // For example, if we are the 15th of June 2020, the following will set the date on 15:
    Carbon::createFromDate(2019, 4); // 2019-04-15
    // If we are the 31th of October, as 31th April does not exist, it overflows to May:
    Carbon::createFromDate(2019, 4); // 2019-05-01
    // That's why you simply should not use Carbon::createFromDate() with only 2 parameters (1 or 3 are safe, but no 2)

# Additional

以下的 Laravel example code 的意思是?
  • Example:
    <?php
    echo Carbon::createFromFormat('Y-m-d H', '1975-05-21 22')->toDateTimeString();
  • Answer:
    // 1975-05-21 22:00:00
    使用 createFromFormat() 來自定義 format
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    echo Carbon::create(2000, 1, 35, 13, 0, 0);
    echo "\n";

    try {
    Carbon::createSafe(2000, 1, 35, 13, 0, 0);
    } catch (\Carbon\Exceptions\InvalidDateException $exp) {
    echo $exp->getMessage();
    }
  • Answer:
    // 2000-02-04 13:00:00
    // day : 35 is not a valid value.
    使用 createSafe() 來產生 Carbon exception
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    Carbon::parse($request->changed_at)->setTimezone(config('app.timezone'));
  • Answer:
    就算帶入的 string 本身已經是 ISO8601 格式, 如果不特別使用 setTimezone 或 toIso8601String 的話, 存入 MySQL 的 date 是不會根據當前的 timezone 去做轉換的, 也就是 Laravel 會無視 timezone 的部分, 直接將 datetime 的部分存入資料庫, 這樣就失去 ISO8601 註明 timezone 意義了
以下的 Laravel example code 的意思是?
  • Example:
    <?php
    public function test()
    {
    Carbon::setTestNow(Carbon::parse('January 1, 2020'))
    }
  • Answer:
    使用 setTestNow() 可以設定 Carbon 的當前時間
Laravel - Package - Octane Laravel - Testing - Database (官方文件原子化翻譯筆記)

留言

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×