Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

600 lines (534 sloc) 20.058 kb
<?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\Locale\Stub;
use Symfony\Component\Locale\Stub\StubLocale;
use Symfony\Component\Locale\Stub\DateFormat\FullTransformer;
use Symfony\Component\Locale\Exception\NotImplementedException;
use Symfony\Component\Locale\Exception\MethodNotImplementedException;
use Symfony\Component\Locale\Exception\MethodArgumentNotImplementedException;
use Symfony\Component\Locale\Exception\MethodArgumentValueNotImplementedException;
/**
* Provides a stub IntlDateFormatter for the 'en' locale.
*
* @author Igor Wiedler <igor@wiedler.ch>
*/
class StubIntlDateFormatter
{
/**
* The error code from the last operation
*
* @var integer
*/
protected $errorCode = StubIntl::U_ZERO_ERROR;
/**
* The error message from the last operation
*
* @var string
*/
protected $errorMessage = 'U_ZERO_ERROR';
/* date/time format types */
const NONE = -1;
const FULL = 0;
const LONG = 1;
const MEDIUM = 2;
const SHORT = 3;
/* calendar formats */
const TRADITIONAL = 0;
const GREGORIAN = 1;
/**
* Patterns used to format the date when no pattern is provided
*
* @var array
*/
private $defaultDateFormats = array(
self::NONE => '',
self::FULL => 'EEEE, LLLL d, y',
self::LONG => 'LLLL d, y',
self::MEDIUM => 'LLL d, y',
self::SHORT => 'M/d/yy',
);
/**
* Patterns used to format the time when no pattern is provided
*
* @var array
*/
private $defaultTimeFormats = array(
self::FULL => 'h:mm:ss a zzzz',
self::LONG => 'h:mm:ss a z',
self::MEDIUM => 'h:mm:ss a',
self::SHORT => 'h:mm a',
);
/**
* @var int
*/
private $datetype;
/**
* @var int
*/
private $timetype;
/**
* @var string
*/
private $pattern;
/**
* @var DateTimeZone
*/
private $dateTimeZone;
/**
* @var Boolean
*/
private $unitializedTimeZoneId = false;
/**
* @var string
*/
private $timeZoneId;
/**
* Constructor
*
* @param string $locale The locale code
* @param int $datetype Type of date formatting, one of the format type constants
* @param int $timetype Type of time formatting, one of the format type constants
* @param string $timezone Timezone identifier
* @param int $calendar Calendar to use for formatting or parsing; default is Gregorian.
* One of the calendar constants.
* @param string $pattern Optional pattern to use when formatting
*
* @see http://www.php.net/manual/en/intldateformatter.create.php
* @see http://userguide.icu-project.org/formatparse/datetime
*
* @throws MethodArgumentValueNotImplementedException When $locale different than 'en' is passed
* @throws MethodArgumentValueNotImplementedException When $calendar different than GREGORIAN is passed
*/
public function __construct($locale, $datetype, $timetype, $timezone = null, $calendar = self::GREGORIAN, $pattern = null)
{
if ('en' !== $locale) {
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'locale', $locale, 'Only the \'en\' locale is supported');
}
if (self::GREGORIAN !== $calendar) {
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'calendar', $calendar, 'Only the GREGORIAN calendar is supported');
}
$this->datetype = $datetype;
$this->timetype = $timetype;
$this->setPattern($pattern);
$this->setTimeZoneId($timezone);
}
/**
* Static constructor
*
* @param string $locale The locale code
* @param int $datetype Type of date formatting, one of the format type constants
* @param int $timetype Type of time formatting, one of the format type constants
* @param string $timezone Timezone identifier
* @param int $calendar Calendar to use for formatting or parsing; default is Gregorian.
* One of the calendar constants.
* @param string $pattern Optional pattern to use when formatting
*
* @see http://www.php.net/manual/en/intldateformatter.create.php
* @see http://userguide.icu-project.org/formatparse/datetime
*
* @throws MethodArgumentValueNotImplementedException When $locale different than 'en' is passed
*/
public static function create($locale, $datetype, $timetype, $timezone = null, $calendar = self::GREGORIAN, $pattern = null)
{
return new self($locale, $datetype, $timetype, $timezone, $calendar, $pattern);
}
/**
* Format the date/time value (timestamp) as a string
*
* @param mixed $timestamp Unix timestamp to format
*
* @return string The formatted value
*
* @see http://www.php.net/manual/en/intldateformatter.format.php
*
* @throws NotImplementedException If one of the formatting characters is not implemented
*/
public function format($timestamp)
{
// intl allows timestamps to be passed as arrays - we don't
if (is_array($timestamp)) {
$message = version_compare(\PHP_VERSION, '5.3.4', '>=') ?
'Only integer unix timestamps and DateTime objects are supported' :
'Only integer unix timestamps are supported';
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'timestamp', $timestamp, $message);
}
// behave like the intl extension
$argumentError = null;
if (version_compare(\PHP_VERSION, '5.3.4', '<') && !is_int($timestamp)) {
$argumentError = 'datefmt_format: takes either an array or an integer timestamp value ';
} elseif (version_compare(\PHP_VERSION, '5.3.4', '>=') && !is_int($timestamp) && !$timestamp instanceof \DateTime) {
$argumentError = 'datefmt_format: takes either an array or an integer timestamp value or a DateTime object';
if (version_compare(\PHP_VERSION, '5.5.0-dev', '>=') && !is_int($timestamp)) {
$argumentError = sprintf('datefmt_format: string \'%s\' is not numeric, which would be required for it to be a valid date', $timestamp);
}
}
if (null !== $argumentError) {
StubIntl::setError(StubIntl::U_ILLEGAL_ARGUMENT_ERROR, $argumentError);
$this->errorCode = StubIntl::getErrorCode();
$this->errorMessage = StubIntl::getErrorMessage();
return false;
}
// As of PHP 5.3.4, IntlDateFormatter::format() accepts DateTime instances
if (version_compare(\PHP_VERSION, '5.3.4', '>=') && $timestamp instanceof \DateTime) {
$timestamp = $timestamp->getTimestamp();
}
$transformer = new FullTransformer($this->getPattern(), $this->getTimeZoneId());
$formatted = $transformer->format($this->createDateTime($timestamp));
// behave like the intl extension
StubIntl::setError(StubIntl::U_ZERO_ERROR);
$this->errorCode = StubIntl::getErrorCode();
$this->errorMessage = StubIntl::getErrorMessage();
return $formatted;
}
/**
* Formats an object
*
* @param object $object
* @param mixed $format
* @param string $locale
*
* @return string The formatted value
*
* @see http://www.php.net/manual/en/intldateformatter.formatobject.php
*
* @throws MethodNotImplementedException
*/
public function formatObject($object, $format = null, $locale = null)
{
throw new MethodNotImplementedException(__METHOD__);
}
/**
* Returns the formatter's calendar
*
* @return int The calendar being used by the formatter
*
* @see http://www.php.net/manual/en/intldateformatter.getcalendar.php
*/
public function getCalendar()
{
return self::GREGORIAN;
}
/**
* Returns the formatter's calendar object
*
* @return object The calendar's object being used by the formatter
*
* @see http://www.php.net/manual/en/intldateformatter.getcalendarobject.php
*
* @throws MethodNotImplementedException
*/
public function getCalendarObject()
{
throw new MethodNotImplementedException(__METHOD__);
}
/**
* Returns the formatter's datetype
*
* @return int The current value of the formatter
*
* @see http://www.php.net/manual/en/intldateformatter.getdatetype.php
*/
public function getDateType()
{
return $this->datetype;
}
/**
* Returns formatter's last error code. Always returns the U_ZERO_ERROR class constant value
*
* @return int The error code from last formatter call
*
* @see http://www.php.net/manual/en/intldateformatter.geterrorcode.php
*/
public function getErrorCode()
{
return $this->errorCode;
}
/**
* Returns formatter's last error message. Always returns the U_ZERO_ERROR_MESSAGE class constant value
*
* @return string The error message from last formatter call
*
* @see http://www.php.net/manual/en/intldateformatter.geterrormessage.php
*/
public function getErrorMessage()
{
return $this->errorMessage;
}
/**
* Returns the formatter's locale
*
* @param int $type The locale name type to return between valid or actual (StubLocale::VALID_LOCALE or StubLocale::ACTUAL_LOCALE, respectively)
*
* @return string The locale name used to create the formatter
*
* @see http://www.php.net/manual/en/intldateformatter.getlocale.php
*/
public function getLocale($type = StubLocale::ACTUAL_LOCALE)
{
return 'en';
}
/**
* Returns the formatter's pattern
*
* @return string The pattern string used by the formatter
*
* @see http://www.php.net/manual/en/intldateformatter.getpattern.php
*/
public function getPattern()
{
return $this->pattern;
}
/**
* Returns the formatter's time type
*
* @return string The time type used by the formatter
*
* @see http://www.php.net/manual/en/intldateformatter.gettimetype.php
*/
public function getTimeType()
{
return $this->timetype;
}
/**
* Returns the formatter's timezone identifier
*
* @return string The timezone identifier used by the formatter
*
* @see http://www.php.net/manual/en/intldateformatter.gettimezoneid.php
*/
public function getTimeZoneId()
{
if (!$this->unitializedTimeZoneId) {
return $this->timeZoneId;
}
// In PHP 5.5 default timezone depends on `date_default_timezone_get()` method
if (version_compare(\PHP_VERSION, '5.5.0-dev', '>=')) {
return date_default_timezone_get();
}
return null;
}
/**
* Returns the formatter's timezone
*
* @return mixed The timezone used by the formatter
*
* @see http://www.php.net/manual/en/intldateformatter.gettimezone.php
*
* @throws MethodNotImplementedException
*/
public function getTimeZone()
{
throw new MethodNotImplementedException(__METHOD__);
}
/**
* Returns whether the formatter is lenient
*
* @return string The timezone identifier used by the formatter
*
* @see http://www.php.net/manual/en/intldateformatter.islenient.php
*
* @throws MethodNotImplementedException
*/
public function isLenient()
{
throw new MethodNotImplementedException(__METHOD__);
}
/**
* Parse string to a field-based time value
*
* @param string $value String to convert to a time value
* @param int $position Position at which to start the parsing in $value (zero-based).
* If no error occurs before $value is consumed, $parse_pos will
* contain -1 otherwise it will contain the position at which parsing
* ended. If $parse_pos > strlen($value), the parse fails immediately.
*
* @return string Localtime compatible array of integers: contains 24 hour clock value in tm_hour field
*
* @see http://www.php.net/manual/en/intldateformatter.localtime.php
*
* @throws MethodNotImplementedException
*/
public function localtime($value, &$position = 0)
{
throw new MethodNotImplementedException(__METHOD__);
}
/**
* Parse string to a timestamp value
*
* @param string $value String to convert to a time value
* @param int $position Position at which to start the parsing in $value (zero-based).
* If no error occurs before $value is consumed, $parse_pos will
* contain -1 otherwise it will contain the position at which parsing
* ended. If $parse_pos > strlen($value), the parse fails immediately.
*
* @return string Parsed value as a timestamp
*
* @see http://www.php.net/manual/en/intldateformatter.parse.php
*
* @throws MethodArgumentNotImplementedException When $position different than null, behavior not implemented
*/
public function parse($value, &$position = null)
{
// We don't calculate the position when parsing the value
if (null !== $position) {
throw new MethodArgumentNotImplementedException(__METHOD__, 'position');
}
$dateTime = $this->createDateTime(0);
$transformer = new FullTransformer($this->getPattern(), $this->getTimeZoneId());
$timestamp = $transformer->parse($dateTime, $value);
// behave like the intl extension. FullTransformer::parse() set the proper error
$this->errorCode = StubIntl::getErrorCode();
$this->errorMessage = StubIntl::getErrorMessage();
return $timestamp;
}
/**
* Set the formatter's calendar
*
* @param string $calendar The calendar to use. Default is IntlDateFormatter::GREGORIAN.
*
* @return Boolean true on success or false on failure
*
* @see http://www.php.net/manual/en/intldateformatter.setcalendar.php
*
* @throws MethodNotImplementedException
*/
public function setCalendar($calendar)
{
throw new MethodNotImplementedException(__METHOD__);
}
/**
* Set the leniency of the parser
*
* Define if the parser is strict or lenient in interpreting inputs that do not match the pattern
* exactly. Enabling lenient parsing allows the parser to accept otherwise flawed date or time
* patterns, parsing as much as possible to obtain a value. Extra space, unrecognized tokens, or
* invalid values ("February 30th") are not accepted.
*
* @param Boolean $lenient Sets whether the parser is lenient or not, default is false (strict)
*
* @return Boolean true on success or false on failure
*
* @see http://www.php.net/manual/en/intldateformatter.setlenient.php
*
* @throws MethodArgumentValueNotImplementedException When $lenient is true
*/
public function setLenient($lenient)
{
if ($lenient) {
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'lenient', $lenient, 'Only the strict parser is supported');
}
}
/**
* Set the formatter's pattern
*
* @param string $pattern A pattern string in conformance with the ICU IntlDateFormatter documentation
*
* @return Boolean true on success or false on failure
*
* @see http://www.php.net/manual/en/intldateformatter.setpattern.php
* @see http://userguide.icu-project.org/formatparse/datetime
*/
public function setPattern($pattern)
{
if (null === $pattern) {
$pattern = $this->getDefaultPattern();
}
$this->pattern = $pattern;
}
/**
* Set the formatter's timezone identifier
*
* @param string $timeZoneId The time zone ID string of the time zone to use.
* If NULL or the empty string, the default time zone for the
* runtime is used.
*
* @return Boolean true on success or false on failure
*
* @see http://www.php.net/manual/en/intldateformatter.settimezoneid.php
*/
public function setTimeZoneId($timeZoneId)
{
if (null === $timeZoneId) {
// In PHP 5.5 if $timeZoneId is null it fallbacks to `date_default_timezone_get()` method
if (version_compare(\PHP_VERSION, '5.5.0-dev', '>=')) {
$timeZoneId = date_default_timezone_get();
} else {
// TODO: changes were made to ext/intl in PHP 5.4.4 release that need to be investigated since it will
// use ini's date.timezone when the time zone is not provided. As a not well tested workaround, uses UTC.
// See the first two items of the commit message for more information:
// https://github.com/php/php-src/commit/eb346ef0f419b90739aadfb6cc7b7436c5b521d9
$timeZoneId = getenv('TZ') ?: 'UTC';
}
$this->unitializedTimeZoneId = true;
}
// Backup original passed time zone
$timeZone = $timeZoneId;
// Get an Etc/GMT time zone that is accepted for \DateTimeZone
if ('GMT' !== $timeZoneId && 0 === strpos($timeZoneId, 'GMT')) {
try {
$timeZoneId = DateFormat\TimeZoneTransformer::getEtcTimeZoneId($timeZoneId);
} catch (\InvalidArgumentException $e) {
// Does nothing, will fallback to UTC
}
}
try {
$this->dateTimeZone = new \DateTimeZone($timeZoneId);
} catch (\Exception $e) {
$this->dateTimeZone = new \DateTimeZone('UTC');
}
$this->timeZoneId = $timeZone;
return true;
}
/**
* This method was added in PHP 5.5 as replacement for `setTimeZoneId()`
*
* @param mixed $timeZone
*
* @return Boolean true on success or false on failure
*
* @see http://www.php.net/manual/en/intldateformatter.settimezone.php
*/
public function setTimeZone($timeZone)
{
return $this->setTimeZoneId($timeZone);
}
/**
* Create and returns a DateTime object with the specified timestamp and with the
* current time zone
*
* @param int $timestamp
*
* @return \DateTime
*/
protected function createDateTime($timestamp)
{
$dateTime = new \DateTime();
$dateTime->setTimestamp($timestamp);
$dateTime->setTimezone($this->dateTimeZone);
return $dateTime;
}
/**
* Returns a pattern string based in the datetype and timetype values
*
* @return string
*/
protected function getDefaultPattern()
{
$patternParts = array();
if (self::NONE !== $this->datetype) {
$patternParts[] = $this->defaultDateFormats[$this->datetype];
}
if (self::NONE !== $this->timetype) {
$patternParts[] = $this->defaultTimeFormats[$this->timetype];
}
$pattern = implode(' ', $patternParts);
return $pattern;
}
}
Jump to Line
Something went wrong with that request. Please try again.