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