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
92.68% covered (success)
92.68%
38 / 41
StandardDate
0.00% covered (danger)
0.00%
0 / 1
33.33% covered (danger)
33.33%
1 / 3
12.06
92.68% covered (success)
92.68%
38 / 41
 map
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
10 / 10
 determineOffset
0.00% covered (danger)
0.00%
0 / 1
7.03
91.67% covered (success)
91.67%
22 / 24
 determineTimezone
0.00% covered (danger)
0.00%
0 / 1
4.05
85.71% covered (warning)
85.71%
6 / 7
<?php
namespace Popy\Calendar\Parser\ResultMapper;
use DateTimeZone;
use Popy\Calendar\Parser\DateLexerResult;
use Popy\Calendar\ValueObject\TimeOffset;
use Popy\Calendar\Parser\ResultMapperInterface;
use Popy\Calendar\ValueObject\DateRepresentationInterface;
/**
 * Maps standard format symbols to DateRepresentationInterface fields.
 */
class StandardDate implements ResultMapperInterface
{
    /**
     * @inheritDoc
     */
    public function map(DateLexerResult $parts, DateRepresentationInterface $date)
    {
        $offset = $this->determineOffset($parts, $date->getOffset());
        return $date
            // SI Units
            // U   Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
            // u   Microseconds
            ->withUnixTime($parts->get('U'))
            ->withUnixMicroTime($parts->get('u'))
            // Offset & timezone
            ->withOffset($offset)
            ->withTimezone($this->determineTimezone(
                $parts,
                $offset,
                $date->getTimezone()
            ))
        ;
    }
    /**
     * Determine date's offset value/dst/abbrevaition from lexer result,
     * overriding only if a value is found.
     *
     * @param DateLexerResult $parts  Lexer result.
     * @param TimeOffset      $offset Current date offset.
     *
     * @return TimeOffset
     */
    protected function determineOffset(DateLexerResult $parts, TimeOffset $offset)
    {
        // Z   Timezone offset in seconds.
        if (null !== $value = $parts->get('Z')) {
            $value = (int)$value;
        } elseif (null !== $o = $parts->getFirst('O', 'P')) {
            // O   Difference to Greenwich time (GMT) in hours Example: +0200
            // P   Difference to Greenwich time (GMT) with colon between hours and minutes
            $o = str_replace(':', '', $o);
            $sign = substr($o, 0, 1);
            $hours = (int)substr($o, 1, 2);
            $minutes = (int)substr($o, 3, 2);
            $o = $hours * 60 + $minutes;
            $o = $o * 60;
            if ($sign === '-') {
                $o = -$o;
            }
            $value = $o;
        }
        if (null !== $value) {
            $offset = $offset->withValue($value);
        }
        // I (capital i) Whether or not the date is in daylight saving time
        if (null !== $t = $parts->get('I')) {
            $offset = $offset->withDst($t);
        }
        
        // T   Timezone abbreviation   Examples: EST, MDT ...
        if (null !== $t = $parts->get('T')) {
            $offset = $offset->withAbbreviation($t);
        }
        return $offset;
    }
    /**
     * Determine date's timezone. If an offset has been found, Timezone has
     * no effect on the date parsing, but will have on the date display.
     *
     * @param DateLexerResult $parts   Date lexer results.
     * @param integer|null    $offset  Date offset if it has been found.
     * @param DateTimeZone    $inputTz Default timezone if any.
     *
     * @return DateTimeZone
     */
    protected function determineTimezone(DateLexerResult $parts, TimeOffset $offset, DateTimeZone $inputTz)
    {
        // e   Timezone identifier (added in PHP 5.1.0)    Examples: UTC, GMT, Atlantic/Azores
        // O   Difference to Greenwich time (GMT) in hours Example: +0200
        // P   Difference to Greenwich time (GMT) with colon between hours and minutes (added in PHP 5.1.3)    Example: +02:00
        if (null !== $tz = $parts->getFirst('e', 'O', 'P')) {
            return new DateTimeZone($tz);
        }
        // Create a fixed timezone matching the offset.
        if (null !== $tz = $offset->buildTimeZone()) {
            return $tz;
        }
        if (null !== $inputTz) {
            return $inputTz;
        }
        // Fallback.
        return new DateTimeZone(date_default_timezone_get());
    }
}