Completed
Push — master ( 43b902...6d8c91 )
by ignace nyamagana
12:37
created

day()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 3
dl 0
loc 11
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * League.Period (https://period.thephpleague.com).
5
 *
6
 * (c) Ignace Nyamagana Butera <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace League\Period;
15
16
use DateInterval;
17
use DatePeriod;
18
use DateTime;
19
use DateTimeImmutable;
20
use DateTimeInterface;
21
use TypeError;
22
use function filter_var;
23
use function get_class;
24
use function gettype;
25
use function intdiv;
26
use function is_int;
27
use function is_object;
28
use function is_string;
29
use function sprintf;
30
use const FILTER_VALIDATE_INT;
31
32
/**
33
 * Returns a DateTimeImmutable object.
34
 *
35
 * A datepoint can be
36
 * <ul>
37
 * <li>a DateTimeInterface object
38
 * <li>a integer interpreted as a timestamp
39
 * <li>a string parsable by DateTime::__construct
40
 * </ul>
41
 */
42
function datepoint($datepoint): DateTimeImmutable
43
{
44
    if ($datepoint instanceof DateTimeImmutable) {
45
        return $datepoint;
46
    }
47
48
    if ($datepoint instanceof DateTime) {
49
        return DateTimeImmutable::createFromMutable($datepoint);
50
    }
51
52
    if (false !== ($timestamp = filter_var($datepoint, FILTER_VALIDATE_INT))) {
53
        return new DateTimeImmutable('@'.$timestamp);
54
    }
55
56
    if (is_string($datepoint)) {
57
        return new DateTimeImmutable($datepoint);
58
    }
59
60
    throw new TypeError(sprintf(
61
        'The datepoint must be expressed using an integer, a string or a DateTimeInterface object %s given',
62
        is_object($datepoint) ? get_class($datepoint) : gettype($datepoint)
63
    ));
64
}
65
66
/**
67
 * Returns a DateInval object.
68
 *
69
 * The duration can be
70
 * <ul>
71
 * <li>an Period object</li>
72
 * <li>a DateInterval object</li>
73
 * <li>an integer interpreted as the duration expressed in seconds.</li>
74
 * <li>a string parsable by DateInterval::createFromDateString</li>
75
 * </ul>
76
 */
77
function duration($duration): DateInterval
78
{
79
    if ($duration instanceof Period) {
80
        return $duration->getDateInterval();
81
    }
82
83
    if ($duration instanceof DateInterval) {
84
        return $duration;
85
    }
86
87
    if (false !== ($second = filter_var($duration, FILTER_VALIDATE_INT))) {
88
        return new DateInterval('PT'.$second.'S');
89
    }
90
91
    if (is_string($duration)) {
92
        return DateInterval::createFromDateString($duration);
93
    }
94
95
    throw new TypeError(sprintf(
96
        'The duration must be expressed using an integer, a string, a DateInterval or a Period object %s given',
97
        is_object($duration) ? get_class($duration) : gettype($duration)
98
    ));
99
}
100
101
/**
102
 * Creates new instance from a starting point and an interval.
103
 */
104
function interval_after($datepoint, $duration): Period
105
{
106
    $datepoint = datepoint($datepoint);
107
    $duration = duration($duration);
108
109
    return new Period($datepoint, $datepoint->add($duration));
110
}
111
112
/**
113
 * Creates new instance from a ending excluded datepoint and an interval.
114
 */
115
function interval_before($datepoint, $duration): Period
116
{
117
    $datepoint = datepoint($datepoint);
118
    $duration = duration($duration);
119
120
    return new Period($datepoint->sub($duration), $datepoint);
121
}
122
123
/**
124
 * Creates new instance where the given duration is simultaneously
125
 * substracted from and added to the datepoint.
126
 */
127
function interval_around($datepoint, $duration): Period
128
{
129
    $datepoint = datepoint($datepoint);
130
    $duration = duration($duration);
131
132
    return new Period($datepoint->sub($duration), $datepoint->add($duration));
133
}
134
135
/**
136
 * Creates new instance from a DatePeriod.
137
 */
138
function interval_from_dateperiod(DatePeriod $datePeriod): Period
139
{
140
    return new Period($datePeriod->getStartDate(), $datePeriod->getEndDate());
141
}
142
143
/**
144
 * Creates new instance for a specific year.
145
 *
146
 * @param mixed $year_or_datepoint a year as an int or a datepoint
147
 */
148
function year($year_or_datepoint): Period
149
{
150
    if (is_int($year_or_datepoint)) {
151
        $startDate = (new DateTimeImmutable())->setDate($year_or_datepoint, 1, 1)->setTime(0, 0);
152
153
        return new Period($startDate, $startDate->add(new DateInterval('P1Y')));
154
    }
155
156
    $datepoint = datepoint($year_or_datepoint);
157
    $startDate = $datepoint->setDate((int) $datepoint->format('Y'), 1, 1)->setTime(0, 0);
158
159
    return new Period($startDate, $startDate->add(new DateInterval('P1Y')));
160
}
161
162
/**
163
 * Creates new instance for a specific ISO year.
164
 *
165
 * @param mixed $year_or_datepoint an iso year as an int or a datepoint
166
 */
167
function iso_year($year_or_datepoint): Period
168
{
169
    if (is_int($year_or_datepoint)) {
170
        return new Period(
171
            (new DateTimeImmutable())->setISODate($year_or_datepoint, 1)->setTime(0, 0),
172
            (new DateTimeImmutable())->setISODate(++$year_or_datepoint, 1)->setTime(0, 0)
173
        );
174
    }
175
176
    $datepoint = datepoint($year_or_datepoint)->setTime(0, 0);
177
    $iso_year = (int) $datepoint->format('o');
178
179
    return new Period($datepoint->setISODate($iso_year, 1), $datepoint->setISODate(++$iso_year, 1));
180
}
181
182
/**
183
 * Creates new instance for a specific semester in a given year.
184
 *
185
 * @param mixed $year_or_datepoint a year as an int or a datepoint
186
 */
187
function semester($year_or_datepoint, int $semester = 1): Period
188
{
189
    if (is_int($year_or_datepoint)) {
190
        $month = (($semester - 1) * 6) + 1;
191
        $startDate = (new DateTimeImmutable())->setDate($year_or_datepoint, $month, 1)->setTime(0, 0);
192
193
        return new Period($startDate, $startDate->add(new DateInterval('P6M')));
194
    }
195
196
    $datepoint = datepoint($year_or_datepoint);
197
    $year = (int) $datepoint->format('Y');
198
    $month = (intdiv((int) $datepoint->format('n'), 6) * 6) + 1;
199
    $startDate = $datepoint->setDate($year, $month, 1)->setTime(0, 0);
200
201
    return new Period($startDate, $startDate->add(new DateInterval('P6M')));
202
}
203
204
/**
205
 * Creates new instance for a specific quarter in a given year.
206
 *
207
 * @param mixed $year_or_datepoint an iso year as an int or a datepoint
208
 */
209
function quarter($year_or_datepoint, int $quarter = 1): Period
210
{
211
    if (is_int($year_or_datepoint)) {
212
        $month = (($quarter - 1) * 3) + 1;
213
        $startDate = (new DateTimeImmutable())->setDate($year_or_datepoint, $month, 1)->setTime(0, 0);
214
215
        return new Period($startDate, $startDate->add(new DateInterval('P3M')));
216
    }
217
218
    $datepoint = datepoint($year_or_datepoint);
219
    $year = (int) $datepoint->format('Y');
220
    $month = (intdiv((int) $datepoint->format('n'), 3) * 3) + 1;
221
    $startDate = $datepoint->setDate($year, $month, 1)->setTime(0, 0);
222
223
    return new Period($startDate, $startDate->add(new DateInterval('P3M')));
224
}
225
226
/**
227
 * Creates new instance for a specific year and month.
228
 *
229
 * @param mixed $year_or_datepoint a year as an int or a datepoint
230
 */
231
function month($year_or_datepoint, int $month = 1): Period
232
{
233
    if (is_int($year_or_datepoint)) {
234
        $startDate = (new DateTimeImmutable())->setDate($year_or_datepoint, $month, 1)->setTime(0, 0);
235
236
        return new Period($startDate, $startDate->add(new DateInterval('P1M')));
237
    }
238
239
    $datepoint = datepoint($year_or_datepoint);
240
    $startDate = $datepoint
241
        ->setDate((int) $datepoint->format('Y'), (int) $datepoint->format('n'), 1)
242
        ->setTime(0, 0);
243
244
    return new Period($startDate, $startDate->add(new DateInterval('P1M')));
245
}
246
247
/**
248
 * Creates new instance for a specific ISO8601 week.
249
 *
250
 * @param mixed $year_or_datepoint an iso year as an int or a datepoint
251
 */
252
function iso_week($year_or_datepoint, int $week = 1): Period
253
{
254
    if (is_int($year_or_datepoint)) {
255
        $startDate = (new DateTimeImmutable())->setISODate($year_or_datepoint, $week, 1)->setTime(0, 0);
256
257
        return new Period($startDate, $startDate->add(new DateInterval('P7D')));
258
    }
259
260
    $datepoint = datepoint($year_or_datepoint)->setTime(0, 0);
261
    $startDate = $datepoint->setISODate((int) $datepoint->format('o'), (int) $datepoint->format('W'), 1);
262
263
    return new Period($startDate, $startDate->add(new DateInterval('P7D')));
264
}
265
266
/**
267
 * Creates new instance for a specific date.
268
 *
269
 * The date is truncated so that the time range starts at midnight
270
 * according to the date timezone and last a full day.
271
 *
272
 * @param mixed $year_or_datepoint a year as an int or a datepoint
273
 */
274
function day($year_or_datepoint, int $month = 1, int $day = 1): Period
275
{
276
    if (is_int($year_or_datepoint)) {
277
        $startDate = (new DateTimeImmutable())->setDate($year_or_datepoint, $month, $day)->setTime(0, 0);
278
279
        return new Period($startDate, $startDate->add(new DateInterval('P1D')));
280
    }
281
282
    $startDate = datepoint($year_or_datepoint)->setTime(0, 0);
283
284
    return new Period($startDate, $startDate->add(new DateInterval('P1D')));
285
}
286
287
/**
288
 * Creates new instance for a specific date and hour.
289
 *
290
 * The starting datepoint represents the beginning of the hour
291
 * The interval is equal to 1 hour
292
 *
293
 * @param mixed $year_or_datepoint a year as an int or a datepoint
294
 */
295
function hour($year_or_datepoint, int $month = 1, int $day = 1, int $hour = 0): Period
296
{
297
    if (is_int($year_or_datepoint)) {
298
        $startDate = (new DateTimeImmutable())->setDate($year_or_datepoint, $month, $day)->setTime($hour, 0);
299
300
        return new Period($startDate, $startDate->add(new DateInterval('PT1H')));
301
    }
302
303
    $datepoint = datepoint($year_or_datepoint);
304
    $startDate = $datepoint->setTime((int) $datepoint->format('H'), 0);
305
306
    return new Period($startDate, $startDate->add(new DateInterval('PT1H')));
307
}
308
309
/**
310
 * Creates new instance for a specific date, hour and minute.
311
 *
312
 * The starting datepoint represents the beginning of the minute
313
 * The interval is equal to 1 minute
314
 *
315
 * @param mixed $year_or_datepoint a year as an int or a datepoint
316
 */
317
function minute($year_or_datepoint, int $month = 1, int $day = 1, int $hour = 0, int $minute = 0): Period
318
{
319
    if (is_int($year_or_datepoint)) {
320
        $startDate = (new DateTimeImmutable())->setDate($year_or_datepoint, $month, $day)->setTime($hour, $minute);
321
322
        return new Period($startDate, $startDate->add(new DateInterval('PT1M')));
323
    }
324
325
    $datepoint = datepoint($year_or_datepoint);
326
    $startDate = $datepoint->setTime((int) $datepoint->format('H'), (int) $datepoint->format('i'));
327
328
    return new Period($startDate, $startDate->add(new DateInterval('PT1M')));
329
}
330
331
/**
332
 * Creates new instance for a specific date, hour, minute and second.
333
 *
334
 * The starting datepoint represents the beginning of the second
335
 * The interval is equal to 1 second
336
 *
337
 * @param mixed $year_or_datepoint a year as an int or a datepoint
338
 */
339
function second(
340
    $year_or_datepoint,
341
    int $month = 1,
342
    int $day = 1,
343
    int $hour = 0,
344
    int $minute = 0,
345
    int $second = 0
346
): Period {
347
    if (is_int($year_or_datepoint)) {
348
        $startDate = (new DateTimeImmutable())
349
            ->setDate($year_or_datepoint, $month, $day)
350
            ->setTime($hour, $minute, $second);
351
352
        return new Period($startDate, $startDate->add(new DateInterval('PT1S')));
353
    }
354
355
    $datepoint = datepoint($year_or_datepoint);
356
    $startDate = $datepoint->setTime(
357
        (int) $datepoint->format('H'),
358
        (int) $datepoint->format('i'),
359
        (int) $datepoint->format('s')
360
    );
361
362
    return new Period($startDate, $startDate->add(new DateInterval('PT1S')));
363
}
364
365
/**
366
 * Creates new instance for a specific datepoint.
367
 *
368
 * @param mixed $year_or_datepoint a year as an int or a datepoint
369
 */
370
function instant(
371
    $year_or_datepoint,
372
    int $month = 1,
373
    int $day = 1,
374
    int $hour = 0,
375
    int $minute = 0,
376
    int $second = 0,
377
    int $microsecond = 0
378
): Period {
379
    if (is_int($year_or_datepoint)) {
380
        $datepoint = (new DateTimeImmutable())
381
            ->setDate($year_or_datepoint, $month, $day)
382
            ->setTime($hour, $minute, $second, $microsecond);
383
384
        return new Period($datepoint, $datepoint);
385
    }
386
387
    $datepoint = datepoint($year_or_datepoint);
388
389
    return new Period($datepoint, $datepoint);
390
}
391