Completed
Push — master ( 526eb1...0fdc47 )
by Daniel
01:48
created

Romanian::setHolidaysFixed()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 17
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 13
nc 2
nop 1
1
<?php
2
3
/**
4
 *
5
 * The MIT License (MIT)
6
 *
7
 * Copyright (c) 2015 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
        $days = easter_days($year);
48
        return $base->add(new \DateInterval("P{$days}D"));
49
    }
50
51
    /**
52
     * returns an array with non-standard holidays from a JSON file
53
     *
54
     * @param string $fileBaseName
55
     * @return mixed
56
     */
57
    protected function readTypeFromJsonFileUniversal($filePath, $fileBaseName)
58
    {
59
        $fName       = $filePath . DIRECTORY_SEPARATOR . $fileBaseName . '.min.json';
60
        $fJson       = fopen($fName, 'r');
61
        $jSonContent = fread($fJson, filesize($fName));
62
        fclose($fJson);
63
        return json_decode($jSonContent, true);
64
    }
65
66
    /**
67
     * List of legal holidays
68
     *
69
     * @param \DateTime $lngDate
70
     * @param boolean $inclCatholicEaster
71
     * @return array
72
     */
73
    protected function setHolidays(\DateTime $lngDate, $inclCatholicEaster = false, $inclWorkingHolidays = false)
74
    {
75
        $givenYear = $lngDate->format('Y');
76
        $daying    = array_merge($this->setHolidaysOrthodoxEaster($lngDate), $this->setHolidaysFixed($lngDate));
77
        if ($inclWorkingHolidays) {
78
            $daying = array_merge($daying, $this->setHolidaysFixedButWorking($lngDate));
79
        }
80
        if ($inclCatholicEaster) { // Catholic easter is already known by PHP
81
            $firstEasterDate  = strtotime($this->getEasterDatetime($givenYear)->format('Y-m-d'));
82
            $secondEasterDate = strtotime('+1 day', $firstEasterDate);
83
            $daying           = array_merge($daying, [
84
                $firstEasterDate,
85
                $secondEasterDate,
86
            ]);
87
        }
88
        sort($daying);
89
        return array_unique($daying); // remove duplicate for when catholic and orthodox easter match
90
    }
91
92
    /**
93
     * List of all Romanian fixed holidays
94
     * (where fixed means every single year occur on same day of the month)
95
     *
96
     * @param \DateTime $lngDate
97
     * @return array
98
     */
99
    private function setHolidaysFixed(\DateTime $lngDate)
100
    {
101
        $daying    = [
102
            mktime(0, 0, 0, 1, 1, $lngDate->format('Y')), // Happy New Year
103
            mktime(0, 0, 0, 1, 2, $lngDate->format('Y')), // recovering from New Year party
104
            mktime(0, 0, 0, 5, 1, $lngDate->format('Y')), // May 1st
105
            mktime(0, 0, 0, 12, 1, $lngDate->format('Y')), // Romanian National Day
106
            mktime(0, 0, 0, 12, 25, $lngDate->format('Y')), // Christmas Day
107
            mktime(0, 0, 0, 12, 26, $lngDate->format('Y')), // Christmas 2nd Day
108
        ];
109
        $newerDays = $this->setHolidaysFixedOnlyNewerYears($lngDate);
110
        if (count($newerDays) > 0) {
111
            $daying = array_merge($daying, $newerDays);
112
            sort($daying);
113
        }
114
        return $daying;
115
    }
116
117
    /**
118
     * List of all Romanian fixed holidays for newer years
119
     * (as the legislation introduced few additional ones along the years, those are managed here)
120
     *
121
     * @param \DateTime $lngDate
122
     * @return array
123
     */
124
    private function setHolidaysFixedOnlyNewerYears(\DateTime $lngDate)
125
    {
126
        $daying = [];
127
        if ($lngDate->format('Y') >= 2009) {
128
            $daying[] = mktime(0, 0, 0, 8, 15, $lngDate->format('Y')); // St. Marry
129
            if ($lngDate->format('Y') >= 2012) {
130
                $daying[] = mktime(0, 0, 0, 11, 30, $lngDate->format('Y')); // St. Andrew
131
                if ($lngDate->format('Y') >= 2017) {
132
                    $daying[] = mktime(0, 0, 0, 1, 24, $lngDate->format('Y')); // Union Day
133
                    $daying[] = mktime(0, 0, 0, 6, 1, $lngDate->format('Y')); // Child's Day
134
                }
135
            }
136
        }
137
        return $daying;
138
    }
