概要
以下のドキュメントに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()andjson_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;
});
jsonSerializeとjson_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で返すようにしても変わりませんでした。バグ??
週の初めと終わりの設定で例外が発生しなくなった
setWeekStartsAtandsetWeekEndsAtno 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
同じ月の判定
isSameMonthandisCurrentMonthnow returnsfalsefor same month in different year but you can passfalseas a second parameter ofisSameMonthor first parameter ofisCurrentMonthto 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,
dayOfYearstarted from0. In Carbon 2 it starts from1.
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,
nullwas considered as0when passed to add/sub method (such asaddDays(null),subMonths(null), etc.). In Carbon 2, it behaves the same as no parameters so default to1. Anyway, you're discouraged to passnullin 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,
$selfis no longer needed in mixins you should just use$thisinstead.- As PHP 7.1+ perfectly supports microseconds,
useMicrosecondsFallbackandisMicrosecondsFallbackEnabledare no longer needed and so have been removed.
このあたりまで確認しようとすると時間がかかりすぎるため気になる方はご自身で確認してみてください。