LoginSignup
0
0

More than 1 year has passed since last update.

Carbon 1と2での動作変更点

Posted at

概要

以下のドキュメントにCarbon 2への移行について記載がありますが、それぞれについてtinkerを利用して実際に動作を確認していきます。

検証に利用したバージョン

  • Carbon 1: 1.39.1
  • Carbon 2: 2.48.0

動作確認

デフォルトの日付

Default values (when parameters are omitted) for $month and $day in the ::create() method are now 1 (were values from current date in Carbon 1). And default values for $hour, $minute and $second are now 0, this goes for omitted values, but you still can pass explicitly null to get the current value from now (similar behavior as in Carbon 1).

Carbon 1

>>> Carbon::create()
=> Carbon\Carbon @1621653995 {#3168
     date: 2021-05-22 12:26:35.0 Asia/Tokyo (+09:00),
   }

現在日時が返されています。

Carbon 2

>>> Carbon::create()
=> Carbon\Carbon @-62167252739 {#4825
     date: 0000-01-01 00:00:00.0 Asia/Tokyo (+09:18),
   }

年と月のデフォルトが1になっていて、そのほかは0になっています。

\Carbon\Carbon::create(null, null, null, null, null, null)
=> Carbon\Carbon @1621655137 {#4827
     date: 2021-05-22 12:45:37.954871 Asia/Tokyo (+09:00),
   }

それぞれに null を渡すことで現在日時が利用されるようになっています。

マイクロ秒精度

Now you get microsecond precision everywhere, it also means 2 dates in the same second but not in the same microsecond are no longer equal.

どこでもマイクロ秒の精度が得られるようになり、秒まで同じでも2つの日付が等しくなくなったとあります。

比較すべきコードが思いつきませんでしたが、以下の結果は1と2で同じでした。

Carbon 1

>>> Carbon::now()->equalTo(Carbon::now())
=> false

Carbon 2

>>> Carbon::now()->equalTo(Carbon::now())
=> false

JSONシリアライズ

$date->jsonSerialize() and json_encode($date) no longer returns arrays but simple strings: "2017-06-27T13:14:15.000000Z". This allows to create dates from it easier in JavaScript. You still can get the previous behavior using:

Carbon::serializeUsing(function ($date) {
    return [
        'date' => $date->toDateTimeString(),
    ] + (array) $date->tz;
});

jsonSerializejson_encodeは配列を返さなくなり、文字列を返すようになったとのこと。しかし、serializeUsingで前のように返すことも可能とのこと。

Carbon 1

>>> // シリアライズ未設定
>>> $dt = Carbon::now()
=> Carbon\Carbon @1621739556 {#3179
     date: 2021-05-23 12:12:36.362641 Asia/Tokyo (+09:00),
   }
>>> $dt->jsonSerialize()
=> []
>>> json_encode($dt)
=> "[]"

>>> // シリアライズ設定
>>> Carbon::serializeUsing(function ($date) {
...     return [
...         'date' => $date->toDateTimeString(),
...     ] + (array) $date->tz;
... });
=> null
>>> $dt->jsonSerialize()
=> [
     "date" => "2021-05-23 10:39:51",
     "timezone_type" => 3,
     "timezone" => "Asia/Tokyo",
   ]
>>> json_encode($dt)
=> "{"date":"2021-05-23 10:43:54","timezone_type":3,"timezone":"Asia\/Tokyo"}"

serializeUsing をする前は空の配列が返ってきていますが、その後はserializeUsingで設定した内容が返ってきていることがわかります。

シリアライズ未設定時に空の配列が返るのが正しい動作なのかは不明です。

Carbon 2

>>> $dt = Carbon::now()
>>> // シリアライズ未設定
=> Carbon\Carbon @1621734690 {#4826
     date: 2021-05-23 10:51:30.734085 Asia/Tokyo (+09:00),
   }
>>> $dt->jsonSerialize()
=> "2021-05-23T01:51:30.734085Z"
>>> json_encode($dt)
=> ""2021-05-23T01:51:30.734085Z""

>>> // シリアライズ設定
>>> Carbon::serializeUsing(function ($date) {                                                                                             ...     return [
...         'date' => $date->toDateTimeString(),
...     ] + (array) $date->tz;
... });
});
=> null
>>> $dt->jsonSerialize()
=> [
     "date" => "2021-05-23 10:51:30",
     "timezone_type" => 3,
     "timezone" => "Asia/Tokyo",
   ]
>>> json_encode($dt)                                                                                                                     
=> "{"date":"2021-05-23 10:51:30","timezone_type":3,"timezone":"Asia\/Tokyo"}"

serializeUsing をする前は文字列が返ってきていますが、その後はserializeUsingで設定した内容が返ってきていることがわかります。

文字列フォーマット

$date->setToStringFormat() with a closure no longer return a format but a final string. So you can return any string and the following in Carbon 1:

Carbon::setToStringFormat(function ($date) {
    return $date->year === 1976 ?
        'jS \o\f F g:i:s a' :
        'jS \o\f F, Y g:i:s a';
});

would become in Carbon 2:

Carbon::setToStringFormat(function ($date) {
    return $date->formatLocalized($date->year === 1976 ?
        'jS \o\f F g:i:s a' :
        'jS \o\f F, Y g:i:s a'
    );
});

2では文字列フォーマットのクロージャではフォーマットではなく、最終的な文字列を返すようになったとのこと。ただし、2でもクロージャ内でフォーマットを指定することが可能とのこと。

Carbon 1

>>> Carbon::setToStringFormat(function ($date) {
...     return $date->year === 1976 ?
...         'jS \o\f F g:i:s a' :
...         'jS \o\f F, Y g:i:s a';
... });
=> null
>>> echo $dt
23rd of May, 2021 10:45:31 am

