Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
33.33% covered (danger)
33.33%
1 / 3
CRAP
76.60% covered (warning)
76.60%
36 / 47
DateSolar
0.00% covered (danger)
0.00%
0 / 1
33.33% covered (danger)
33.33%
1 / 3
10.04
76.60% covered (warning)
76.60%
36 / 47
 __construct
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
6 / 6
 fromUnixTime
0.00% covered (danger)
0.00%
0 / 1
6.03
65.52% covered (warning)
65.52%
19 / 29
 toUnixTime
0.00% covered (danger)
0.00%
0 / 1
2.00
91.67% covered (success)
91.67%
11 / 12
<?php
namespace Popy\Calendar\Converter\UnixTimeConverter;
use BCMathExtended\BC;
use Popy\Calendar\Converter\Conversion;
use Popy\Calendar\Converter\UnixTimeConverterInterface;
use Popy\Calendar\Converter\CompleteLeapYearCalculatorInterface;
use Popy\Calendar\ValueObject\DateSolarRepresentationInterface;
/**
 * Handles DateSolarRepresentationInterface.
 *
 * The eraDayIndex is calculated using an "eraStart" reference date. Year, year
 * length and leap days calculations are delegated to a LeapYearCalculator.
 */
class DateSolar implements UnixTimeConverterInterface
{
    /**
     * Era start unix time.
     *
     * @var integer
     */
    protected $eraStart;
    /**
     * Day length in seconds.
     *
     * @var integer|float|string
     */
    protected $dayLengthInSeconds = 24 * 3600;
    /**
     * Leap year calculator.
     *
     * @var CompleteLeapYearCalculatorInterface
     */
    protected $calculator;
    /**
     * Class constructor.
     *
     * @param CompleteLeapYearCalculatorInterface $calculator         Leap year calculator.
     * @param integer                     $eraStart           Era start unix time.
     * @param integer|float|string|null   $dayLengthInSeconds Day length in seconds.
     */
    public function __construct(CompleteLeapYearCalculatorInterface $calculator, $eraStart, $dayLengthInSeconds = null)
    {
        $this->calculator = $calculator;
        $this->eraStart   = $eraStart;
        if (null !== $dayLengthInSeconds) {
            $this->dayLengthInSeconds = $dayLengthInSeconds;
        }
    }
    /**
     * @inheritDoc
     */
    public function fromUnixTime(Conversion $conversion)
    {
        if (!$conversion->getTo() instanceof DateSolarRepresentationInterface) {
            return;
        }
        $res = $conversion->getTo();
        // TODO : remove code repetition by using a separate abstraction
        // handling basic math operations.
        if (is_integer($this->dayLengthInSeconds) || !class_exists(BC::class)) {
            // bc not needed/not available
            // Relative time from era start.
            $relativeTime = $conversion->getUnixTime() - $this->eraStart;
            // Calculating global day index. Floor is used to properly handle
            // negative values
            $eraDayIndex = (int)floor($relativeTime / $this->dayLengthInSeconds);
            $time = $relativeTime - $eraDayIndex * $this->dayLengthInSeconds;
            // TODO : handle the loss as microseconds ?
            if (is_float($time)) {
                $time = (int)ceil($time);
            }
            $conversion->setUnixTime($time);
        } else {
            // Using bc math if available for non int dayLengthInSeconds in
            // order to stay as precise as possible.
            // Relative time from era start.
            $relativeTime = bcsub($conversion->getUnixTime(), $this->eraStart);
            // Calculating global day index. Floor is used to properly handle
            // negative values
            $eraDayIndex = BC::floor(
                bcdiv($relativeTime, $this->dayLengthInSeconds)
            );
            // TODO : handle the loss as microseconds ?
            $time = BC::ceil(bcsub(
                $relativeTime,
                bcmul($eraDayIndex, $this->dayLengthInSeconds)
            ));
            $conversion->setUnixTime((int)$time);
        }
        list($year, $dayIndex) = $this->calculator
            ->getYearAndDayIndexFromErayDayIndex($eraDayIndex)
        ;
        $res = $res
            ->withYear($year, $this->calculator->isLeapYear($year))
            ->withDayIndex($dayIndex, $eraDayIndex)
        ;
        $conversion->setTo($res);
    }
    /**
     * @inheritDoc
     */
    public function toUnixTime(Conversion $conversion)
    {
        $input = $conversion->getTo();
        if (!$input instanceof DateSolarRepresentationInterface) {
            return;
        }
        $year = $input->getYear();
        $eraDayIndex = $input->getDayIndex()
            + $this->calculator->getYearEraDayIndex($year)
        ;
        // TODO : BC Math implementation
        $conversion->setUnixTime(intval(
            $conversion->getUnixTime() + $this->eraStart
            + $eraDayIndex * $this->dayLengthInSeconds
        ));
    }
}