1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Eclipxe\XlsxExporter; |
6
|
|
|
|
7
|
|
|
class DateConverter |
8
|
|
|
{ |
9
|
|
|
public const TIME = 'TIME'; |
10
|
|
|
|
11
|
|
|
public const DATE = 'DATE'; |
12
|
|
|
|
13
|
|
|
public const DATETIME = 'DATETIME'; |
14
|
|
|
|
15
|
|
|
public const PRECISION_TIME = 6; |
16
|
|
|
|
17
|
|
|
public const PRECISION_POW = 10 ** self::PRECISION_TIME; |
18
|
|
|
|
19
|
3 |
|
public static function tsToExcel(int $timestamp, string $type): string |
20
|
|
|
{ |
21
|
3 |
|
if (self::TIME === $type) { |
22
|
1 |
|
return static::tsToExcelTime($timestamp); |
23
|
|
|
} |
24
|
2 |
|
if (self::DATE === $type) { |
25
|
1 |
|
return static::tsToExcelDate($timestamp); |
26
|
|
|
} |
27
|
1 |
|
return static::tsToExcelDateTime($timestamp); |
28
|
|
|
} |
29
|
|
|
|
30
|
9 |
|
public static function tsToExcelTime(int $timestamp): string |
31
|
|
|
{ |
32
|
9 |
|
$utc = static::utcParts($timestamp); |
33
|
|
|
// return number_format((($utc[3] * 3600) + ($utc[4] * 60) + $utc[5]) / 86400, static::PRECISION_TIME, '.', ''); |
34
|
9 |
|
return number_format(self::roundTime($utc[3], $utc[4], $utc[5]), static::PRECISION_TIME, '.', ''); |
35
|
|
|
} |
36
|
|
|
|
37
|
9 |
|
public static function roundTime(int $hours, int $minutes, int $seconds): float |
38
|
|
|
{ |
39
|
9 |
|
$relative = ($hours * 3600 + $minutes * 60 + $seconds) / 86400; |
40
|
9 |
|
return ceil(round(self::PRECISION_POW * $relative, 2)) / self::PRECISION_POW; |
41
|
|
|
} |
42
|
|
|
|
43
|
8 |
|
public static function tsToExcelDate(int $timestamp): string |
44
|
|
|
{ |
45
|
8 |
|
$utc = static::utcParts($timestamp); |
46
|
|
|
// Bug 1900 is not a leap year |
47
|
|
|
// http://support.microsoft.com/kb/214326 |
48
|
8 |
|
$delta = (1900 == $utc[0] && $utc[1] <= 2) ? -1 : 0; |
49
|
8 |
|
return (string) ((int) (25569 + $delta + (($timestamp + $utc[6]) / 86400))); |
50
|
|
|
} |
51
|
|
|
|
52
|
6 |
|
public static function tsToExcelDateTime(int $timestamp): string |
53
|
|
|
{ |
54
|
6 |
|
return number_format( |
55
|
6 |
|
(int) static::tsToExcelDate($timestamp) + (float) static::tsToExcelTime($timestamp), |
56
|
6 |
|
static::PRECISION_TIME, |
57
|
6 |
|
'.', |
58
|
6 |
|
'' |
59
|
6 |
|
); |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* @return array{int, int, int, int, int, int, int} |
|
|
|
|
64
|
|
|
*/ |
65
|
11 |
|
public static function utcParts(int $timestamp): array |
66
|
|
|
{ |
67
|
11 |
|
$offset = idate('Z', $timestamp); |
68
|
|
|
/** @var array{string, string, string, string, string, string, string} $values */ |
69
|
11 |
|
$values = explode(',', gmdate('Y,m,d,H,i,s', $timestamp + $offset) . ',' . $offset); |
70
|
11 |
|
return array_map('intval', $values); |
71
|
|
|
} |
72
|
|
|
} |
73
|
|
|
|