RepetitiveDateEstimator::build()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 2
1
<?php
2
3
namespace Tworzenieweb\CyclicDates;
4
5
use DateTime;
6
7
/**
8
 * Use this class for estimating events occuring on every month. For example having an estimation
9
 * of event occuring for every month in 2 weeks interval is as simple as
10
 * RepetitiveDateEstimator::build(new DateTime(), RepeatitiveInterval::twoWeeks())
11
 * This will show 2 dates for each month one scheduled for 15th and second for 29th
12
 *
13
 * @package Tworzenieweb\CyclicDates
14
 */
15
class RepetitiveDateEstimator
16
{
17
    /**
18
     * @var DateTime
19
     */
20
    private $referenceDate;
21
22
    /**
23
     * @var RepetitiveInterval
24
     */
25
    private $interval;
26
27
28
29
    /**
30
     * @param DateTime           $referenceDate
31
     * @param RepetitiveInterval $interval
32
     */
33
    private function __construct(DateTime $referenceDate, RepetitiveInterval $interval)
34
    {
35
        $this->referenceDate = $referenceDate;
36
        $this->interval = $interval;
37
    }
38
39
40
41
    /**
42
     * @param DateTime           $referenceDate
43
     * @param RepetitiveInterval $interval
44
     *
45
     * @return RepetitiveDateEstimator
46
     */
47
    public static function build(DateTime $referenceDate, RepetitiveInterval $interval)
48
    {
49
        $repetitiveDateEstimator = new self($referenceDate, $interval);
50
51
        return $repetitiveDateEstimator;
52
    }
53
54
55
56
    /**
57
     * @return DateTime
58
     */
59
    public function getNextDate()
60
    {
61
        $referenceWithoutTime = clone $this->referenceDate;
62
63
        $dayOfMonth = (int)$referenceWithoutTime->format('j');
64
        $repetitiveInterval = $this->interval->interval();
65
        $moduloInterval = $dayOfMonth % $repetitiveInterval;
66
67
        if ($moduloInterval === 0) {
68
            $daysToAdd = 1;
69
        } else {
70
            $daysToAdd = $repetitiveInterval - ($moduloInterval);
71
            $daysInCurrentMonth = (int)$referenceWithoutTime->format('t');
72
73
            if ($dayOfMonth + $daysToAdd >= $daysInCurrentMonth) {
74
                $daysToAdd += ($daysInCurrentMonth - $dayOfMonth - ($daysToAdd - $repetitiveInterval));
75
            }
76
            $daysToAdd++;
77
        }
78
79
        $nextDate = clone $referenceWithoutTime;
80
        $nextDate->modify(sprintf('+ %d days', $daysToAdd));
81
82
        return $nextDate;
83
    }
84
}