139
140
    /**
141
     * List of Romanian fixed holidays that are still working (weird ones)
142
     * (where fixed means every single year occur on same day of the month)
143
     *
144
     * @param \DateTime $lngDate
145
     * @return array
146
     */
147
    private function setHolidaysFixedButWorking(\DateTime $lngDate)
148
    {
149
        $daying    = [];
150
        $givenYear = $lngDate->format('Y');
151
        if ($givenYear >= 2015) {
152
            $daying[] = mktime(0, 0, 0, 1, 24, $givenYear); // Unirea Principatelor Romane
153
        }
154
        if ($givenYear >= 2016) {
155
            $daying[] = mktime(0, 0, 0, 2, 19, $givenYear); // Constantin Brancusi birthday
156
        }
157
        return $daying;
158
    }
159
160
    /**
161
     * List of all Orthodox holidays and Pentecost
162
     *
163
     * @param \DateTime $lngDate
164
     * @return array
165
     */
166
    private function setHolidaysOrthodoxEaster(\DateTime $lngDate)
167
    {
168
        $givenYear      = $lngDate->format('Y');
169
        $daying         = [];
170
        $configPath     = __DIR__ . DIRECTORY_SEPARATOR . 'json';
171
        $statmentsArray = $this->readTypeFromJsonFileUniversal($configPath, 'RomanianBankHolidays');
172
        if (array_key_exists($givenYear, $statmentsArray)) {
173
            foreach ($statmentsArray[$givenYear] as $value) {
174
                $daying[] = strtotime($value);
175
            }
176
        }
177
        return $daying;
178
    }
179
180
    /**
181
     * returns bank holidays in a given month
182
     *
183
     * @param \DateTime $lngDate
184
     * @param boolean $inclCatholicEaster
185
     * @return int
186
     */
187
    protected function setHolidaysInMonth(\DateTime $lngDate, $inclCatholicEaster = false)
188
    {
189
        $holidaysInGivenYear = $this->setHolidays($lngDate, $inclCatholicEaster);
190
        $thisMonthDayArray   = $this->setMonthAllDaysIntoArray($lngDate);
191
        $holidays            = 0;
192
        foreach ($thisMonthDayArray as $value) {
193
            if (in_array($value, $holidaysInGivenYear)) {
194
                $holidays += 1;
195
            }
196
        }
197
        return $holidays;
198
    }
199
200
    /**
201
     * return an array with all days within a month from a given date
202
     *
203
     * @param \DateTime $lngDate
204
     * @return array
205
     */
206
    protected function setMonthAllDaysIntoArray(\DateTime $lngDate)
207
    {
208
        $firstDayGivenMonth  = strtotime($lngDate->modify('first day of this month')->format('Y-m-d'));
209
        $lastDayInGivenMonth = strtotime($lngDate->modify('last day of this month')->format('Y-m-d'));
210
        $secondsInOneDay     = 24 * 60 * 60;
211
        return range($firstDayGivenMonth, $lastDayInGivenMonth, $secondsInOneDay);
212
    }
213
214
    /**
215
     * returns working days in a given month
216
     *
217
     * @param \DateTime $lngDate
218
     * @param boolean $inclCatholicEaster
219
     * @return int
220
     */
221
    protected function setWorkingDaysInMonth(\DateTime $lngDate, $inclCatholicEaster = false)
222
    {
223
        $holidaysInGivenYear = $this->setHolidays($lngDate, $inclCatholicEaster);
224
        $thisMonthDayArray   = $this->setMonthAllDaysIntoArray($lngDate);
225
        $workingDays         = 0;
226
        foreach ($thisMonthDayArray as $value) {
227
            if (!in_array(strftime('%w', $value), [0, 6]) && !in_array($value, $holidaysInGivenYear)) {
228
                $workingDays += 1;
229
            }
230
        }
231
        return $workingDays;
232
    }
233
}
234