フォーマットをクロージャ内で指定することで文字列化時に指定したフォーマットが指定されています。

Carbon 2

>>> Carbon::setToStringFormat(function ($date) {
...     return $date->year === 1976 ?
...         'jS \o\f F g:i:s a' :
...         'jS \o\f F, Y g:i:s a';
... });
=> null
>>> echo $dt
jS \o\f F, Y g:i:s a
>>> Carbon::setToStringFormat(function ($date) {
...     return $date->formatLocalized($date->year === 1976 ?
...         'jS \o\f F g:i:s a' :
...         'jS \o\f F, Y g:i:s a'
...     );
... });
=> null
>>> echo $dt                                                                                                                             
jS \o\f F, Y g:i:s a

クロージャ内でformatLocalizedを返さないとフォーマット文字列がそのまま返ってきてるのはわかりますが、formatLocalizeで返すようにしても変わりませんでした。バグ??

週の初めと終わりの設定で例外が発生しなくなった

setWeekStartsAt and setWeekEndsAt no longer throw exceptions on values out of ranges, but they are also deprecated.

Carbon 1

>>> Carbon::setWeekStartsAt(7)
InvalidArgumentException with message 'Day of a week should be greater than or equal to 0 and less than or equal to 6.'

Carbon 2

>>> Carbon::setWeekStartsAt(7)
=> null

同じ月の判定

isSameMonth and isCurrentMonth now returns false for same month in different year but you can pass false as a second parameter of isSameMonth or first parameter of isCurrentMonth to compare ignoring the year.

同じ月でも年が違えばfalseを返すようになったとのこと。

Carbon 1

>>> $dt1 = Carbon::create(2021, 1, 1)
=> Carbon\Carbon @1609468118 {#3170
     date: 2021-01-01 11:28:38.0 Asia/Tokyo (+09:00),
   }
>>> $dt2 = Carbon::create(2020, 1, 1)
=> Carbon\Carbon @1577845721 {#3183
     date: 2020-01-01 11:28:41.0 Asia/Tokyo (+09:00),
   }
>>> $dt1->isSameMonth($dt2)
=> true

Carbon 2

>>> $dt1 = Carbon::create(2021, 1, 1)
=> Carbon\Carbon @1609426800 {#4827
     date: 2021-01-01 00:00:00.0 Asia/Tokyo (+09:00),
   }
>>> $dt2 = Carbon::create(2020, 1, 1)
=> Carbon\Carbon @1577804400 {#4837
     date: 2020-01-01 00:00:00.0 Asia/Tokyo (+09:00),
   }
>>> $dt1->isSameMonth($dt2)
=> false

CarbonIntervalが例外を投げるようになった

In Carbon 1, calls of an unknown method on CarbonInterval (ex: CarbonInterval::anything()) just returned null. In Carbon 2 they throw an exception.

Carbon 1

>>> CarbonInterval::anything()
=> null

Carbon 2

>>> CarbonInterval::anything()
Carbon\Exceptions\BadFluentConstructorException with message 'Unknown fluent constructor 'anything'.'

dayOfYearの数え方の変更

In Carbon 1, dayOfYear started from 0. In Carbon 2 it starts from 1.

Carbon 1

>>> $dt = Carbon::create(2021, 1, 1)
=> Carbon\Carbon @1609469811 {#3165
     date: 2021-01-01 11:56:51.0 Asia/Tokyo (+09:00),
   }
>>> $dt->dayOfYear()
BadMethodCallException with message 'Method dayOfYear does not exist.'

そんなメソッドはないと怒られてしまう。。。

Carbon 2

>>> $dt = Carbon::create(2021, 1, 1)
=> Carbon\Carbon @1609426800 {#4833
     date: 2021-01-01 00:00:00.0 Asia/Tokyo (+09:00),
   }
>>> $dt->dayOfYear()
=> 1

addDayなどにnullが渡されたときの動作の変更

In Carbon 1, null was considered as 0 when passed to add/sub method (such as addDays(null), subMonths(null), etc.). In Carbon 2, it behaves the same as no parameters so default to 1. Anyway, you're discouraged to pass null in such methods as it's ambiguous and the behavior for next major version is not guaranteed.

2ではnullが渡されたらデフォルトの動作になったとのこと。

Carbon 1

>>> $dt = Carbon::create(2021, 1, 1)
=> Carbon\Carbon @1609470044 {#3171
     date: 2021-01-01 12:00:44.0 Asia/Tokyo (+09:00),
   }
>>> $dt->addDay(null)
=> Carbon\Carbon @1609470044 {#3171
     date: 2021-01-01 12:00:44.0 Asia/Tokyo (+09:00),
   }

日付が変わっていません。

Carbon 2

>>> $dt = Carbon::create(2021, 1, 1)
=> Carbon\Carbon @1609426800 {#4833
     date: 2021-01-01 00:00:00.0 Asia/Tokyo (+09:00),
   }
>>> $dt->addDay(null)
=> Carbon\Carbon @1609513200 {#4833
     date: 2021-01-02 00:00:00.0 Asia/Tokyo (+09:00),
   }

日付が加算されています。

その他削除されたメソッドなど

  • ::compareYearWithMonth() and ::compareYearWithMonth() have been removed. Strict comparisons are now the default. And you can use the next parameter of isSame/isCurrent set to false to get month-only comparisons.
  • As we dropped PHP 5, $self is no longer needed in mixins you should just use $this instead.
  • As PHP 7.1+ perfectly supports microseconds, useMicrosecondsFallback and isMicrosecondsFallbackEnabled are no longer needed and so have been removed.

このあたりまで確認しようとすると時間がかかりすぎるため気になる方はご自身で確認してみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0