/vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php
PHP | 231 lines | 119 code | 26 blank | 86 comment | 21 complexity | e2ef91059fde6a6d4415e7d8395e538c MD5 | raw file
- <?php
- /*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- namespace Symfony\Component\Form\Extension\Core\DataTransformer;
- use Symfony\Component\Form\Exception\TransformationFailedException;
- use Symfony\Component\Form\Exception\UnexpectedTypeException;
- /**
- * Transforms between a date string and a DateTime object.
- *
- * @author Bernhard Schussek <bschussek@gmail.com>
- * @author Florian Eckerstorfer <florian@eckerstorfer.org>
- */
- class DateTimeToStringTransformer extends BaseDateTimeTransformer
- {
- /**
- * Format used for generating strings.
- *
- * @var string
- */
- private $generateFormat;
- /**
- * Format used for parsing strings.
- *
- * Different than the {@link $generateFormat} because formats for parsing
- * support additional characters in PHP that are not supported for
- * generating strings.
- *
- * @var string
- */
- private $parseFormat;
- /**
- * Whether to parse by appending a pipe "|" to the parse format.
- *
- * This only works as of PHP 5.3.7.
- *
- * @var bool
- */
- private $parseUsingPipe;
- /**
- * Transforms a \DateTime instance to a string.
- *
- * @see \DateTime::format() for supported formats
- *
- * @param string $inputTimezone The name of the input timezone
- * @param string $outputTimezone The name of the output timezone
- * @param string $format The date format
- * @param bool $parseUsingPipe Whether to parse by appending a pipe "|" to the parse format
- *
- * @throws UnexpectedTypeException if a timezone is not a string
- */
- public function __construct($inputTimezone = null, $outputTimezone = null, $format = 'Y-m-d H:i:s', $parseUsingPipe = true)
- {
- parent::__construct($inputTimezone, $outputTimezone);
- $this->generateFormat = $this->parseFormat = $format;
- $this->parseUsingPipe = $parseUsingPipe || null === $parseUsingPipe;
- // See http://php.net/manual/en/datetime.createfromformat.php
- // The character "|" in the format makes sure that the parts of a date
- // that are *not* specified in the format are reset to the corresponding
- // values from 1970-01-01 00:00:00 instead of the current time.
- // Without "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 12:32:47",
- // where the time corresponds to the current server time.
- // With "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 00:00:00",
- // which is at least deterministic and thus used here.
- if ($this->parseUsingPipe && false === strpos($this->parseFormat, '|')) {
- $this->parseFormat .= '|';
- }
- }
- /**
- * Transforms a DateTime object into a date string with the configured format
- * and timezone.
- *
- * @param \DateTime|\DateTimeInterface $dateTime A DateTime object
- *
- * @return string A value as produced by PHP's date() function
- *
- * @throws TransformationFailedException If the given value is not a \DateTime
- * instance or if the output timezone
- * is not supported.
- */
- public function transform($value)
- {
- if (null === $value) {
- return '';
- }
- if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
- throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.');
- }
- if (!$value instanceof \DateTimeImmutable) {
- $value = clone $value;
- }
- try {
- $value = $value->setTimezone(new \DateTimeZone($this->outputTimezone));
- } catch (\Exception $e) {
- throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
- }
- return $value->format($this->generateFormat);
- }
- /**
- * Transforms a date string in the configured timezone into a DateTime object.
- *
- * @param string $value A value as produced by PHP's date() function
- *
- * @return \DateTime An instance of \DateTime
- *
- * @throws TransformationFailedException If the given value is not a string,
- * if the date could not be parsed or
- * if the input timezone is not supported.
- */
- public function reverseTransform($value)
- {
- if (empty($value)) {
- return;
- }
- if (!is_string($value)) {
- throw new TransformationFailedException('Expected a string.');
- }
- try {
- $outputTz = new \DateTimeZone($this->outputTimezone);
- $dateTime = \DateTime::createFromFormat($this->parseFormat, $value, $outputTz);
- $lastErrors = \DateTime::getLastErrors();
- if (0 < $lastErrors['warning_count'] || 0 < $lastErrors['error_count']) {
- throw new TransformationFailedException(
- implode(', ', array_merge(
- array_values($lastErrors['warnings']),
- array_values($lastErrors['errors'])
- ))
- );
- }
- // On PHP versions < 5.3.7 we need to emulate the pipe operator
- // and reset parts not given in the format to their equivalent
- // of the UNIX base timestamp.
- if (!$this->parseUsingPipe) {
- list($year, $month, $day, $hour, $minute, $second) = explode('-', $dateTime->format('Y-m-d-H-i-s'));
- // Check which of the date parts are present in the pattern
- preg_match(
- '/('.
- '(?P<day>[djDl])|'.
- '(?P<month>[FMmn])|'.
- '(?P<year>[Yy])|'.
- '(?P<hour>[ghGH])|'.
- '(?P<minute>i)|'.
- '(?P<second>s)|'.
- '(?P<dayofyear>z)|'.
- '(?P<timestamp>U)|'.
- '[^djDlFMmnYyghGHiszU]'.
- ')*/',
- $this->parseFormat,
- $matches
- );
- // preg_match() does not guarantee to set all indices, so
- // set them unless given
- $matches = array_merge(array(
- 'day' => false,
- 'month' => false,
- 'year' => false,
- 'hour' => false,
- 'minute' => false,
- 'second' => false,
- 'dayofyear' => false,
- 'timestamp' => false,
- ), $matches);
- // Reset all parts that don't exist in the format to the
- // corresponding part of the UNIX base timestamp
- if (!$matches['timestamp']) {
- if (!$matches['dayofyear']) {
- if (!$matches['day']) {
- $day = 1;
- }
- if (!$matches['month']) {
- $month = 1;
- }
- }
- if (!$matches['year']) {
- $year = 1970;
- }
- if (!$matches['hour']) {
- $hour = 0;
- }
- if (!$matches['minute']) {
- $minute = 0;
- }
- if (!$matches['second']) {
- $second = 0;
- }
- $dateTime->setDate($year, $month, $day);
- $dateTime->setTime($hour, $minute, $second);
- }
- }
- if ($this->inputTimezone !== $this->outputTimezone) {
- $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone));
- }
- } catch (TransformationFailedException $e) {
- throw $e;
- } catch (\Exception $e) {
- throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
- }
- return $dateTime;
- }
- }