1 | <?php |
||||
2 | |||||
3 | namespace Popy\Calendar\Converter\UnixTimeConverter; |
||||
4 | |||||
5 | use Popy\Calendar\Converter\Conversion; |
||||
6 | use Popy\Calendar\Converter\UnixTimeConverterInterface; |
||||
7 | use Popy\Calendar\Converter\CompleteLeapYearCalculatorInterface; |
||||
8 | use Popy\Calendar\ValueObject\DateSolarRepresentationInterface; |
||||
9 | |||||
10 | /** |
||||
11 | * Handles DateSolarRepresentationInterface. |
||||
12 | * |
||||
13 | * The eraDayIndex is calculated using an "eraStart" reference date. Year, year |
||||
14 | * length and leap days calculations are delegated to a LeapYearCalculator. |
||||
15 | */ |
||||
16 | class DateSolar implements UnixTimeConverterInterface |
||||
17 | { |
||||
18 | /** |
||||
19 | * Era start unix time. |
||||
20 | * |
||||
21 | * @var integer |
||||
22 | */ |
||||
23 | protected $eraStart; |
||||
24 | |||||
25 | /** |
||||
26 | * Day length in seconds. |
||||
27 | * |
||||
28 | * @var integer|float|string |
||||
29 | */ |
||||
30 | protected $dayLengthInSeconds = 24 * 3600; |
||||
31 | |||||
32 | /** |
||||
33 | * Leap year calculator. |
||||
34 | * |
||||
35 | * @var CompleteLeapYearCalculatorInterface |
||||
36 | */ |
||||
37 | protected $calculator; |
||||
38 | |||||
39 | /** |
||||
40 | * Class constructor. |
||||
41 | * |
||||
42 | * @param CompleteLeapYearCalculatorInterface $calculator Leap year calculator. |
||||
43 | * @param integer $eraStart Era start unix time. |
||||
44 | * @param integer|float|string|null $dayLengthInSeconds Day length in seconds. |
||||
45 | */ |
||||
46 | public function __construct(CompleteLeapYearCalculatorInterface $calculator, $eraStart, $dayLengthInSeconds = null) |
||||
47 | { |
||||
48 | $this->calculator = $calculator; |
||||
49 | $this->eraStart = $eraStart; |
||||
50 | |||||
51 | if (null !== $dayLengthInSeconds) { |
||||
52 | $this->dayLengthInSeconds = $dayLengthInSeconds; |
||||
53 | } |
||||
54 | } |
||||
55 | |||||
56 | /** |
||||
57 | * @inheritDoc |
||||
58 | */ |
||||
59 | public function fromUnixTime(Conversion $conversion) |
||||
60 | { |
||||
61 | if (!$conversion->getTo() instanceof DateSolarRepresentationInterface) { |
||||
62 | return; |
||||
63 | } |
||||
64 | |||||
65 | $res = $conversion->getTo(); |
||||
66 | |||||
67 | // TODO : remove code repetition by using a separate abstraction |
||||
68 | // handling basic math operations. |
||||
69 | |||||
70 | if (is_integer($this->dayLengthInSeconds)) { |
||||
71 | // bc not needed/not available |
||||
72 | |||||
73 | // Relative time from era start. |
||||
74 | $relativeTime = $conversion->getUnixTime() - $this->eraStart; |
||||
75 | |||||
76 | // Calculating global day index. Floor is used to properly handle |
||||
77 | // negative values |
||||
78 | $eraDayIndex = (int)floor($relativeTime / $this->dayLengthInSeconds); |
||||
79 | |||||
80 | $time = $relativeTime - $eraDayIndex * $this->dayLengthInSeconds; |
||||
81 | |||||
82 | // TODO : handle the loss as microseconds ? |
||||
83 | if (is_float($time)) { |
||||
0 ignored issues
–
show
introduced
by
![]() |
|||||
84 | $time = (int)ceil($time); |
||||
85 | } |
||||
86 | |||||
87 | $conversion->setUnixTime($time); |
||||
88 | } else { |
||||
89 | // Using bc math if available for non int dayLengthInSeconds in |
||||
90 | // order to stay as precise as possible. |
||||
91 | |||||
92 | // Relative time from era start. |
||||
93 | $relativeTime = bcsub($conversion->getUnixTime(), $this->eraStart); |
||||
94 | |||||
95 | // Calculating global day index. Floor is used to properly handle |
||||
96 | // negative values |
||||
97 | $eraDayIndex = floor( |
||||
98 | bcdiv($relativeTime, $this->dayLengthInSeconds) |
||||
0 ignored issues
–
show
bcdiv($relativeTime, $this->dayLengthInSeconds) of type string is incompatible with the type double expected by parameter $value of floor() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
99 | ); |
||||
100 | |||||
101 | // TODO : handle the loss as microseconds ? |
||||
102 | $time = ceil(bcsub( |
||||
0 ignored issues
–
show
bcsub($relativeTime, bcm...s->dayLengthInSeconds)) of type string is incompatible with the type double expected by parameter $value of ceil() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
103 | $relativeTime, |
||||
104 | bcmul($eraDayIndex, $this->dayLengthInSeconds) |
||||
105 | )); |
||||
106 | |||||
107 | $conversion->setUnixTime((int)$time); |
||||
108 | } |
||||
109 | |||||
110 | list($year, $dayIndex) = $this->calculator |
||||
111 | ->getYearAndDayIndexFromErayDayIndex($eraDayIndex) |
||||
0 ignored issues
–
show
It seems like
$eraDayIndex can also be of type double ; however, parameter $eraDayIndex of Popy\Calendar\Converter\...IndexFromErayDayIndex() does only seem to accept integer , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
112 | ; |
||||
113 | |||||
114 | $res = $res |
||||
115 | ->withYear($year, $this->calculator->isLeapYear($year)) |
||||
116 | ->withDayIndex($dayIndex, $eraDayIndex) |
||||
0 ignored issues
–
show
It seems like
$eraDayIndex can also be of type double ; however, parameter $eraDayIndex of Popy\Calendar\ValueObjec...terface::withDayIndex() does only seem to accept null|integer , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
117 | ; |
||||
118 | |||||
119 | $conversion->setTo($res); |
||||
120 | } |
||||
121 | |||||
122 | /** |
||||
123 | * @inheritDoc |
||||
124 | */ |
||||
125 | public function toUnixTime(Conversion $conversion) |
||||
126 | { |
||||
127 | $input = $conversion->getTo(); |
||||
128 | |||||
129 | if (!$input instanceof DateSolarRepresentationInterface) { |
||||
130 | return; |
||||
131 | } |
||||
132 | |||||
133 | $year = (int)$input->getYear(); |
||||
134 | $eraDayIndex = $input->getDayIndex() |
||||
135 | + $this->calculator->getYearEraDayIndex($year) |
||||
136 | ; |
||||
137 | |||||
138 | // TODO : BC Math implementation |
||||
139 | $conversion->setUnixTime(intval( |
||||
140 | $conversion->getUnixTime() + $this->eraStart |
||||
141 | + $eraDayIndex * $this->dayLengthInSeconds |
||||
142 | )); |
||||
143 | } |
||||
144 | } |
||||
145 |