Issues (10)

src/DateTimeImmutable.php (5 issues)

1
<?php
2
3
namespace Gearbox\DateTime;
4
5
use DateTime as PhpDateTime;
6
use Exception as PhpException;
7
8
/**
9
 * Represents a specific moment in time and cannot be changed.
10
 */
11
class DateTimeImmutable implements DateTimeInterface
12
{
13
    const DATETIME_FOR_FILE_NAME    = 'Y-m-d_H-i-s';
14
    const GERMAN_DATETIME           = 'd.m.Y H:i:s';
15
    const GERMAN_DATE               = 'd.m.Y';
16
    const MYSQL_DATETIME            = 'Y-m-d H:i:s';
17
    const MYSQL_DATE                = 'Y-m-d';
18
19
    /** @var \DateTime */
20
    protected $phpDateTime = null;
21
22
23
24
    /**
25
     * May be called with any date string the php version of DateTime accepts
26
     * and additionally with a unix timestamp also.
27
     *
28
     * @param string $dateString Defaults to 'now'.
29
     */
30
    public function __construct($dateString = 'now')
31
    {
32
        try {
33
            $this->phpDateTime = new PhpDateTime($dateString);
34
        }
35
        catch (PhpException $exception) {
36
            // Suspect it is a unixtime that could not be parsed.
37
            $this->phpDateTime = new PhpDateTime();
38
            $this->phpDateTime->setTimestamp($dateString);
39
        }
40
    }
41
42
43
44
    public function __clone()
45
    {
46
        // Force a clone of phpDateTime, otherwise the cloned DateTime object
47
        // would point to the same phpDateTime instance.
48
        $this->phpDateTime = clone $this->phpDateTime;
49
    }
50
51
52
53
    /**
54
     * Returns numeric representation of a day, without leading zeros.
55
     *
56
     * @return integer
57
     */
58
    public function getDayAsNumber()
59
    {
60
        $day = $this->phpDateTime->format('j');
61
62
        return $day;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $day returns the type string which is incompatible with the documented return type integer.
Loading history...
63
    }
64
65
66
67
    /**
68
     * Returns instance of MonthImmutable
69
     *
70
     * @return \Gearbox\DateTime\MonthImmutable
71
     */
72
    public function getMonth()
73
    {
74
        $month = new MonthImmutable($this->phpDateTime->format('Y-m'));
75
76
        return $month;
77
    }
78
79
80
81
    /**
82
     * Returns numeric representation of a month, without leading zeros.
83
     *
84
     * @return integer
85
     */
86
    public function getMonthAsNumber()
87
    {
88
        $month = $this->phpDateTime->format('n');
89
90
        return $month;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $month returns the type string which is incompatible with the documented return type integer.
Loading history...
91
    }
92
93
94
95
    /**
96
     * Returns year with four digits
97
     *
98
     * @return integer
99
     */
100
    public function getYearAsNumber()
101
    {
102
        $year = $this->phpDateTime->format('Y');
103
104
        return $year;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $year returns the type string which is incompatible with the documented return type integer.
Loading history...
105
    }
106
107
108
109
    /**
110
     * @param integer $hours
111
     * @param integer $minutes
112
     * @param integer $seconds
113
     * @return \Gearbox\DateTime\DateTimeImmutable
114
     */
115
    public function setTime($hours, $minutes, $seconds = 0)
116
    {
117
        $phpDateTime = clone $this->phpDateTime;
118
        $phpDateTime->setTime($hours, $minutes, $seconds);
119
        $newDateTime = $this->createInstance($phpDateTime);
120
121
        return $newDateTime;
122
    }
123
124
125
126
    /**
127
     * Returns true if the DateTime object and the date to compare with represent the same date.
128
     *
129
     * @param \Gearbox\DateTime\DateTimeInterface $dateToCompareWith
130
     * @return boolean
131
     */
132
    public function equals(DateTimeInterface $dateToCompareWith)
133
    {
134
        $equals = $this->asUnixTimestamp() == $dateToCompareWith->asUnixTimestamp();
135
136
        return $equals;
137
    }
138
139
140
141
    /**
142
     * Returns true if the DateTime object is earlier than the date to compare with.
143
     *
144
     * @param \Gearbox\DateTime\DateTimeInterface $dateToCompareWith
145
     * @return boolean
146
     */
147
    public function isEarlier(DateTimeInterface $dateToCompareWith)
148
    {
149
        $isEarlier = $this->asUnixTimestamp() < $dateToCompareWith->asUnixTimestamp();
150
151
        return $isEarlier;
152
    }
153
154
155
156
    /**
157
     * Returns true if the DateTime object is later than the date to compare with.
158
     *
159
     * @param \Gearbox\DateTime\DateTimeInterface $dateToCompareWith
160
     * @return boolean
161
     */
162
    public function isLater(DateTimeInterface $dateToCompareWith)
163
    {
164
        $isLater = $this->asUnixTimestamp() > $dateToCompareWith->asUnixTimestamp();
165
166
        return $isLater;
167
    }
168
169
170
171
    /**
172
     * @param \Gearbox\DateTime\DateTimeInterface $dateToCompareWith
173
     * @return boolean
174
     */
175
    public function isLaterOrEquals(DateTimeInterface $dateToCompareWith)
176
    {
177
        $equals = ($this->isLater($dateToCompareWith) || $this->equals($dateToCompareWith));
178
179
        return $equals;
180
    }
181
182
183
184
    /**
185
     * @param \Gearbox\DateTime\DateTimeInterface $dateToCompareWith
186
     * @return boolean
187
     */
188
    public function isEarlierOrEquals(DateTimeInterface $dateToCompareWith)
189
    {
190
        $equals = ($this->isEarlier($dateToCompareWith) || $this->equals($dateToCompareWith));
191
192
        return $equals;
193
    }
194
195
196
197
    /**
198
     * @param \Gearbox\DateTime\DateTimeInterface $dateTimeToCompareWith
199
     * @return boolean
200
     */
201
    public function isSameMonth(DateTimeInterface $dateTimeToCompareWith)
202
    {
203
        $sameMonth = $this->getMonthAsNumber() == $dateTimeToCompareWith->getMonthAsNumber() && $this->getYearAsNumber() == $dateTimeToCompareWith->getYearAsNumber();
204
205
        return $sameMonth;
206
    }
207
208
209
210
    /**
211
     * @return boolean
212
     */
213
    public function isInThePast()
214
    {
215
        $isInThePast = $this->asUnixTimestamp() < time();
216
217
        return $isInThePast;
218
    }
219
220
221
222
    /**
223
     * @return boolean
224
     */
225
    public function isInTheFuture()
226
    {
227
        $isInTheFuture = $this->asUnixTimestamp() > time();
228
229
        return $isInTheFuture;
230
    }
231
232
233
234
    /**
235
     * @param \Gearbox\DateTime\DateIntervalInterface $interval
236
     * @return \Gearbox\DateTime\DateTimeImmutable
237
     */
238
    public function add(DateIntervalInterface $interval)
239
    {
240
        $phpDateTime = clone $this->phpDateTime;
241
        $phpDateTime->add($interval->getAsPhpDateInterval());
242
        $newDateTime = $this->createInstance($phpDateTime);
243
244
        return $newDateTime;
245
    }
246
247
248
249
    /**
250
     * @param integer $numberOfDays
251
     * @return \Gearbox\DateTime\DateTimeImmutable
252
     */
253
    public function addDays($numberOfDays)
254
    {
255
        $daysInterval = new DateInterval($numberOfDays . ' days');
256
        $newDateTime = $this->add($daysInterval);
257
258
        return $newDateTime;
259
    }
260
261
262
263
    /**
264
     * @param integer $numberOfMonths
265
     * @return \Gearbox\DateTime\DateTimeImmutable
266
     */
267
    public function addMonths($numberOfMonths)
268
    {
269
        $monthsInterval = new DateInterval($numberOfMonths . ' months');
270
        $newDateTime = $this->add($monthsInterval);
271
272
        return $newDateTime;
273
    }
274
275
276
277
    /**
278
     * @param \Gearbox\DateTime\DateTimeInterface $dateTime
279
     * @return \Gearbox\DateTime\DateIntervalInterface
280
     */
281
    public function diff(DateTimeInterface $dateTime)
282
    {
283
        $phpDateInterval = $this->phpDateTime->diff($dateTime->phpDateTime);
284
        $dateIntervalAsString = $phpDateInterval->format(DateIntervalInterface::FORMAT_ISO_8601);
285
        $interval = new DateInterval($dateIntervalAsString);
286
287
        return $interval;
288
    }
289
290
291
292
293
    /**
294
     * @param \Gearbox\DateTime\DateTimeInterface $dateTime
295
     * @return integer
296
     */
297
    public function diffInDays(DateTimeInterface $dateTime)
298
    {
299
        $phpDateInterval = $this->phpDateTime->diff($dateTime->phpDateTime);
300
        $dateIntervalInDays = $phpDateInterval->days;
301
302
        return $dateIntervalInDays;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $dateIntervalInDays also could return the type boolean which is incompatible with the documented return type integer.
Loading history...
303
    }
304
305
306
307
    /**
308
     * @param \Gearbox\DateTime\DateIntervalInterface $interval
309
     * @return \Gearbox\DateTime\DateTimeImmutable
310
     */
311
    public function sub(DateIntervalInterface $interval)
312
    {
313
        $phpDateTime = clone $this->phpDateTime;
314
        $phpDateTime->sub($interval->getAsPhpDateInterval());
315
        $newDateTime = $this->createInstance($phpDateTime);
316
317
        return $newDateTime;
318
    }
319
320
321
322
    /**
323
     * @param string $formatString
324
     * @return string
325
     */
326
    public function format($formatString)
327
    {
328
        return $this->phpDateTime->format($formatString);
329
    }
330
331
332
333
    /**
334
     * @return string 'Y-m-d H:i:s'
335
     */
336
    public function asMySqlDateTime()
337
    {
338
        return $this->phpDateTime->format(self::MYSQL_DATETIME);
339
    }
340
341
342
343
    /**
344
     * @return string 'Y-m-d'
345
     */
346
    public function asMySqlDate()
347
    {
348
        return $this->phpDateTime->format(self::MYSQL_DATE);
349
    }
350
351
352
353
    /**
354
     * @return string
355
     */
356
    public function asUnixTimestamp()
357
    {
358
        return $this->phpDateTime->format('U');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->phpDateTime->format('U') returns the type string which is incompatible with the return type mandated by Gearbox\DateTime\DateTim...face::asUnixTimestamp() of integer.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
359
    }
360
361
362
363
    /**
364
     * @return string 'd.m.Y'
365
     */
366
    public function asGermanDate()
367
    {
368
        return $this->phpDateTime->format(self::GERMAN_DATE);
369
    }
370
371
372
373
    /**
374
     * @return string 'd.m.Y H:i:s'
375
     */
376
    public function asGermanDateTime()
377
    {
378
        return $this->phpDateTime->format(self::GERMAN_DATETIME);
379
    }
380
381
382
383
    /**
384
     * @return string 'Y-m-d_H-i-s'
385
     */
386
    public function asDateTimeForFilename()
387
    {
388
        return $this->phpDateTime->format(self::DATETIME_FOR_FILE_NAME);
389
    }
390
391
392
393
    /**
394
     * @return string
395
     */
396
    public function __toString()
397
    {
398
        return $this->phpDateTime->format(self::GERMAN_DATETIME);
399
    }
400
401
402
403
    /**
404
     * @param $phpDateTime
405
     * @return \Gearbox\DateTime\DateTimeImmutable
406
     */
407
    private function createInstance($phpDateTime)
408
    {
409
        $newDateTime = new self($phpDateTime->format('Y-m-d H:i:s'));
410
411
        return $newDateTime;
412
    }
413
}
414