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
|
|
|
|