放課後アトリエといろ
時の為政者によって封印されてしまった幻の名作、放課後アトリエといろ第65535話が特別公開されました。
さあさっそく読むんだ。
そして本屋で単行本の1巻から4巻までを買い占めて編集部に再開のプレッシャーを掛けるんだ。
今から約10年前、私まだ高校生の時に漫画家デビューした作品『放課後アトリエといろ』は雑誌改変の都合などで打ち切りになったのですが
— 華々つぼみ@ちびちゅき!⑥巻 発売中 (@hanabana_h04) 2019年11月18日
今回skeb経由で画像の様なリクエストをいただきまして特別読み切りとして復活致しました。(続く→) pic.twitter.com/was8bZb49W
おあぁぁぁぁ(絶命)#放課後アトリエといろ pic.twitter.com/dxtbNpSR79
— ラナ・クアール (@rana_kualu) 2019年11月18日
作者が一番うれしいのはお褒めの言葉だいや手紙だみたいなのをたまに見るけど、本当に一番なのはコレじゃないんかね。
— ラナ・クアール (@rana_kualu) 2019年11月18日
いや知らんけど。 pic.twitter.com/ziExc4RC5M
あ、言いたいことはもう終わったので帰っていいですよ。
でもここで終わると不思議なことに何故か消されてしまうので、ここから下にはなんか適当におまけでも置いときます。
Bug #78827 Wrong timestamp
さて問題です。
以下の出力はどうなるでしょう。
$today = strtotime('last Wednesday');
var_dump(
(strtotime('last Wednesday') - $today) / 86400,
(strtotime('last Wednesday + 1 day') - $today) / 86400,
(strtotime('last Wednesday + 2 day') - $today) / 86400,
(strtotime('last Wednesday + 3 day') - $today) / 86400,
(strtotime('last Wednesday + 4 day') - $today) / 86400,
(strtotime('last Wednesday + 5 day') - $today) / 86400,
(strtotime('last Wednesday + 6 day') - $today) / 86400,
(strtotime('last Wednesday + 7 day') - $today) / 86400,
(strtotime('last Wednesday + 8 day') - $today) / 86400,
(strtotime('last Wednesday + 9 day') - $today) / 86400,
);
Expected result
まず$today
は"先週の水曜日、0時0分0秒"になります。
実行したのが木曜であれば昨日、金曜であれば一昨日、そして今日が水曜であれば7日前になります。
ではvar_dumpの行を見ていきましょう。
まずlast Wednesday
の行ですが、ここは同じ値を引いてるだけなので当然0になります。
次にlast Wednesday + 1 day
ですが、ここは"先週の水曜日から+1日、0時0分0秒"となります。
実行したのが木曜であれば今日、金曜であれば昨日のことで、そして今日が水曜であれば6日前になります。
単に1日ずらしただけなので、当然ながら$today
とのずれは必ず1日です。
ということで(strtotime('last Wednesday + 1 day') - $today) / 86400
の答えは、何曜日に実行したとしても必ず1です。
同じくlast Wednesday + 2 day
の答えは必ず2、last Wednesday + 3 day
の答えは必ず3、となります。
そんなかんじで続いていって、一番下のlast Wednesday + 9 day
の答えは必ず9です。
当然ですね。
Actual result
・水曜日以外にstrtotime('last Wednesday + 6 day')
を計算すると、6日後の値になる。
・水曜日以外にstrtotime('last Wednesday + 7 day')
を計算すると、7日後の値になる。
・水曜日にstrtotime('last Wednesday + 6 day')
を計算すると、6日後の値になる。
・水曜日にstrtotime('last Wednesday + 7 day')
を計算すると、14日後の値になる。
書式の曜日が実行した曜日と同じ場合のみ、7日以上の日を足すと何故か値がずれるというバグです。
あまり使わないような書き方をしたうえで、さらに特定の曜日にしか発生しないということで、万一これを踏んでしまったら原因の特定が非常に困難になりそうなバグですね。
あまり使わないというのはつまり、普通はlast Wednesday + 7 day
じゃなくてnext Wednesday
って書くでしょうということですが。
next Wednesday
このバグチケには載ってないのですが、実はnext
でも同じバグが起こります。
$today = strtotime('next Wednesday');
var_dump(
(strtotime('next Wednesday') - $today) / 86400,
(strtotime('next Wednesday - 1 day') - $today) / 86400,
(strtotime('next Wednesday - 2 day') - $today) / 86400,
(strtotime('next Wednesday - 3 day') - $today) / 86400,
(strtotime('next Wednesday - 4 day') - $today) / 86400,
(strtotime('next Wednesday - 5 day') - $today) / 86400,
(strtotime('next Wednesday - 6 day') - $today) / 86400,
(strtotime('next Wednesday - 7 day') - $today) / 86400,
(strtotime('next Wednesday - 8 day') - $today) / 86400,
(strtotime('next Wednesday - 9 day') - $today) / 86400,
);
水曜日以外に実行すると[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
ですが、水曜日に実行すると[0, -8, -9, -10, -11, -12, -13, -14, -15, -16]
になります。
こちらは-1
で起こるので、より深刻ですね。
Bug #78496 date_create rolls a day back on year 0000 timestamp
問題です。
以下の出力はどうなるでしょう。
$timestamp = strtotime('0000-02-20 00:00:00 UTC');
echo gmdate('Y-m-d H:i:s', $timestamp);
echo date_create('@' . $timestamp)->format('Y-m-d H:i:s');
Expected result
当然ですが、どちらも"0000-02-20 00:00:00"になりますよね。
Actual result
なんでだよ。
0年についてはdate_createが正しく計算されないというバグがあります。
西暦0年は存在しないとかいうツッコミが聞こえてきそうですが、ISO 8601では"0000"年は紀元前1年、"-0001"年は紀元前2年を表します。
めっちゃわかりにくい。
date_create
date_create関数のヘルプには『DateTime::__construct() のエイリアス』と書かれているのですが、これ嘘です。
var_dump(date_create('2020/01/32')); // false
var_dump(new DateTime('2020/01/32')); // Fatal error: Uncaught Exception: DateTime::__construct(): Failed to parse time string
書式が理解できない場合、date_create
はfalseを返しますがDateTime::__construct()
は例外を起こします。
Bug #78452 diff makes wrong in hour for Asia/Tehran
さて問題です。
以下の出力はどうなるでしょう。
date_default_timezone_set('Asia/Tokyo');
$date1 = new \DateTime('2019-11-05 11:00:00');
$date2 = new \DateTime('2019-11-01 12:00:00');
echo $date1->diff($date2)->format('%H');
date_default_timezone_set('America/New_York');
$date1 = new \DateTime('2019-11-05 11:00:00');
$date2 = new \DateTime('2019-11-01 12:00:00');
echo $date1->diff($date2)->format('%H');
Expected result
今回出力しているのは時間の差分なので、月が違うことは影響しません。
東京は当然ですがそのまま23ですね。
ニューヨークは夏時間切り替えを挟むのでどういう計算になるのかよくわからないのですが、時間差を求める場合は23でいいのですかね?
Actual result
夏時間の切り替えをまたぐと何故かマイナスになることがあります。
正解がどの値かはわかりませんが、少なくとも-1は明らかに間違いですね。
夏時間を考えてない勘違いバグ報告はわりとよくあるのですが、このチケットについては間違いなくバグです。
Bug #78504 Add warnings to DateTime object with incompatible timezone info
さて問題です。
以下の出力はどうなるでしょう。
$tz = new DateTimeZone('Asia/Tokyo');
$ts = strtotime('2020-01-1 00:00:00');
$dt1 = DateTime::CreateFromFormat("YmdHis", date('YmdHis', $ts), $tz);
$dt2 = DateTime::CreateFromFormat("U", date('U', $ts), $tz);
var_dump(
$dt1->format("Y-m-d H:i:s"),
$dt2->format("Y-m-d H:i:s"),
);
Expected result
当然、両方とも2020-01-01 00:00:00
ですね。
Actual result
前者は2020-01-01 00:00:00
、後者は2019-12-31 15:00:00
です。
なんでだよ。
実はパラメータをタイムスタンプで渡した場合、引数のタイムゾーンは無視されてUTC扱いされます。
これはマニュアルに書かれているのですが、あまりにわかりにくいですね。
従って、この挙動はPHP8か9あたりで変更になる可能性があります。
and
さて問題です。
以下の出力はどうなるでしょう。
$diff = DateInterval::createFromDateString('1 year and 2 months');
Expected result
1年2ヶ月差のDateIntervalオブジェクト。
Actual result
PHP7.2.17以降、そして7.3.4以降エラーになります。
ChangeLogには全く書かれていません。
おそらく50020のバグ修正と一緒に入り込んだものではないかと思いますが確証はありません。
何が問題かって単に'and'という文字列に対応してないということなので、'1 year 2 months'にすれば問題なく動作します。
元々対応してなかったのにたまたま動いていたというやつなので、使う方が悪いといえばそうなのですが、でもサイレントに挙動が変わるとびくっとなりますね。
まとめ
公開されたとか言ってたけど、続きが読みたくてどうしようもなくて我慢できなかったから描いてもらったんですけどね。
さあみんなもどんどん依頼するのだ。