Passed
Push — master ( 790382...9b34f8 )
by Mark
09:58
created

NetworkDays::count()   B

Complexity

Conditions 8
Paths 18

Size

Total Lines 37
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 8

Importance

Changes 0
Metric Value
cc 8
eloc 22
nc 18
nop 3
dl 0
loc 37
ccs 22
cts 22
cp 1
crap 8
rs 8.4444
c 0
b 0
f 0
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel;
4
5
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
6
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
7
8
class NetworkDays
9
{
10
    /**
11
     * NETWORKDAYS.
12
     *
13
     * Returns the number of whole working days between start_date and end_date. Working days
14
     * exclude weekends and any dates identified in holidays.
15
     * Use NETWORKDAYS to calculate employee benefits that accrue based on the number of days
16
     * worked during a specific term.
17
     *
18
     * Excel Function:
19
     *        NETWORKDAYS(startDate,endDate[,holidays[,holiday[,...]]])
20
     *
21
     * @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer),
22
     *                                            PHP DateTime object, or a standard date string
23
     * @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer),
24
     *                                            PHP DateTime object, or a standard date string
25
     * @param mixed $dateArgs
26
     *
27
     * @return int|string Interval between the dates
28
     */
29 29
    public static function count($startDate, $endDate, ...$dateArgs)
30
    {
31
        try {
32
            //    Retrieve the mandatory start and end date that are referenced in the function definition
33 29
            $sDate = Helpers::getDateValue($startDate);
34 28
            $eDate = Helpers::getDateValue($endDate);
35 27
            $startDate = min($sDate, $eDate);
36 27
            $endDate = max($sDate, $eDate);
37
            //    Get the optional days
38 27
            $dateArgs = Functions::flattenArray($dateArgs);
39
            //    Test any extra holiday parameters
40 27
            $holidayArray = [];
41 27
            foreach ($dateArgs as $holidayDate) {
42 5
                $holidayArray[] = Helpers::getDateValue($holidayDate);
43
            }
44 3
        } catch (Exception $e) {
45 3
            return $e->getMessage();
46
        }
47
48
        // Execute function
49 26
        $startDow = self::calcStartDow($startDate);
50 26
        $endDow = self::calcEndDow($endDate);
51 26
        $wholeWeekDays = (int) floor(($endDate - $startDate) / 7) * 5;
52 26
        $partWeekDays = self::calcPartWeekDays($startDow, $endDow);
53
54
        //    Test any extra holiday parameters
55 26
        $holidayCountedArray = [];
56 26
        foreach ($holidayArray as $holidayDate) {
57 4
            if (($holidayDate >= $startDate) && ($holidayDate <= $endDate)) {
58 4
                if ((Week::day($holidayDate, 2) < 6) && (!in_array($holidayDate, $holidayCountedArray))) {
59 4
                    --$partWeekDays;
60 4
                    $holidayCountedArray[] = $holidayDate;
61
                }
62
            }
63
        }
64
65 26
        return self::applySign($wholeWeekDays + $partWeekDays, $sDate, $eDate);
66
    }
67
68 26
    private static function calcStartDow(float $startDate): int
69
    {
70 26
        $startDow = 6 - (int) Week::day($startDate, 2);
71 26
        if ($startDow < 0) {
72 5
            $startDow = 5;
73
        }
74
75 26
        return $startDow;
76
    }
77
78 26
    private static function calcEndDow(float $endDate): int
79
    {
80 26
        $endDow = (int) Week::day($endDate, 2);
81 26
        if ($endDow >= 6) {
82 4
            $endDow = 0;
83
        }
84
85 26
        return $endDow;
86
    }
87
88 26
    private static function calcPartWeekDays(int $startDow, int $endDow): int
89
    {
90 26
        $partWeekDays = $endDow + $startDow;
91 26
        if ($partWeekDays > 5) {
92 18
            $partWeekDays -= 5;
93
        }
94
95 26
        return $partWeekDays;
96
    }
97
98 26
    private static function applySign(int $result, float $sDate, float $eDate): int
99
    {
100 26
        return ($sDate > $eDate) ? -$result : $result;
101
    }
102
}
103