Completed
Push — master ( 7cd69f...11c5ca )
by ignace nyamagana
480:02 queued 467:25
created

functions.php ➔ month()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 3
nop 2
dl 0
loc 17
rs 9.3888
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * League.Period (https://period.thephpleague.com).
5
 *
6
 * @author  Ignace Nyamagana Butera <[email protected]>
7
 * @license https://github.com/thephpleague/period/blob/master/LICENSE (MIT License)
8
 * @version 4.0.0
9
 * @link    https://github.com/thephpleague/period
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
declare(strict_types=1);
16
17
namespace League\Period;
18
19
use DateInterval;
20
use DateTime;
21
use DateTimeImmutable;
22
use TypeError;
23
use const FILTER_VALIDATE_INT;
24
use function filter_var;
25
use function get_class;
26
use function gettype;
27
use function intdiv;
28
use function is_object;
29
use function is_string;
30
use function sprintf;
31
32
/**
33
 * Returns a DateTimeImmutable object.
34
 */
35
function datepoint($datepoint): DateTimeImmutable
36
{
37
    if ($datepoint instanceof DateTimeImmutable) {
38
        return $datepoint;
39
    }
40
41
    if ($datepoint instanceof DateTime) {
42
        return DateTimeImmutable::createFromMutable($datepoint);
43
    }
44
45
    if (false !== ($res = filter_var($datepoint, FILTER_VALIDATE_INT))) {
46
        return new DateTimeImmutable('@'.$res);
47
    }
48
49
    if (is_string($datepoint)) {
50
        return new DateTimeImmutable($datepoint);
51
    }
52
53
    throw new TypeError(sprintf(
0 ignored issues
show
Unused Code introduced by
The call to TypeError::__construct() has too many arguments starting with \sprintf('The datepoint ...: \gettype($datepoint)).

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
54
        'The datepoint must be expressed using an integer, a string or a DateTimeInterface object %s given',
55
        is_object($datepoint) ? get_class($datepoint) : gettype($datepoint)
56
    ));
57
}
58
59
/**
60
 * Returns a DateInval object.
61
 *
62
 * The duration can be
63
 * <ul>
64
 * <li>a DateInterval object</li>
65
 * <li>an Interval object</li>
66
 * <li>an int interpreted as the duration expressed in seconds.</li>
67
 * <li>a string in a format supported by DateInterval::createFromDateString</li>
68
 * </ul>
69
 */
70
function duration($duration): DateInterval
71
{
72
    if ($duration instanceof Period) {
73
        return $duration->getDateInterval();
74
    }
75
76
    if ($duration instanceof DateInterval) {
77
        return $duration;
78
    }
79
80
    if (false !== ($res = filter_var($duration, FILTER_VALIDATE_INT))) {
81
        return new DateInterval('PT'.$res.'S');
82
    }
83
84
    if (is_string($duration)) {
85
        return DateInterval::createFromDateString($duration);
86
    }
87
88
    throw new TypeError(sprintf(
0 ignored issues
show
Unused Code introduced by
The call to TypeError::__construct() has too many arguments starting with \sprintf('The duration m... : \gettype($duration)).

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
89
        'The duration must be expressed using an integer, a string or a DateInterval object %s given',
90
        is_object($duration) ? get_class($duration) : gettype($duration)
91
    ));
92
}
93
94
/**
95
 * Creates new instance from a starting point and an interval.
96
 */
97
function interval_after($startDate, $duration): Period
98
{
99
    $startDate = datepoint($startDate);
100
101
    return new Period($startDate, $startDate->add(duration($duration)));
102
}
103
104
/**
105
 * Creates new instance from a ending excluded datepoint and an interval.
106
 */
107
function interval_before($endDate, $duration): Period
108
{
109
    $endDate = datepoint($endDate);
110
111
    return new Period($endDate->sub(duration($duration)), $endDate);
112
}
113
114
/**
115
 * Creates new instance where the given duration is simultaneously
116
 * substracted from and added to the datepoint.
117
 */
118
function interval_around($datepoint, $duration): Period
119
{
120
    $datepoint = datepoint($datepoint);
121
    $duration = duration($duration);
122
123
    return new Period($datepoint->sub($duration), $datepoint->add($duration));
124
}
125
126
/**
127
 * Creates new instance for a specific year.
128
 *
129
 * @param mixed $int_or_datepoint a year as an int or a datepoint
130
 */
131
function year($int_or_datepoint): Period
132
{
133
    if (is_int($int_or_datepoint)) {
134
        $startDate = (new DateTimeImmutable())->setTime(0, 0)->setDate($int_or_datepoint, 1, 1);
135
136
        return new Period($startDate, $startDate->add(new DateInterval('P1Y')));
137
    }
138
139
    $datepoint = datepoint($int_or_datepoint);
140
    $startDate = $datepoint->setTime(0, 0)->setDate((int) $datepoint->format('Y'), 1, 1);
141
142
    return new Period($startDate, $startDate->add(new DateInterval('P1Y')));
143
}
144
145
/**
146
 * Creates new instance for a specific ISO year.
147
 *
148
 * @param mixed $int_or_datepoint a year as an int or a datepoint
149
 */
150
function iso_year($int_or_datepoint): Period
151
{
152
    if (is_int($int_or_datepoint)) {
153
        $datepoint = (new DateTimeImmutable())->setTime(0, 0);
154
155
        return new Period(
156
            $datepoint->setISODate($int_or_datepoint, 1),
157
            $datepoint->setISODate(++$int_or_datepoint, 1)
158
        );
159
    }
160
161
    $datepoint = datepoint($int_or_datepoint)->setTime(0, 0);
162
    $int_or_datepoint = (int) $datepoint->format('o');
163
164
    return new Period(
165
        $datepoint->setISODate($int_or_datepoint, 1),
166
        $datepoint->setISODate(++$int_or_datepoint, 1)
167
    );
168
}
169
170
/**
171
 * Creates new instance for a specific semester in a given year.
172
 *
173
 * @param mixed    $int_or_datepoint a year as an int or a datepoint
174
 * @param null|int $index            a semester index from 1 to 2 included
175
 */
176
function semester($int_or_datepoint, int $index = null): Period
177
{
178
    if (!is_int($int_or_datepoint)) {
179
        $datepoint = datepoint($int_or_datepoint);
180
        $startDate = $datepoint->setTime(0, 0)->setDate(
181
            (int) $datepoint->format('Y'),
182
            (intdiv((int) $datepoint->format('n'), 6) * 6) + 1,
183
            1
184
        );
185
186
        return new Period($startDate, $startDate->add(new DateInterval('P6M')));
187
    }
188
189
    if (null !== $index && 0 < $index && 2 >= $index) {
190
        $startDate = (new DateTimeImmutable())->setTime(0, 0)
191
            ->setDate($int_or_datepoint, (($index - 1) * 6) + 1, 1);
192
193
        return new Period($startDate, $startDate->add(new DateInterval('P6M')));
194
    }
195
196
    throw new Exception('The semester index is not contained within the valid range.');
197
}
198
199
/**
200
 * Creates new instance for a specific quarter in a given year.
201
 *
202
 * @param mixed    $int_or_datepoint a year as an int or a datepoint
203
 * @param null|int $index            quarter index from 1 to 4 included
204
 */
205
function quarter($int_or_datepoint, int $index = null): Period
206
{
207
    if (!is_int($int_or_datepoint)) {
208
        $datepoint = datepoint($int_or_datepoint)->setTime(0, 0);
209
        $startDate = $datepoint->setDate(
210
            (int) $datepoint->format('Y'),
211
            (intdiv((int) $datepoint->format('n'), 3) * 3) + 1,
212
            1
213
        );
214
215
        return new Period($startDate, $startDate->add(new DateInterval('P3M')));
216
    }
217
218
    if (null !== $index && 0 < $index && 4 >= $index) {
219
        $startDate = (new DateTimeImmutable())->setTime(0, 0)
220
            ->setDate($int_or_datepoint, (($index - 1) * 3) + 1, 1);
221
222
        return new Period($startDate, $startDate->add(new DateInterval('P3M')));
223
    }
224
225
    throw new Exception('The quarter index is not contained within the valid range.');
226
}
227
228
/**
229
 * Creates new instance for a specific year and month.
230
 *
231
 * @param mixed    $int_or_datepoint a year as an int or a datepoint
232
 * @param int|null $index            month index from 1 to 12 included
233
 */
234
function month($int_or_datepoint, int $index = null): Period
235
{
236
    if (!is_int($int_or_datepoint)) {
237
        $datepoint = datepoint($int_or_datepoint)->setTime(0, 0);
238
        $startDate = $datepoint->setDate((int) $datepoint->format('Y'), (int) $datepoint->format('n'), 1);
239
240
        return new Period($startDate, $startDate->add(new DateInterval('P1M')));
241
    }
242
243
    if (null !== $index && 0 < $index && 12 >= $index) {
244
        $startDate = (new DateTimeImmutable())->setTime(0, 0)->setDate($int_or_datepoint, $index, 1);
245
246
        return new Period($startDate, $startDate->add(new DateInterval('P1M')));
247
    }
248
249
    throw new Exception('The month index is not contained within the valid range.');
250
}
251
252
/**
253
 * Creates new instance for a specific ISO8601 week.
254
 *
255
 * @param mixed    $int_or_datepoint a year as an int or a datepoint
256
 * @param int|null $index            index from 1 to 53 included
257
 */
258
function iso_week($int_or_datepoint, int $index = null): Period
259
{
260
    if (!is_int($int_or_datepoint)) {
261
        $datepoint = datepoint($int_or_datepoint)->setTime(0, 0);
262
        $startDate = $datepoint->setISODate((int) $datepoint->format('o'), (int) $datepoint->format('W'), 1);
263
264
        return new Period($startDate, $startDate->add(new DateInterval('P7D')));
265
    }
266
267
    if (null !== $index && 0 < $index && 53 >= $index) {
268
        $startDate = (new DateTimeImmutable())->setTime(0, 0)->setISODate($int_or_datepoint, $index, 1);
269
270
        return new Period($startDate, $startDate->add(new DateInterval('P7D')));
271
    }
272
273
    throw new Exception('The week index is not contained within the valid range.');
274
}
275
276
/**
277
 * Creates new instance for a specific date.
278
 *
279
 * The date is truncated so that the time range starts at midnight
280
 * according to the date timezone and last a full day.
281
 */
282
function day($datepoint): Period
283
{
284
    $startDate = datepoint($datepoint)->setTime(0, 0);
285
286
    return new Period($startDate, $startDate->add(new DateInterval('P1D')));
287
}
288
289
/**
290
 * Creates new instance for a specific date and hour.
291
 *
292
 * The starting datepoint represents the beginning of the hour
293
 * The interval is equal to 1 hour
294
 */
295
function hour($datepoint): Period
296
{
297
    $datepoint = datepoint($datepoint);
298
    $startDate = $datepoint->setTime((int) $datepoint->format('H'), 0);
299
300
    return new Period($startDate, $startDate->add(new DateInterval('PT1H')));
301
}
302
303
/**
304
 * Creates new instance for a specific date, hour and minute.
305
 *
306
 * The starting datepoint represents the beginning of the minute
307
 * The interval is equal to 1 minute
308
 */
309
function minute($datepoint): Period
310
{
311
    $datepoint = datepoint($datepoint);
312
    $startDate = $datepoint->setTime((int) $datepoint->format('H'), (int) $datepoint->format('i'));
313
314
    return new Period($startDate, $startDate->add(new DateInterval('PT1M')));
315
}
316
317
/**
318
 * Creates new instance for a specific date, hour, minute and second.
319
 *
320
 * The starting datepoint represents the beginning of the second
321
 * The interval is equal to 1 second
322
 */
323
function second($datepoint): Period
324
{
325
    $datepoint = datepoint($datepoint);
326
    $startDate = $datepoint->setTime(
327
        (int) $datepoint->format('H'),
328
        (int) $datepoint->format('i'),
329
        (int) $datepoint->format('s')
330
    );
331
332
    return new Period($startDate, $startDate->add(new DateInterval('PT1S')));
333
}
334
335
/**
336
 * Creates new instance for a specific datepoint.
337
 */
338
function instant($datepoint): Period
339
{
340
    $datepoint = datepoint($datepoint);
341
342
    return new Period($datepoint, $datepoint);
343
}
344