Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
<?php
2
 
3
namespace PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel;
4
 
5
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
6
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
7
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
8
 
9
class NetworkDays
10
{
11
    use ArrayEnabled;
12
 
13
    /**
14
     * NETWORKDAYS.
15
     *
16
     * Returns the number of whole working days between start_date and end_date. Working days
17
     * exclude weekends and any dates identified in holidays.
18
     * Use NETWORKDAYS to calculate employee benefits that accrue based on the number of days
19
     * worked during a specific term.
20
     *
21
     * Excel Function:
22
     *        NETWORKDAYS(startDate,endDate[,holidays[,holiday[,...]]])
23
     *
24
     * @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer),
25
     *                                            PHP DateTime object, or a standard date string
26
     *                         Or can be an array of date values
27
     * @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer),
28
     *                                            PHP DateTime object, or a standard date string
29
     *                         Or can be an array of date values
30
     * @param mixed $dateArgs An array of dates (such as holidays) to exclude from the calculation
31
     *
32
     * @return array|int|string Interval between the dates
33
     *         If an array of values is passed for the $startDate or $endDate arguments, then the returned result
34
     *            will also be an array with matching dimensions
35
     */
36
    public static function count(mixed $startDate, mixed $endDate, mixed ...$dateArgs): array|string|int
37
    {
38
        if (is_array($startDate) || is_array($endDate)) {
39
            return self::evaluateArrayArgumentsSubset(
40
                [self::class, __FUNCTION__],
41
                2,
42
                $startDate,
43
                $endDate,
44
                ...$dateArgs
45
            );
46
        }
47
 
48
        try {
49
            //    Retrieve the mandatory start and end date that are referenced in the function definition
50
            $sDate = Helpers::getDateValue($startDate);
51
            $eDate = Helpers::getDateValue($endDate);
52
            $startDate = min($sDate, $eDate);
53
            $endDate = max($sDate, $eDate);
54
            //    Get the optional days
55
            $dateArgs = Functions::flattenArray($dateArgs);
56
            //    Test any extra holiday parameters
57
            $holidayArray = [];
58
            foreach ($dateArgs as $holidayDate) {
59
                $holidayArray[] = Helpers::getDateValue($holidayDate);
60
            }
61
        } catch (Exception $e) {
62
            return $e->getMessage();
63
        }
64
 
65
        // Execute function
66
        $startDow = self::calcStartDow($startDate);
67
        $endDow = self::calcEndDow($endDate);
68
        $wholeWeekDays = (int) floor(($endDate - $startDate) / 7) * 5;
69
        $partWeekDays = self::calcPartWeekDays($startDow, $endDow);
70
 
71
        //    Test any extra holiday parameters
72
        $holidayCountedArray = [];
73
        foreach ($holidayArray as $holidayDate) {
74
            if (($holidayDate >= $startDate) && ($holidayDate <= $endDate)) {
75
                if ((Week::day($holidayDate, 2) < 6) && (!in_array($holidayDate, $holidayCountedArray))) {
76
                    --$partWeekDays;
77
                    $holidayCountedArray[] = $holidayDate;
78
                }
79
            }
80
        }
81
 
82
        return self::applySign($wholeWeekDays + $partWeekDays, $sDate, $eDate);
83
    }
84
 
85
    private static function calcStartDow(float $startDate): int
86
    {
87
        $startDow = 6 - (int) Week::day($startDate, 2);
88
        if ($startDow < 0) {
89
            $startDow = 5;
90
        }
91
 
92
        return $startDow;
93
    }
94
 
95
    private static function calcEndDow(float $endDate): int
96
    {
97
        $endDow = (int) Week::day($endDate, 2);
98
        if ($endDow >= 6) {
99
            $endDow = 0;
100
        }
101
 
102
        return $endDow;
103
    }
104
 
105
    private static function calcPartWeekDays(int $startDow, int $endDow): int
106
    {
107
        $partWeekDays = $endDow + $startDow;
108
        if ($partWeekDays > 5) {
109
            $partWeekDays -= 5;
110
        }
111
 
112
        return $partWeekDays;
113
    }
114
 
115
    private static function applySign(int $result, float $sDate, float $eDate): int
116
    {
117
        return ($sDate > $eDate) ? -$result : $result;
118
    }
119
}