回答編集履歴

1

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

2017/03/01 11:50

投稿

KiyoshiMotoki
KiyoshiMotoki

スコア4791

test CHANGED
@@ -11,3 +11,123 @@
11
11
  - ini_get('date.timezone') の戻り値
12
12
 
13
13
  - 実行環境の時刻が狂っていないか?
14
+
15
+
16
+
17
+ # 以下、コメント欄のやり取りを転載
18
+
19
+
20
+
21
+ ```php
22
+
23
+ // 1月前の日付を得る
24
+
25
+ $now = new DateTime();
26
+
27
+ $begin_date = $now;
28
+
29
+ $begin_date->sub(new DateInterval('P1M'));
30
+
31
+ echo $begin_date->format('Ymd');
32
+
33
+ // 1日前の日付を得る
34
+
35
+ $end_date = $now;
36
+
37
+ $end_date->sub(new DateInterval('P1D'));
38
+
39
+ echo $end_date->format('Ymd');
40
+
41
+ ```
42
+
43
+ 上のコードだと、変数`now`, `$begin_date`, `$end_date`が全て、同じ参照を指していることになります。
44
+
45
+ そのため、1つを変更すると、他の 2つの変数の値も変更される(ように見える)ことになります。
46
+
47
+ ```php
48
+
49
+ $now = new DateTime();
50
+
51
+ $begin_date = $now;
52
+
53
+ $begin_date->sub(new DateInterval('P1M'));
54
+
55
+ echo $begin_date->format('Ymd') . PHP_EOL;
56
+
57
+
58
+
59
+ echo PHP_EOL;
60
+
61
+
62
+
63
+ $end_date = $now;
64
+
65
+ $end_date->sub(new DateInterval('P1D'));
66
+
67
+ echo $end_date->format('Ymd') . PHP_EOL;
68
+
69
+
70
+
71
+ echo PHP_EOL;
72
+
73
+
74
+
75
+ echo $now->format('Ymd') . PHP_EOL;
76
+
77
+ echo $begin_date->format('Ymd') . PHP_EOL;
78
+
79
+ ```
80
+
81
+ 実行結果
82
+
83
+ ```
84
+
85
+ 20170201
86
+
87
+
88
+
89
+ 20170131
90
+
91
+
92
+
93
+ 20170131
94
+
95
+ 20170131
96
+
97
+ ```
98
+
99
+
100
+
101
+ ---
102
+
103
+ > $begin_dateと$end_dateに最初に直接 new DateTime()を突っ込んどけば混乱しなかったんですね。
104
+
105
+
106
+
107
+ ```php
108
+
109
+ $begin_date = new DateTime();
110
+
111
+ $end_date = new DateTime();
112
+
113
+ ```
114
+
115
+ ということでしょうか?
116
+
117
+
118
+
119
+ これだと、1行目を実行してから 2行目が実行されるまでの間に日付が変わると、結果が 1日ズレてしまいます。
120
+
121
+
122
+
123
+ 以下のように、clone キーワードを使用するのが良いと思います。
124
+
125
+ ```php
126
+
127
+ $begin_date = new DateTime();
128
+
129
+ $end_date = clone $begin_date;
130
+
131
+ ```
132
+
133
+ [http://php.net/manual/ja/language.oop5.cloning.php](http://php.net/manual/ja/language.oop5.cloning.php)