functions.php ➔ dateTime2Dos()   C
last analyzed

Complexity

Conditions 7
Paths 4

Size

Total Lines 38
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 7.1429

Importance

Changes 0
Metric Value
cc 7
eloc 25
nc 4
nop 1
dl 0
loc 38
ccs 18
cts 21
cp 0.8571
crap 7.1429
rs 6.7272
c 0
b 0
f 0
1
<?php
2
3
namespace morgue\zip;
4
5
/**
6
 * Convert dos date and time values to a \DateTimeInterface object.
7
 * DOS times are stored as local time values (not UTC), so use the supplied timezone (defaults to \date_default_timezone_get()).
8
 *
9
 * @param int $dosTime
10
 * @param int $dosDate
11
 * @param string $timezone
12
 * @return \DateTimeInterface
13
 * @throws \Exception
14
 */
15
function dos2DateTime(int $dosTime, int $dosDate, string $timezone = null) : \DateTimeInterface
16
{
17
    // Bits 0-4: seconds / 2
18 2052
    $seconds = (($dosTime & 0x1F) << 1);
19
    // Bits 5-10: minutes
20 2052
    $minutes = (($dosTime >> 5) & 0x3F);
21
    // Bits 11-15: hours
22 2052
    $hours = (($dosTime >> 11) & 0x1F);
23
24
    // Bits 0-4: day
25 2052
    $day = ($dosDate & 0x1F);
26
    // Bits 5-8: month
27 2052
    $month = (($dosDate >> 5) & 0x0F);
28
    // Bits 9-15: year - 1980
29 2052
    $year = (($dosDate >> 9) & 0x7F) + 1980;
30
31 2052
    return new \DateTimeImmutable("$year-$month-$day $hours:$minutes:$seconds", new \DateTimeZone($timezone ? $timezone : \date_default_timezone_get()));
32
}
33
34
35
/**
36
 * Create dos time and date integers from datetime object.
37
 *
38
 * @param \DateTimeInterface $datetime
39
 * @return array
40
 */
41
 function dateTime2Dos(\DateTimeInterface $datetime) : array
42
{
43 1
    $year =(int)$datetime->format('Y');
44 1
    $month =(int)$datetime->format('n');
45 1
    $day =(int)$datetime->format('j');
46 1
    $hour =(int)$datetime->format('G');
47 1
    $minute =(int)$datetime->format('i');
48 1
    $second =(int)$datetime->format('s');
49
50 1
    if (($year === 1979) && ($month === 11) && ($day === 30)) {
51 1
        $day = 0;
52 1
        $month = 0;
53 1
        $year = 1980;
54
    }
55
56 1
    elseif (($year === 1979) && ($month === 12)) {
57
        $month = 0;
58
        $year = 1980;
59
    }
60
61 1
    elseif ($year < 1980) {
62
        throw new \InvalidArgumentException("DOS date and time can not represent dates before 1979-11-30");
63
    }
64
65
    $dosTime =
66 1
        ($second >> 1)
67 1
        + ($minute << 5)
68 1
        + ($hour << 11)
69
    ;
70
71
    $dosDate =
72
        $day
73 1
        + ($month << 5)
74 1
        + (($year - 1980) << 9)
75
    ;
76
77 1
    return [$dosTime, $dosDate, 'time' => $dosTime, 'date' => $dosDate];
78
}
79