Completed
Pull Request — master (#8)
by Rodrigo
02:04
created

Calculator::subBusinessDays()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 17
Code Lines 10

Duplication

Lines 17
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 17
loc 17
ccs 0
cts 13
cp 0
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 10
nc 6
nop 1
crap 30
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 View Code Duplication
    public function addBusinessDays($howManyDays)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
122
    {
123 17
        if ($howManyDays < 1) {
124
            throw new \InvalidArgumentException('The parameter $howManyDays must be greater than 0');
125
        }
126
127 17
        $iterator = 0;
128 17
        while ($iterator < $howManyDays) {
129 17
            $this->getDate()->modify('+1 day');
130 17
            if ($this->isBusinessDay($this->getDate())) {
131 16
                $iterator++;
132 16
            }
133 16
        }
134
135 16
        return $this;
136
    }
137
138
    /**
139
     * @param int $howManyDays
140
     *
141
     * @return $this
142
     */
143 View Code Duplication
    public function subBusinessDays($howManyDays)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
144
    {
145
        if ($howManyDays < 1) {
146
            throw new \InvalidArgumentException('The parameter $howManyDays must be greater than 0');
147
        }
148
149
        $iterator = 0;
150
        while ($iterator < $howManyDays) {
151
            if ($this->isBusinessDay($this->getDate())) {
152
                $iterator++;
153
            }
154
            if ($iterator < $howManyDays) { //Don`t modify the date if we are on the last iteration
155
                $this->getDate()->modify('-1 day');
156
            }
157
        }
158
        return $this;
159
    }
160
161
    /**
162
     * @return \DateTime
163
     */
164 17
    public function getDate()
165
    {
166 17
        if ($this->date === null) {
167 1
            $this->date = new \DateTime();
168 1
        }
169
170 17
        return $this->date;
171
    }
172
173
    /**
174
     * @param \DateTime $date
175
     *
176
     * @return bool
177
     */
178 17
    public function isBusinessDay(\DateTime $date)
179
    {
180 17
        if ($this->isFreeWeekDayDay($date)) {
181 7
            return false;
182
        }
183
184 16
        if ($this->isHoliday($date)) {
185 4
            return false;
186
        }
187
188 16
        if ($this->isFreeDay($date)) {
189 7
            return false;
190
        }
191
192 16
        return true;
193
    }
194
195
    /**
196
     * @param \DateTime $date
197
     *
198
     * @return bool
199
     */
200 17
    public function isFreeWeekDayDay(\DateTime $date)
201
    {
202 17
        $currentWeekDay = (int)$date->format(self::WEEK_DAY_FORMAT);
203
204 17
        if (in_array($currentWeekDay, $this->getFreeWeekDays())) {
205 7
            return true;
206
        }
207
208 16
        return false;
209
    }
210
211
    /**
212
     * @param \DateTime $date
213
     *
214
     * @return bool
215
     */
216 16
    public function isHoliday(\DateTime $date)
217
    {
218 16
        $holidayFormatValue = $date->format(self::HOLIDAY_FORMAT);
219 16
        foreach ($this->getHolidays() as $holiday) {
220 4
            if ($holidayFormatValue == $holiday->format(self::HOLIDAY_FORMAT)) {
221 4
                return true;
222
            }
223 16
        }
224
225 16
        return false;
226
    }
227
228
    /**
229
     * @param \DateTime $date
230
     *
231
     * @return bool
232
     */
233 16
    public function isFreeDay(\DateTime $date)
234
    {
235 16
        $freeDayFormatValue = $date->format(self::FREE_DAY_FORMAT);
236 16
        foreach ($this->getFreeDays() as $freeDay) {
237 7
            if ($freeDayFormatValue == $freeDay->format(self::FREE_DAY_FORMAT)) {
238 7
                return true;
239
            }
240 16
        }
241
242 16
        return false;
243
    }
244
}
245