質問するログイン新規登録

回答編集履歴

1

コメント欄のやり取りを転載

2017/03/01 11:50

投稿

KiyoshiMotoki
KiyoshiMotoki

スコア4791

answer CHANGED
@@ -4,4 +4,64 @@
4
4
  `$end_date->sub()`の前後で`$end_date`を var_dump したり、
5
5
  以下の設定などを確認してみてください。
6
6
  - ini_get('date.timezone') の戻り値
7
- - 実行環境の時刻が狂っていないか?
7
+ - 実行環境の時刻が狂っていないか?
8
+
9
+ # 以下、コメント欄のやり取りを転載
10
+
11
+ ```php
12
+ // 1月前の日付を得る
13
+ $now = new DateTime();
14
+ $begin_date = $now;
15
+ $begin_date->sub(new DateInterval('P1M'));
16
+ echo $begin_date->format('Ymd');
17
+ // 1日前の日付を得る
18
+ $end_date = $now;
19
+ $end_date->sub(new DateInterval('P1D'));
20
+ echo $end_date->format('Ymd');
21
+ ```
22
+ 上のコードだと、変数`now`, `$begin_date`, `$end_date`が全て、同じ参照を指していることになります。
23
+ そのため、1つを変更すると、他の 2つの変数の値も変更される(ように見える)ことになります。
24
+ ```php
25
+ $now = new DateTime();
26
+ $begin_date = $now;
27
+ $begin_date->sub(new DateInterval('P1M'));
28
+ echo $begin_date->format('Ymd') . PHP_EOL;
29
+
30
+ echo PHP_EOL;
31
+
32
+ $end_date = $now;
33
+ $end_date->sub(new DateInterval('P1D'));
34
+ echo $end_date->format('Ymd') . PHP_EOL;
35
+
36
+ echo PHP_EOL;
37
+
38
+ echo $now->format('Ymd') . PHP_EOL;
39
+ echo $begin_date->format('Ymd') . PHP_EOL;
40
+ ```
41
+ 実行結果
42
+ ```
43
+ 20170201
44
+
45
+ 20170131
46
+
47
+ 20170131
48
+ 20170131
49
+ ```
50
+
51
+ ---
52
+ > $begin_dateと$end_dateに最初に直接 new DateTime()を突っ込んどけば混乱しなかったんですね。
53
+
54
+ ```php
55
+ $begin_date = new DateTime();
56
+ $end_date = new DateTime();
57
+ ```
58
+ ということでしょうか?
59
+
60
+ これだと、1行目を実行してから 2行目が実行されるまでの間に日付が変わると、結果が 1日ズレてしまいます。
61
+
62
+ 以下のように、clone キーワードを使用するのが良いと思います。
63
+ ```php
64
+ $begin_date = new DateTime();
65
+ $end_date = clone $begin_date;
66
+ ```
67
+ [http://php.net/manual/ja/language.oop5.cloning.php](http://php.net/manual/ja/language.oop5.cloning.php)