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
84.85% covered (warning)
84.85%
56 / 66
Iso8601Weeks
0.00% covered (danger)
0.00%
0 / 1
33.33% covered (danger)
33.33%
1 / 3
18.01
84.85% covered (warning)
84.85%
56 / 66
 __construct
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
5 / 5
 fromUnixTime
0.00% covered (danger)
0.00%
0 / 1
6.20
82.14% covered (warning)
82.14%
23 / 28
 toUnixTime
0.00% covered (danger)
0.00%
0 / 1
9.28
84.85% covered (warning)
84.85%
28 / 33
<?php
namespace Popy\Calendar\Converter\UnixTimeConverter;
use Popy\Calendar\Converter\Conversion;
use Popy\Calendar\Converter\UnixTimeConverterInterface;
use Popy\Calendar\Converter\CompleteLeapYearCalculatorInterface;
use Popy\Calendar\ValueObject\DateSolarRepresentationInterface;
use Popy\Calendar\ValueObject\DateFragmentedRepresentationInterface;
/**
 * Implementation of the standard (gregorian like) month calculation.
 */
class Iso8601Weeks implements UnixTimeConverterInterface
{
    /**
     * Leap year calculator.
     *
     * @var CompleteLeapYearCalculatorInterface
     */
    protected $calculator;
    /**
     * First day of first year weekday index. 1970 started a thursday.
     *
     * @var integer
     */
    protected $firstYearDayIndex = 3;
    /**
     * Class constructor.
     *
     * @param CompleteLeapYearCalculatorInterface $calculator         Leap year calculator.
     * @param integer|null                        $firstYearDayIndex  First day of first year weekday index.
     */
    public function __construct(CompleteLeapYearCalculatorInterface $calculator, $firstYearDayIndex = null)
    {
        $this->calculator = $calculator;
        if (null !== $firstYearDayIndex) {
            $this->firstYearDayIndex = $firstYearDayIndex;
        }
    }
    /**
     * @inheritDoc
     */
    public function fromUnixTime(Conversion $conversion)
    {
        $input = $conversion->getTo();
        if (
            !$input instanceof DateFragmentedRepresentationInterface
            || !$input instanceof DateSolarRepresentationInterface
        ) {
            return;
        }
        $year = $input->getYear();
        // Assuming the era starting year is 1970, it starts a Thursday.
        $dayOfWeek = ($input->getEraDayIndex() + $this->firstYearDayIndex) % 7;
        // dayOfWeek may be negative is eraDayIndex was negative
        if ($dayOfWeek < 0) {
            $dayOfWeek += 7;
        }
        $weekIndex = null;
        // Get day yearl-index of the same week thursday
        $thursdayIndex = $input->getDayIndex() + 3 - $dayOfWeek;
        if ($thursdayIndex >= $this->calculator->getYearLength($year)) {
            $year++;
            $weekIndex = 0;
            $thursdayIndex -= $this->calculator->getYearLength($year);
        } else {
            if ($thursdayIndex < 0) {
                $year--;
                $thursdayIndex =
                    $this->calculator->getYearLength($year)
                    + $thursdayIndex
                ;
            }
            $weekIndex = intval($thursdayIndex / 7);
        }
        $dateParts = $input->getDateParts()->withTransversals([
            $year,
            $weekIndex,
            $dayOfWeek
        ]);
        $conversion->setTo($input->withDateParts($dateParts));
    }
    /**
     * @inheritDoc
     */
    public function toUnixTime(Conversion $conversion)
    {
        $input = $conversion->getTo();
        if (
            !$input instanceof DateFragmentedRepresentationInterface
            || !$input instanceof DateSolarRepresentationInterface
        ) {
            return;
        }
        if (null !== $input->getDayIndex() && null !== $input->getYear()) {
            return ;
        }
        $year = $input->getDateParts()->getTransversal(0);
        $weekIndex = $input->getDateParts()->getTransversal(1);
        $dayOfWeek = $input->getDateParts()->getTransversal(2);
        if (null === $year || null === $weekIndex) {
            // Too imprecise to be worth
            return;
        }
        $startingEraDayIndex = $this->calculator->getYearEraDayIndex($year);
        // DoW of the first day of year
        $dow = ($startingEraDayIndex + $this->firstYearDayIndex) % 7;
        // walk until first thursday
        $eraDayIndex = $startingEraDayIndex + (10 - $dow) % 7;
        // Now eraDayIndex points on the thursday of the week #0. Lets go to the
        // weekIndex, and move to the dayOfWeek
        $eraDayIndex += $weekIndex * 7 + $dayOfWeek - 3;
        $dayIndex = $eraDayIndex - $startingEraDayIndex;
        if ($dayIndex < 0) {
            $year--;
            $eraDayIndex += $this->calculator->getYearLength($year);
            $dayIndex = $eraDayIndex - $startingEraDayIndex;
        } else {
            $yl = $this->calculator->getYearLength($year);
            if ($dayIndex >= $yl) {
                $year++;
                $dayIndex -= $yl;
                $eraDayIndex += $yl;
            }
        }
        $isLeapYear = $this->calculator->isLeapYear($year);
        $input = $input
            ->withYear($year, $isLeapYear)
            ->withDayIndex($dayIndex, $eraDayIndex)
        ;
        $conversion->setTo($input);
    }
}