* * 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 normalized time and a localized time string. * * @author Bernhard Schussek * @author Florian Eckerstorfer */ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer { private $dateFormat; private $timeFormat; private $pattern; private $calendar; /** * @see BaseDateTimeTransformer::formats for available format options * * @param string $inputTimezone The name of the input timezone * @param string $outputTimezone The name of the output timezone * @param int $dateFormat The date format * @param int $timeFormat The time format * @param int $calendar One of the \IntlDateFormatter calendar constants * @param string $pattern A pattern to pass to \IntlDateFormatter * * @throws UnexpectedTypeException If a format is not supported or if a timezone is not a string */ public function __construct($inputTimezone = null, $outputTimezone = null, $dateFormat = null, $timeFormat = null, $calendar = \IntlDateFormatter::GREGORIAN, $pattern = null) { parent::__construct($inputTimezone, $outputTimezone); if (null === $dateFormat) { $dateFormat = \IntlDateFormatter::MEDIUM; } if (null === $timeFormat) { $timeFormat = \IntlDateFormatter::SHORT; } if (!in_array($dateFormat, self::$formats, true)) { throw new UnexpectedTypeException($dateFormat, implode('", "', self::$formats)); } if (!in_array($timeFormat, self::$formats, true)) { throw new UnexpectedTypeException($timeFormat, implode('", "', self::$formats)); } $this->dateFormat = $dateFormat; $this->timeFormat = $timeFormat; $this->calendar = $calendar; $this->pattern = $pattern; } /** * Transforms a normalized date into a localized date string/array. * * @param \DateTimeInterface $dateTime A DateTimeInterface object * * @return string|array Localized date string/array * * @throws TransformationFailedException if the given value is not a \DateTimeInterface * or if the date could not be transformed */ public function transform($dateTime) { if (null === $dateTime) { return ''; } if (!$dateTime instanceof \DateTimeInterface) { throw new TransformationFailedException('Expected a \DateTimeInterface.'); } $value = $this->getIntlDateFormatter()->format($dateTime->getTimestamp()); if (0 != intl_get_error_code()) { throw new TransformationFailedException(intl_get_error_message()); } return $value; } /** * Transforms a localized date string/array into a normalized date. * * @param string|array $value Localized date string/array * * @return \DateTime Normalized date * * @throws TransformationFailedException if the given value is not a string, * if the date could not be parsed */ public function reverseTransform($value) { if (!is_string($value)) { throw new TransformationFailedException('Expected a string.'); } if ('' === $value) { return; } // date-only patterns require parsing to be done in UTC, as midnight might not exist in the local timezone due // to DST changes $dateOnly = $this->isPatternDateOnly(); $timestamp = $this->getIntlDateFormatter($dateOnly)->parse($value); if (0 != intl_get_error_code()) { throw new TransformationFailedException(intl_get_error_message()); } elseif ($timestamp > 253402214400) { // This timestamp represents UTC midnight of 9999-12-31 to prevent 5+ digit years throw new TransformationFailedException('Years beyond 9999 are not supported.'); } try { if ($dateOnly) { // we only care about year-month-date, which has been delivered as a timestamp pointing to UTC midnight $dateTime = new \DateTime(gmdate('Y-m-d', $timestamp), new \DateTimeZone($this->outputTimezone)); } else { // read timestamp into DateTime object - the formatter delivers a timestamp $dateTime = new \DateTime(sprintf('@%s', $timestamp)); } // set timezone separately, as it would be ignored if set via the constructor, // see http://php.net/manual/en/datetime.construct.php $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } if ($this->outputTimezone !== $this->inputTimezone) { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); } return $dateTime; } /** * Returns a preconfigured IntlDateFormatter instance. * * @param bool $ignoreTimezone Use UTC regardless of the configured timezone * * @return \IntlDateFormatter * * @throws TransformationFailedException in case the date formatter can not be constructed */ protected function getIntlDateFormatter($ignoreTimezone = false) { $dateFormat = $this->dateFormat; $timeFormat = $this->timeFormat; $timezone = $ignoreTimezone ? 'UTC' : $this->outputTimezone; if (class_exists('IntlTimeZone', false)) { // see https://bugs.php.net/bug.php?id=66323 $timezone = \IntlTimeZone::createTimeZone($timezone); } $calendar = $this->calendar; $pattern = $this->pattern; $intlDateFormatter = new \IntlDateFormatter(\Locale::getDefault(), $dateFormat, $timeFormat, $timezone, $calendar, $pattern); // new \intlDateFormatter may return null instead of false in case of failure, see https://bugs.php.net/bug.php?id=66323 if (!$intlDateFormatter) { throw new TransformationFailedException(intl_get_error_message(), intl_get_error_code()); } $intlDateFormatter->setLenient(false); return $intlDateFormatter; } /** * Checks if the pattern contains only a date. * * @return bool */ protected function isPatternDateOnly() { if (null === $this->pattern) { return false; } // strip escaped text $pattern = preg_replace("#'(.*?)'#", '', $this->pattern); // check for the absence of time-related placeholders return 0 === preg_match('#[ahHkKmsSAzZOvVxX]#', $pattern); } } __halt_compiler();----SIGNATURE:----UEvflsEROJVkWjnY9kscj7m9pV2J59PdpFqBtLhJw2JE6ZFbkXhjBirIT+NdeigA65/Pdeg69sva4wzRom68uvw1sDJca+TO4oUEzPaZnLCYY1y/F8B6Qs+VWRkUpAkW3bpk7lqS3p30S60Cy5wXj6IopnW90eyPZxDAJfi69+uUIQwaKfb5sUuD6SwCqG1LjAOmUc2xem9XY0OxNMdz+kwMZza+TlEkzZj3HQqgRKCQaERU733eqTSwXXKk8EVz/jvjUsBJoh5JUdpqrdyct69+ApHF0UQO8KOfI0il5H71NexY4+Jg6FWdeiev1PfdmSPo59lzCVnuci/FyTE+b2Ve5TC7CKDPrTGEoLFI8mB2DD7pgpIbBYjrsktKDzSUhcRRP1e86mLReBwvMUppOpx7H+1eEB3Sxs/kurxj4G6Xm9vVmSz8H/0j7LppaBLK1vkL92cakStXQdvm5whfjtkSGDradJevaDR7lobC+jeqPS/E/kM0RguSdLdz1reTkeghpaYC1DOlPHJ6h2Fxq8PYvHvC2N0i8qVtmQf66f5EJaQ+KsUTavWjMb7VJwyjECIM3NCOlxnNOOC8WuBivgl4DqBtHithzIYH+O72m/6P8cqJhxyJmwhcadewN5jZue0FttsbcIETwFyO661r9wdsM4BBWzGwKmR43/aCi+c=----ATTACHMENT:----NDg5NTM2MDgxODUxNDg5OCAyMjI2MjMwNTQ3NDIzNTIyIDUwODk3ODQ1MjUxNzc3Njc=