LoginSignup
9
3

More than 3 years have passed since last update.

[PHP]strtotime("- 1 month")はアカン[31日はテストが落ちる日]

Posted at

これはなに?

PHPでstrtotime("- 1 month")とかstrtotime("+ 1 month")とか書いちゃだめだよって話です。

今日は何の日でしょう?

今日は、弊社の自動テストが落ちた日です。
昨日は落ちなかったのに、いったいなぜ今日落ちてしまったのでしょう。

なぜ落ちた?

それは今日が31日だからです。

テストコードに現在時刻を使ったコードがありました。
ただし、現在時刻から+1ヶ月したり-1ヶ月したりして、相対的な日付でテストをしているので、
普段は時刻が変わることによる問題は起こっていませんでした。

しかし、今日初めて問題が発覚しました。
現在時刻から前月の月を取得する計算が31日だけおかしかったのです。

前月の計算の仕方(NGケース)

strtotime("- 1 month")

一見良さそうです。今から マイナス1ヶ月後の日付が取れそうです。

7/1なら6/1

7/20なら6/20

7/31なら7/1

( ゚д゚) ・・・
 
(つд⊂)ゴシゴシ
 
(;゚д゚) ・・・
 
(つд⊂)ゴシゴシゴシ
  _, ._
(;゚ Д゚) …!?

0ヶ月前やん!

strtotime("+ 1 month")

の場合でも問題が起こります。

8/31の1ヶ月後は
10/1になってしまします。
2ヶ月後ですね。

正しい書き方

strtotime('first day of previous month');
strtotime('first day of next month');

参考コード

間違った例

date('Y-m-d H:i:s', strtotime('+ 1 Month', strtotime('2020/08/31 00:00:01')))
=> "2020-10-01 00:00:01"
>>> date('Y-m-d H:i:s', strtotime('- 1 Month', strtotime('2020/07/31 00:00:01')))
=> "2020-07-01 00:00:01"

正しい例

>>> date('Y-m-d H:i:s', strtotime('first day of previous month', strtotime('2020/07/31 00:00:01')))
=> "2020-06-01 00:00:01"
>>>  date('Y-m-d H:i:s', strtotime('first day of next month', strtotime('2020/08/31 00:00:01')))
=> "2020-09-01 00:00:01"

参考

https://bugs.php.net/bug.php?id=44073
https://stackoverflow.com/questions/19727274/strtotime-bug-when-using-1-month-from-january

9
3
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
9
3