popy-dev /
popy-calendar
| 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
Loading history...
|
|||||
| 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
Loading history...
|
|||||
| 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
Loading history...
|
|||||
| 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
Loading history...
|
|||||
| 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
Loading history...
|
|||||
| 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 |