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\Information\ExcelError;
8
use PhpOffice\PhpSpreadsheet\Shared\Date as SharedDateHelper;
9
 
10
class Days360
11
{
12
    use ArrayEnabled;
13
 
14
    /**
15
     * DAYS360.
16
     *
17
     * Returns the number of days between two dates based on a 360-day year (twelve 30-day months),
18
     * which is used in some accounting calculations. Use this function to help compute payments if
19
     * your accounting system is based on twelve 30-day months.
20
     *
21
     * Excel Function:
22
     *        DAYS360(startDate,endDate[,method])
23
     *
24
     * @param array|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 array|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 array|mixed $method US or European Method as a bool
31
     *                                        FALSE or omitted: U.S. (NASD) method. If the starting date is
32
     *                                        the last day of a month, it becomes equal to the 30th of the
33
     *                                        same month. If the ending date is the last day of a month and
34
     *                                        the starting date is earlier than the 30th of a month, the
35
     *                                        ending date becomes equal to the 1st of the next month;
36
     *                                        otherwise the ending date becomes equal to the 30th of the
37
     *                                        same month.
38
     *                                        TRUE: European method. Starting dates and ending dates that
39
     *                                        occur on the 31st of a month become equal to the 30th of the
40
     *                                        same month.
41
     *                         Or can be an array of methods
42
     *
43
     * @return array|int|string Number of days between start date and end date
44
     *         If an array of values is passed for the $startDate or $endDays,arguments, then the returned result
45
     *            will also be an array with matching dimensions
46
     */
47
    public static function between(mixed $startDate = 0, mixed $endDate = 0, mixed $method = false): array|string|int
48
    {
49
        if (is_array($startDate) || is_array($endDate) || is_array($method)) {
50
            return self::evaluateArrayArguments([self::class, __FUNCTION__], $startDate, $endDate, $method);
51
        }
52
 
53
        try {
54
            $startDate = Helpers::getDateValue($startDate);
55
            $endDate = Helpers::getDateValue($endDate);
56
        } catch (Exception $e) {
57
            return $e->getMessage();
58
        }
59
 
60
        if (!is_bool($method)) {
61
            return ExcelError::VALUE();
62
        }
63
 
64
        // Execute function
65
        $PHPStartDateObject = SharedDateHelper::excelToDateTimeObject($startDate);
66
        $startDay = $PHPStartDateObject->format('j');
67
        $startMonth = $PHPStartDateObject->format('n');
68
        $startYear = $PHPStartDateObject->format('Y');
69
 
70
        $PHPEndDateObject = SharedDateHelper::excelToDateTimeObject($endDate);
71
        $endDay = $PHPEndDateObject->format('j');
72
        $endMonth = $PHPEndDateObject->format('n');
73
        $endYear = $PHPEndDateObject->format('Y');
74
 
75
        return self::dateDiff360((int) $startDay, (int) $startMonth, (int) $startYear, (int) $endDay, (int) $endMonth, (int) $endYear, !$method);
76
    }
77
 
78
    /**
79
     * Return the number of days between two dates based on a 360 day calendar.
80
     */
81
    private static function dateDiff360(int $startDay, int $startMonth, int $startYear, int $endDay, int $endMonth, int $endYear, bool $methodUS): int
82
    {
83
        $startDay = self::getStartDay($startDay, $startMonth, $startYear, $methodUS);
84
        $endDay = self::getEndDay($endDay, $endMonth, $endYear, $startDay, $methodUS);
85
 
86
        return $endDay + $endMonth * 30 + $endYear * 360 - $startDay - $startMonth * 30 - $startYear * 360;
87
    }
88
 
89
    private static function getStartDay(int $startDay, int $startMonth, int $startYear, bool $methodUS): int
90
    {
91
        if ($startDay == 31) {
92
            --$startDay;
93
        } elseif ($methodUS && ($startMonth == 2 && ($startDay == 29 || ($startDay == 28 && !Helpers::isLeapYear($startYear))))) {
94
            $startDay = 30;
95
        }
96
 
97
        return $startDay;
98
    }
99
 
100
    private static function getEndDay(int $endDay, int &$endMonth, int &$endYear, int $startDay, bool $methodUS): int
101
    {
102
        if ($endDay == 31) {
103
            if ($methodUS && $startDay != 30) {
104
                $endDay = 1;
105
                if ($endMonth == 12) {
106
                    ++$endYear;
107
                    $endMonth = 1;
108
                } else {
109
                    ++$endMonth;
110
                }
111
            } else {
112
                $endDay = 30;
113
            }
114
        }
115
 
116
        return $endDay;
117
    }
118
}