Romanian::setHolidaysInMonth()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
cc 3
nc 3
nop 2
1
<?php
2
3
/**
4
 *
5
 * The MIT License (MIT)
6
 *
7
 * Copyright (c) 2015 - 2021 Daniel Popiniuc
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a copy
10
 * of this software and associated documentation files (the "Software"), to deal
11
 * in the Software without restriction, including without limitation the rights
12
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
 * copies of the Software, and to permit persons to whom the Software is
14
 * furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included in all
17
 * copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
 * SOFTWARE.
26
 *
27
 */
28
29
namespace danielgp\bank_holidays;
30
31
/**
32
 * Return a list of all Romanian Holidays between 2001 and 2020
33
 *
34
 * @author Daniel Popiniuc
35
 */
36
trait Romanian
37
{
38
39
    /**
40
     *
41
     * @param int $year
42
     * @return type
43
     */
44
    private function getEasterDatetime($year)
45
    {
46
        $base = new \DateTime($year . '-03-21');
47
        return $base->add(new \DateInterval('P{' . easter_days($year) . '}D'));
48
    }
49
50
    /**
51
     * returns an array with non-standard holidays from a JSON file
52
     *
53
     * @param string $fileBaseName
54
     * @return mixed
55
     */
56
    protected function readTypeFromJsonFileUniversal($filePath, $fileBaseName)
57
    {
58
        $fName       = $filePath . DIRECTORY_SEPARATOR . $fileBaseName . '.min.json';
59
        $fJson       = fopen($fName, 'r');
60
        $jSonContent = fread($fJson, filesize($fName));
61
        fclose($fJson);
62
        return json_decode($jSonContent, true);
63
    }
64
65
    /**
66
     * List of legal holidays
67
     *
68
     * @param \DateTime $lngDate
69
     * @param boolean $inclCatholicEaster
70
     * @return array
71
     */
72
    public function setHolidays(\DateTime $lngDate, $inclCatholicEaster = false, $inclWorkingHolidays = false)
73
    {
74
        $givenYear = $lngDate->format('Y');
75
        $daying    = array_merge($this->setHolidaysOrthodoxEaster($lngDate), $this->setHolidaysFixed($lngDate));
76
        if ($inclWorkingHolidays) {
77
            $daying = array_merge($daying, $this->setHolidaysFixedButWorking($lngDate));
78
        }
79
        if ($inclCatholicEaster) { // Catholic easter is already known by PHP
80
            $firstEasterDate  = strtotime($this->getEasterDatetime($givenYear)->format('Y-m-d'));
81
            $secondEasterDate = strtotime('+1 day', $firstEasterDate);
82
            $daying           = array_merge($daying, [
83
                $firstEasterDate,
84
                $secondEasterDate,
85
            ]);
86
        }
87
        sort($daying);
88
        return array_unique($daying); // remove duplicate for when catholic and orthodox easter match
89
    }
90
91
    /**
92
     * List of all Romanian fixed holidays
93
     * (where fixed means every single year occur on same day of the month)
94
     *
95
     * @param \DateTime $lngDate
96
     * @return array
97
     */
98
    private function setHolidaysFixed(\DateTime $lngDate)
99
    {
100
        $daying    = [
101
            mktime(0, 0, 0, 1, 1, $lngDate->format('Y')), // Happy New Year
102
            mktime(0, 0, 0, 1, 2, $lngDate->format('Y')), // recovering from New Year party
103
            mktime(0, 0, 0, 5, 1, $lngDate->format('Y')), // May 1st
104
            mktime(0, 0, 0, 12, 1, $lngDate->format('Y')), // Romanian National Day
105
            mktime(0, 0, 0, 12, 25, $lngDate->format('Y')), // Christmas Day
106
            mktime(0, 0, 0, 12, 26, $lngDate->format('Y')), // Christmas 2nd Day
107
        ];
108
        $newerDays = $this->setHolidaysFixedOnlyNewerYears($lngDate);
109
        if (count($newerDays) > 0) {
110
            $daying = array_merge($daying, $newerDays);
111
            sort($daying);
112
        }
113
        return $daying;
114
    }
115
116
    /**
117
     * List of all Romanian fixed holidays for newer years
118
     * (as the legislation introduced few additional ones along the years, those are managed here)
119
     *
120
     * @param \DateTime $lngDate
121
     * @return array
122
     */
123
    private function setHolidaysFixedOnlyNewerYears(\DateTime $lngDate)
124
    {
125
        $daying = [];
126
        if ($lngDate->format('Y') >= 2009) {
127
            $daying[] = mktime(0, 0, 0, 8, 15, $lngDate->format('Y')); // St. Marry
128
            if ($lngDate->format('Y') >= 2012) {
129
                $daying[] = mktime(0, 0, 0, 11, 30, $lngDate->format('Y')); // St. Andrew
130
                if ($lngDate->format('Y') >= 2017) {
131
                    $daying[] = mktime(0, 0, 0, 1, 24, $lngDate->format('Y')); // Union Day
132
                    $daying[] = mktime(0, 0, 0, 6, 1, $lngDate->format('Y')); // Child's Day
133
                }
134
            }
135
        }
136
        return $daying;
137
    }
138
139
    /**
140
     * List of Romanian fixed holidays that are still working (weird ones)
141
     * (where fixed means every single year occur on same day of the month)
142
     *
143
     * @param \DateTime $lngDate
144
     * @return array
145
     */
146
    private function setHolidaysFixedButWorking(\DateTime $lngDate)
147
    {
148
        $daying    = [];
149
        $givenYear = $lngDate->format('Y');
150
        if ($givenYear >= 2015) {
151
            $daying[] = mktime(0, 0, 0, 1, 24, $givenYear); // Unirea Principatelor Romane
152
            if ($givenYear >= 2016) {
153
                $daying[] = mktime(0, 0, 0, 2, 19, $givenYear); // Constantin Brancusi birthday
154
            }
155
        }
156
        return $daying;
157
    }
158
159
    /**
160
     * List of all Orthodox holidays and Pentecost
161
     *
162
     * @param \DateTime $lngDate
163
     * @return array
164
     */
165
    private function setHolidaysOrthodoxEaster(\DateTime $lngDate)
166
    {
167
        $givenYear      = $lngDate->format('Y');
168
        $daying         = [];
169
        $configPath     = __DIR__ . DIRECTORY_SEPARATOR . 'json';
170
        $statmentsArray = $this->readTypeFromJsonFileUniversal($configPath, 'RomanianBankHolidays');
171
        if (array_key_exists($givenYear, $statmentsArray)) {
172
            foreach ($statmentsArray[$givenYear] as $value) {
173
                $daying[] = strtotime($value);
174
            }
175
        }
176
        return $daying;
177
    }
178
179
    /**
180
     * returns bank holidays in a given month
181
     *
182
     * @param \DateTime $lngDate
183
     * @param boolean $inclCatholicEaster
184
     * @return int
185
     */
186
    public function setHolidaysInMonth(\DateTime $lngDate, $inclCatholicEaster = false)
187
    {
188
        $holidaysInGivenYear = $this->setHolidays($lngDate, $inclCatholicEaster);
189
        $thisMonthDayArray   = $this->setMonthAllDaysIntoArray($lngDate);
190
        $holidays            = 0;
191
        foreach ($thisMonthDayArray as $value) {
192
            if (in_array($value, $holidaysInGivenYear)) {
193
                $holidays += 1;
194
            }
195
        }
196
        return $holidays;
197
    }
198
199
    /**
200
     * return an array with all days within a month from a given date
201
     *
202
     * @param \DateTime $lngDate
203
     * @return array
204
     */
205
    protected function setMonthAllDaysIntoArray(\DateTime $lngDate)
206
    {
207
        $firstDayGivenMonth  = strtotime($lngDate->modify('first day of this month')->format('Y-m-d'));
208
        $lastDayInGivenMonth = strtotime($lngDate->modify('last day of this month')->format('Y-m-d'));
209
        $secondsInOneDay     = 24 * 60 * 60;
210
        return range($firstDayGivenMonth, $lastDayInGivenMonth, $secondsInOneDay);
211
    }
212
213
    /**
214
     * returns working days in a given month
215
     *
216
     * @param \DateTime $lngDate
217
     * @param boolean $inclCatholicEaster
218
     * @return int
219
     */
220
    public function setWorkingDaysInMonth(\DateTime $lngDate, $inclCatholicEaster = false)
221
    {
222
        $holidaysInGivenYear = $this->setHolidays($lngDate, $inclCatholicEaster);
223
        $thisMonthDayArray   = $this->setMonthAllDaysIntoArray($lngDate);
224
        $workingDays         = 0;
225
        foreach ($thisMonthDayArray as $value) {
226
            if (!in_array(strftime('%w', $value), [0, 6]) && !in_array($value, $holidaysInGivenYear)) {
227
                $workingDays += 1;
228
            }
229
        }
230
        return $workingDays;
231
    }
232
}
233