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

Time::fromHMS()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 35
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 21
nc 10
nop 3
dl 0
loc 35
ccs 21
cts 21
cp 1
crap 6
rs 8.9617
c 0
b 0
f 0
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel;
4
5
use DateTime;
6
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
7
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
8
use PhpOffice\PhpSpreadsheet\Shared\Date as SharedDateHelper;
9
10
class Time
11
{
12
    /**
13
     * TIME.
14
     *
15
     * The TIME function returns a value that represents a particular time.
16
     *
17
     * NOTE: When used in a Cell Formula, MS Excel changes the cell format so that it matches the time
18
     * format of your regional settings. PhpSpreadsheet does not change cell formatting in this way.
19
     *
20
     * Excel Function:
21
     *        TIME(hour,minute,second)
22
     *
23
     * @param mixed $hour A number from 0 (zero) to 32767 representing the hour.
24
     *                                    Any value greater than 23 will be divided by 24 and the remainder
25
     *                                    will be treated as the hour value. For example, TIME(27,0,0) =
26
     *                                    TIME(3,0,0) = .125 or 3:00 AM.
27
     * @param mixed $minute A number from 0 to 32767 representing the minute.
28
     *                                    Any value greater than 59 will be converted to hours and minutes.
29
     *                                    For example, TIME(0,750,0) = TIME(12,30,0) = .520833 or 12:30 PM.
30
     * @param mixed $second A number from 0 to 32767 representing the second.
31
     *                                    Any value greater than 59 will be converted to hours, minutes,
32
     *                                    and seconds. For example, TIME(0,0,2000) = TIME(0,33,22) = .023148
33
     *                                    or 12:33:20 AM
34
     *
35
     * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object,
36
     *                        depending on the value of the ReturnDateType flag
37
     */
38 28
    public static function fromHMS($hour, $minute, $second)
39
    {
40
        try {
41 28
            $hour = self::toIntWithNullBool($hour);
42 27
            $minute = self::toIntWithNullBool($minute);
43 27
            $second = self::toIntWithNullBool($second);
44 1
        } catch (Exception $e) {
45 1
            return $e->getMessage();
46
        }
47
48 27
        self::adjustSecond($second, $minute);
49 27
        self::adjustMinute($minute, $hour);
50
51 27
        if ($hour > 23) {
52 1
            $hour = $hour % 24;
53 26
        } elseif ($hour < 0) {
54 3
            return Functions::NAN();
55
        }
56
57
        // Execute function
58 25
        $retType = Functions::getReturnDateType();
59 25
        if ($retType === Functions::RETURNDATE_EXCEL) {
60 23
            $calendar = SharedDateHelper::getExcelCalendar();
61 23
            $date = (int) ($calendar !== SharedDateHelper::CALENDAR_WINDOWS_1900);
62
63 23
            return (float) SharedDateHelper::formattedPHPToExcel($calendar, 1, $date, $hour, $minute, $second);
64
        }
65 2
        if ($retType === Functions::RETURNDATE_UNIX_TIMESTAMP) {
66 1
            return (int) SharedDateHelper::excelToTimestamp(SharedDateHelper::formattedPHPToExcel(1970, 1, 1, $hour, $minute, $second)); // -2147468400; //    -2147472000 + 3600
67
        }
68
        // RETURNDATE_PHP_DATETIME_OBJECT
69
        // Hour has already been normalized (0-23) above
70 1
        $phpDateObject = new DateTime('1900-01-01 ' . $hour . ':' . $minute . ':' . $second);
71
72 1
        return $phpDateObject;
73
    }
74
75 27
    private static function adjustSecond(int &$second, int &$minute): void
76
    {
77 27
        if ($second < 0) {
78 5
            $minute += floor($second / 60);
79 5
            $second = 60 - abs($second % 60);
80 5
            if ($second == 60) {
81 5
                $second = 0;
82
            }
83 23
        } elseif ($second >= 60) {
84 1
            $minute += floor($second / 60);
85 1
            $second = $second % 60;
86
        }
87 27
    }
88
89 27
    private static function adjustMinute(int &$minute, int &$hour): void
90
    {
91 27
        if ($minute < 0) {
92 8
            $hour += floor($minute / 60);
93 8
            $minute = 60 - abs($minute % 60);
94 8
            if ($minute == 60) {
95 8
                $minute = 0;
96
            }
97 20
        } elseif ($minute >= 60) {
98 3
            $hour += floor($minute / 60);
99 3
            $minute = $minute % 60;
100
        }
101 27
    }
102
103
    /**
104
     * @param mixed $value expect int
105
     */
106 28
    private static function toIntWithNullBool($value): int
107
    {
108 28
        $value = Functions::flattenSingleValue($value);
109 28
        $value = $value ?? 0;
110 28
        if (is_bool($value)) {
111 2
            $value = (int) $value;
112
        }
113 28
        if (!is_numeric($value)) {
114 1
            throw new Exception(Functions::VALUE());
115
        }
116
117 27
        return (int) $value;
118
    }
119
}
120