Calculator   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 207
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 25
lcom 1
cbo 0
dl 0
loc 207
ccs 56
cts 56
cp 1
rs 10
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A setStartDate() 0 9 1
A setHolidays() 0 6 1
A getHolidays() 0 4 1
A setFreeDays() 0 6 1
A getFreeDays() 0 4 1
A setFreeWeekDays() 0 6 1
A getFreeWeekDays() 0 8 2
A isFreeWeekDayDay() 0 10 2
A isBusinessDay() 0 16 4
A addBusinessDays() 0 12 3
A getDate() 0 8 2
A isHoliday() 0 11 3
A isFreeDay() 0 11 3
1
<?php
2
3
namespace BusinessDays;
4
5
6
/**
7
 * Class Calculator
8
 *
9
 * @package BusinessDays
10
 */
11
class Calculator
12
{
13
    const MONDAY    = 1;
14
    const TUESDAY   = 2;
15
    const WEDNESDAY = 3;
16
    const THURSDAY  = 4;
17
    const FRIDAY    = 5;
18
    const SATURDAY  = 6;
19
    const SUNDAY    = 7;
20
21
    const WEEK_DAY_FORMAT = 'N';
22
    const HOLIDAY_FORMAT  = 'm-d';
23
    const FREE_DAY_FORMAT = 'Y-m-d';
24
25
    /** @var \DateTime */
26
    private $date;
27
28
    /** @var \DateTime[] */
29
    private $holidays = array();
30
31
    /** @var \DateTime[] */
32
    private $freeDays = array();
33
34
    /** @var int[] */
35
    private $freeWeekDays = array();
36
37
    /**
38
     * @param \DateTime $startDate Date to start calculations from
39
     *
40
     * @return $this
41
     */
42 16
    public function setStartDate(\DateTime $startDate)
43
    {
44
        // Use clone so parameter is not passed as a reference.
45
        // If not, it can brake caller method by changing $startDate parameter while changing it here.
46
47 16
        $this->date = clone $startDate;
48
49 16
        return $this;
50
    }
51
52
    /**
53
     * @param \DateTime[] $holidays Array of holidays that repeats each year. (Only month and date is used to match).
54
     *
55
     * @return $this
56
     */
57 15
    public function setHolidays(array $holidays)
58
    {
59 15
        $this->holidays = $holidays;
60
61 15
        return $this;
62
    }
63
64
    /**
65
     * @return \DateTime[]
66
     */
67 16
    private function getHolidays()
68
    {
69 16
        return $this->holidays;
70
    }
71
72
    /**
73
     * @param \DateTime[] $freeDays Array of free days that dose not repeat.
74
     *
75
     * @return $this
76
     */
77 15
    public function setFreeDays(array $freeDays)
78
    {
79 15
        $this->freeDays = $freeDays;
80
81 15
        return $this;
82
    }
83
84
    /**
85
     * @return \DateTime[]
86
     */
87 16
    private function getFreeDays()
88
    {
89 16
        return $this->freeDays;
90
    }
91
92
    /**
93
     * @param int[] $freeWeekDays Array of days of the week which are not business days.
94
     *
95
     * @return $this
96
     */
97 16
    public function setFreeWeekDays(array $freeWeekDays)
98
    {
99 16
        $this->freeWeekDays = $freeWeekDays;
100
101 16
        return $this;
102
    }
103
104
    /**
105
     * @return int[]
106
     */
107 17
    private function getFreeWeekDays()
108
    {
109 17
        if (count($this->freeWeekDays) >= 7) {
110 1
            throw new \InvalidArgumentException('Too many non business days provided');
111
        }
112
113 16
        return $this->freeWeekDays;
114
    }
115
116
    /**
117
     * @param int $howManyDays
118
     *
119
     * @return $this
120
     */
121 17
    public function addBusinessDays($howManyDays)
122
    {
123 17
        $iterator = 0;
124 17
        while ($iterator < $howManyDays) {
125 17
            $this->getDate()->modify('+1 day');
126 17
            if ($this->isBusinessDay($this->getDate())) {
127 16
                $iterator++;
128
            }
129
        }
130
131 16
        return $this;
132
    }
133
134
    /**
135
     * @return \DateTime
136
     */
137 17
    public function getDate()
138
    {
139 17
        if ($this->date === null) {
140 1
            $this->date = new \DateTime();
141
        }
142
143 17
        return $this->date;
144
    }
145
146
    /**
147
     * @param \DateTime $date
148
     *
149
     * @return bool
150
     */
151 17
    public function isBusinessDay(\DateTime $date)
152
    {
153 17
        if ($this->isFreeWeekDayDay($date)) {
154 7
            return false;
155
        }
156
157 16
        if ($this->isHoliday($date)) {
158 4
            return false;
159
        }
160
161 16
        if ($this->isFreeDay($date)) {
162 7
            return false;
163
        }
164
165 16
        return true;
166
    }
167
168
    /**
169
     * @param \DateTime $date
170
     *
171
     * @return bool
172
     */
173 17
    public function isFreeWeekDayDay(\DateTime $date)
174
    {
175 17
        $currentWeekDay = (int)$date->format(self::WEEK_DAY_FORMAT);
176
177 17
        if (in_array($currentWeekDay, $this->getFreeWeekDays())) {
178 7
            return true;
179
        }
180
181 16
        return false;
182
    }
183
184
    /**
185
     * @param \DateTime $date
186
     *
187
     * @return bool
188
     */
189 16
    public function isHoliday(\DateTime $date)
190
    {
191 16
        $holidayFormatValue = $date->format(self::HOLIDAY_FORMAT);
192 16
        foreach ($this->getHolidays() as $holiday) {
193 4
            if ($holidayFormatValue == $holiday->format(self::HOLIDAY_FORMAT)) {
194 4
                return true;
195
            }
196
        }
197
198 16
        return false;
199
    }
200
201
    /**
202
     * @param \DateTime $date
203
     *
204
     * @return bool
205
     */
206 16
    public function isFreeDay(\DateTime $date)
207
    {
208 16
        $freeDayFormatValue = $date->format(self::FREE_DAY_FORMAT);
209 16
        foreach ($this->getFreeDays() as $freeDay) {
210 7
            if ($freeDayFormatValue == $freeDay->format(self::FREE_DAY_FORMAT)) {
211 7
                return true;
212
            }
213
        }
214
215 16
        return false;
216
    }
217
}
218