ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Difference.php
Go to the documentation of this file.
1<?php
2
4
5use DateInterval;
6use DateTime;
9use PhpOffice\PhpSpreadsheet\Shared\Date as SharedDateHelper;
10
12{
24 public static function interval($startDate, $endDate, $unit = 'D')
25 {
26 try {
27 $startDate = Helpers::getDateValue($startDate);
28 $endDate = Helpers::getDateValue($endDate);
29 $difference = self::initialDiff($startDate, $endDate);
30 $unit = strtoupper(Functions::flattenSingleValue($unit));
31 } catch (Exception $e) {
32 return $e->getMessage();
33 }
34
35 // Execute function
36 $PHPStartDateObject = SharedDateHelper::excelToDateTimeObject($startDate);
37 $startDays = (int) $PHPStartDateObject->format('j');
38 $startMonths = (int) $PHPStartDateObject->format('n');
39 $startYears = (int) $PHPStartDateObject->format('Y');
40
41 $PHPEndDateObject = SharedDateHelper::excelToDateTimeObject($endDate);
42 $endDays = (int) $PHPEndDateObject->format('j');
43 $endMonths = (int) $PHPEndDateObject->format('n');
44 $endYears = (int) $PHPEndDateObject->format('Y');
45
46 $PHPDiffDateObject = $PHPEndDateObject->diff($PHPStartDateObject);
47
48 $retVal = false;
49 $retVal = self::replaceRetValue($retVal, $unit, 'D') ?? self::datedifD($difference);
50 $retVal = self::replaceRetValue($retVal, $unit, 'M') ?? self::datedifM($PHPDiffDateObject);
51 $retVal = self::replaceRetValue($retVal, $unit, 'MD') ?? self::datedifMD($startDays, $endDays, $PHPEndDateObject, $PHPDiffDateObject);
52 $retVal = self::replaceRetValue($retVal, $unit, 'Y') ?? self::datedifY($PHPDiffDateObject);
53 $retVal = self::replaceRetValue($retVal, $unit, 'YD') ?? self::datedifYD($difference, $startYears, $endYears, $PHPStartDateObject, $PHPEndDateObject);
54 $retVal = self::replaceRetValue($retVal, $unit, 'YM') ?? self::datedifYM($PHPDiffDateObject);
55
56 return is_bool($retVal) ? Functions::VALUE() : $retVal;
57 }
58
59 private static function initialDiff(float $startDate, float $endDate): float
60 {
61 // Validate parameters
62 if ($startDate > $endDate) {
63 throw new Exception(Functions::NAN());
64 }
65
66 return $endDate - $startDate;
67 }
68
76 private static function replaceRetValue($retVal, string $unit, string $compare)
77 {
78 if ($retVal !== false || $unit !== $compare) {
79 return $retVal;
80 }
81
82 return null;
83 }
84
85 private static function datedifD(float $difference): int
86 {
87 return (int) $difference;
88 }
89
90 private static function datedifM(DateInterval $PHPDiffDateObject): int
91 {
92 return 12 * (int) $PHPDiffDateObject->format('%y') + (int) $PHPDiffDateObject->format('%m');
93 }
94
95 private static function datedifMD(int $startDays, int $endDays, DateTime $PHPEndDateObject, DateInterval $PHPDiffDateObject): int
96 {
97 if ($endDays < $startDays) {
98 $retVal = $endDays;
99 $PHPEndDateObject->modify('-' . $endDays . ' days');
100 $adjustDays = (int) $PHPEndDateObject->format('j');
101 $retVal += ($adjustDays - $startDays);
102 } else {
103 $retVal = (int) $PHPDiffDateObject->format('%d');
104 }
105
106 return $retVal;
107 }
108
109 private static function datedifY(DateInterval $PHPDiffDateObject): int
110 {
111 return (int) $PHPDiffDateObject->format('%y');
112 }
113
114 private static function datedifYD(float $difference, int $startYears, int $endYears, DateTime $PHPStartDateObject, DateTime $PHPEndDateObject): int
115 {
116 $retVal = (int) $difference;
117 if ($endYears > $startYears) {
118 $isLeapStartYear = $PHPStartDateObject->format('L');
119 $wasLeapEndYear = $PHPEndDateObject->format('L');
120
121 // Adjust end year to be as close as possible as start year
122 while ($PHPEndDateObject >= $PHPStartDateObject) {
123 $PHPEndDateObject->modify('-1 year');
124 $endYears = $PHPEndDateObject->format('Y');
125 }
126 $PHPEndDateObject->modify('+1 year');
127
128 // Get the result
129 $retVal = $PHPEndDateObject->diff($PHPStartDateObject)->days;
130
131 // Adjust for leap years cases
132 $isLeapEndYear = $PHPEndDateObject->format('L');
133 $limit = new DateTime($PHPEndDateObject->format('Y-02-29'));
134 if (!$isLeapStartYear && !$wasLeapEndYear && $isLeapEndYear && $PHPEndDateObject >= $limit) {
135 --$retVal;
136 }
137 }
138
139 return (int) $retVal;
140 }
141
142 private static function datedifYM(DateInterval $PHPDiffDateObject): int
143 {
144 return (int) $PHPDiffDateObject->format('%m');
145 }
146}
An exception for terminatinating execution or to throw for unit testing.
static initialDiff(float $startDate, float $endDate)
Definition: Difference.php:59
static datedifMD(int $startDays, int $endDays, DateTime $PHPEndDateObject, DateInterval $PHPDiffDateObject)
Definition: Difference.php:95
static datedifY(DateInterval $PHPDiffDateObject)
Definition: Difference.php:109
static interval($startDate, $endDate, $unit='D')
DATEDIF.
Definition: Difference.php:24
static datedifYD(float $difference, int $startYears, int $endYears, DateTime $PHPStartDateObject, DateTime $PHPEndDateObject)
Definition: Difference.php:114
static datedifM(DateInterval $PHPDiffDateObject)
Definition: Difference.php:90
static replaceRetValue($retVal, string $unit, string $compare)
Decide whether it's time to set retVal.
Definition: Difference.php:76
static datedifYM(DateInterval $PHPDiffDateObject)
Definition: Difference.php:142
static getDateValue($dateValue, bool $allowBool=true)
getDateValue.
Definition: Helpers.php:31
static flattenSingleValue($value='')
Convert an array to a single scalar value by extracting the first element.
Definition: Functions.php:649