PageRenderTime 45ms CodeModel.GetById 1ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Symfony/Component/Locale/Stub/StubIntlDateFormatter.php

https://github.com/Exercise/symfony
PHP | 493 lines | 180 code | 54 blank | 259 comment | 17 complexity | b89fcf1a8136269b2df2f3f923baa118 MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Locale\Stub;
  11. use Symfony\Component\Locale\Stub\StubLocale;
  12. use Symfony\Component\Locale\Stub\DateFormat\FullTransformer;
  13. use Symfony\Component\Locale\Exception\NotImplementedException;
  14. use Symfony\Component\Locale\Exception\MethodNotImplementedException;
  15. use Symfony\Component\Locale\Exception\MethodArgumentNotImplementedException;
  16. use Symfony\Component\Locale\Exception\MethodArgumentValueNotImplementedException;
  17. /**
  18. * Provides a stub IntlDateFormatter for the 'en' locale.
  19. *
  20. * @author Igor Wiedler <igor@wiedler.ch>
  21. */
  22. class StubIntlDateFormatter
  23. {
  24. /**
  25. * Constants defined by the intl extension, not class constants in IntlDateFormatter
  26. * TODO: remove if the Form component drop the call to the intl_is_failure() function
  27. *
  28. * @see StubIntlDateFormatter::getErrorCode()
  29. * @see StubIntlDateFormatter::getErrorMessage()
  30. */
  31. const U_ZERO_ERROR = 0;
  32. const U_ZERO_ERROR_MESSAGE = 'U_ZERO_ERROR';
  33. /* date/time format types */
  34. const NONE = -1;
  35. const FULL = 0;
  36. const LONG = 1;
  37. const MEDIUM = 2;
  38. const SHORT = 3;
  39. /* calendar formats */
  40. const TRADITIONAL = 0;
  41. const GREGORIAN = 1;
  42. /**
  43. * Patterns used to format the date when no pattern is provided
  44. *
  45. * @var array
  46. */
  47. private $defaultDateFormats = array(
  48. self::NONE => '',
  49. self::FULL => 'EEEE, LLLL d, y',
  50. self::LONG => 'LLLL d, y',
  51. self::MEDIUM => 'LLL d, y',
  52. self::SHORT => 'M/d/yy',
  53. );
  54. /**
  55. * Patterns used to format the time when no pattern is provided
  56. *
  57. * @var array
  58. */
  59. private $defaultTimeFormats = array(
  60. self::FULL => 'h:mm:ss a zzzz',
  61. self::LONG => 'h:mm:ss a z',
  62. self::MEDIUM => 'h:mm:ss a',
  63. self::SHORT => 'h:mm a',
  64. );
  65. /**
  66. * @var int
  67. */
  68. private $datetype;
  69. /**
  70. * @var int
  71. */
  72. private $timetype;
  73. /**
  74. * @var string
  75. */
  76. private $pattern;
  77. /**
  78. * @var DateTimeZone
  79. */
  80. private $dateTimeZone;
  81. /**
  82. * @var Boolean
  83. */
  84. private $unitializedTimeZoneId = false;
  85. /**
  86. * @var string
  87. */
  88. private $timeZoneId;
  89. /**
  90. * Constructor
  91. *
  92. * @param string $locale The locale code
  93. * @param int $datetype Type of date formatting, one of the format type constants
  94. * @param int $timetype Type of time formatting, one of the format type constants
  95. * @param string $timezone Timezone identifier
  96. * @param int $calendar Calendar to use for formatting or parsing; default is Gregorian.
  97. * One of the calendar constants.
  98. * @param string $pattern Optional pattern to use when formatting
  99. *
  100. * @see http://www.php.net/manual/en/intldateformatter.create.php
  101. * @see http://userguide.icu-project.org/formatparse/datetime
  102. *
  103. * @throws MethodArgumentValueNotImplementedException When $locale different than 'en' is passed
  104. * @throws MethodArgumentValueNotImplementedException When $calendar different than GREGORIAN is passed
  105. */
  106. public function __construct($locale, $datetype, $timetype, $timezone = null, $calendar = self::GREGORIAN, $pattern = null)
  107. {
  108. if ('en' != $locale) {
  109. throw new MethodArgumentValueNotImplementedException(__METHOD__, 'locale', $locale, 'Only the \'en\' locale is supported');
  110. }
  111. if (self::GREGORIAN != $calendar) {
  112. throw new MethodArgumentValueNotImplementedException(__METHOD__, 'calendar', $calendar, 'Only the GREGORIAN calendar is supported');
  113. }
  114. $this->datetype = $datetype;
  115. $this->timetype = $timetype;
  116. $this->setPattern($pattern);
  117. $this->setTimeZoneId($timezone);
  118. }
  119. /**
  120. * Static constructor
  121. *
  122. * @param string $locale The locale code
  123. * @param int $datetype Type of date formatting, one of the format type constants
  124. * @param int $timetype Type of time formatting, one of the format type constants
  125. * @param string $timezone Timezone identifier
  126. * @param int $calendar Calendar to use for formatting or parsing; default is Gregorian.
  127. * One of the calendar constants.
  128. * @param string $pattern Optional pattern to use when formatting
  129. *
  130. * @see http://www.php.net/manual/en/intldateformatter.create.php
  131. * @see http://userguide.icu-project.org/formatparse/datetime
  132. *
  133. * @throws MethodArgumentValueNotImplementedException When $locale different than 'en' is passed
  134. */
  135. static public function create($locale, $datetype, $timetype, $timezone = null, $calendar = self::GREGORIAN, $pattern = null)
  136. {
  137. return new self($locale, $datetype, $timetype, $timezone, $calendar, $pattern);
  138. }
  139. /**
  140. * Format the date/time value (timestamp) as a string
  141. *
  142. * @param mixed $timestamp Unix timestamp to format
  143. *
  144. * @return string The formatted value
  145. *
  146. * @see http://www.php.net/manual/en/intldateformatter.format.php
  147. *
  148. * @throws NotImplementedException If one of the formatting characters is not implemented
  149. */
  150. public function format($timestamp)
  151. {
  152. // intl allows timestamps to be passed as arrays - we don't
  153. if (is_array($timestamp)) {
  154. throw new MethodArgumentValueNotImplementedException(__METHOD__, 'timestamp', $timestamp, 'Only integer unix timestamps are supported');
  155. }
  156. // behave like the intl extension
  157. if (!is_int($timestamp) && version_compare(\PHP_VERSION, '5.3.4', '<')) {
  158. StubIntl::setErrorCode(StubIntl::U_ILLEGAL_ARGUMENT_ERROR);
  159. return false;
  160. }
  161. // As of PHP 5.3.4, IntlDateFormatter::format() accepts DateTime instances
  162. if ($timestamp instanceOf \DateTime && version_compare(\PHP_VERSION, '5.3.4', '>=')) {
  163. $timestamp = $timestamp->getTimestamp();
  164. }
  165. $transformer = new FullTransformer($this->getPattern(), $this->getTimeZoneId());
  166. $formatted = $transformer->format($this->createDateTime($timestamp));
  167. return $formatted;
  168. }
  169. /**
  170. * Returns the formatter's calendar
  171. *
  172. * @return int The calendar being used by the formatter
  173. *
  174. * @see http://www.php.net/manual/en/intldateformatter.getcalendar.php
  175. */
  176. public function getCalendar()
  177. {
  178. return self::GREGORIAN;
  179. }
  180. /**
  181. * Returns the formatter's datetype
  182. *
  183. * @return int The current value of the formatter
  184. *
  185. * @see http://www.php.net/manual/en/intldateformatter.getdatetype.php
  186. */
  187. public function getDateType()
  188. {
  189. return $this->datetype;
  190. }
  191. /**
  192. * Returns formatter's last error code. Always returns the U_ZERO_ERROR class constant value
  193. *
  194. * @return int The error code from last formatter call
  195. *
  196. * @see http://www.php.net/manual/en/intldateformatter.geterrorcode.php
  197. */
  198. public function getErrorCode()
  199. {
  200. return self::U_ZERO_ERROR;
  201. }
  202. /**
  203. * Returns formatter's last error message. Always returns the U_ZERO_ERROR_MESSAGE class constant value
  204. *
  205. * @return string The error message from last formatter call
  206. *
  207. * @see http://www.php.net/manual/en/intldateformatter.geterrormessage.php
  208. */
  209. public function getErrorMessage()
  210. {
  211. return self::U_ZERO_ERROR_MESSAGE;
  212. }
  213. /**
  214. * Returns the formatter's locale
  215. *
  216. * @param int $type The locale name type to return between valid or actual (StubLocale::VALID_LOCALE or StubLocale::ACTUAL_LOCALE, respectively)
  217. *
  218. * @return string The locale name used to create the formatter
  219. *
  220. * @see http://www.php.net/manual/en/intldateformatter.getlocale.php
  221. */
  222. public function getLocale($type = StubLocale::ACTUAL_LOCALE)
  223. {
  224. return 'en';
  225. }
  226. /**
  227. * Returns the formatter's pattern
  228. *
  229. * @return string The pattern string used by the formatter
  230. *
  231. * @see http://www.php.net/manual/en/intldateformatter.getpattern.php
  232. */
  233. public function getPattern()
  234. {
  235. return $this->pattern;
  236. }
  237. /**
  238. * Returns the formatter's time type
  239. *
  240. * @return string The time type used by the formatter
  241. *
  242. * @see http://www.php.net/manual/en/intldateformatter.gettimetype.php
  243. */
  244. public function getTimeType()
  245. {
  246. return $this->timetype;
  247. }
  248. /**
  249. * Returns the formatter's timezone identifier
  250. *
  251. * @return string The timezone identifier used by the formatter
  252. *
  253. * @see http://www.php.net/manual/en/intldateformatter.gettimezoneid.php
  254. */
  255. public function getTimeZoneId()
  256. {
  257. if (!$this->unitializedTimeZoneId) {
  258. return $this->timeZoneId;
  259. }
  260. return null;
  261. }
  262. /**
  263. * Returns whether the formatter is lenient
  264. *
  265. * @return string The timezone identifier used by the formatter
  266. *
  267. * @see http://www.php.net/manual/en/intldateformatter.islenient.php
  268. *
  269. * @throws MethodNotImplementedException
  270. */
  271. public function isLenient()
  272. {
  273. throw new MethodNotImplementedException(__METHOD__);
  274. }
  275. /**
  276. * Parse string to a field-based time value
  277. *
  278. * @param string $value String to convert to a time value
  279. * @param int $position Position at which to start the parsing in $value (zero-based).
  280. * If no error occurs before $value is consumed, $parse_pos will
  281. * contain -1 otherwise it will contain the position at which parsing
  282. * ended. If $parse_pos > strlen($value), the parse fails immediately.
  283. *
  284. * @return string Localtime compatible array of integers: contains 24 hour clock value in tm_hour field
  285. *
  286. * @see http://www.php.net/manual/en/intldateformatter.localtime.php
  287. *
  288. * @throws MethodNotImplementedException
  289. */
  290. public function localtime($value, &$position = 0)
  291. {
  292. throw new MethodNotImplementedException(__METHOD__);
  293. }
  294. /**
  295. * Parse string to a timestamp value
  296. *
  297. * @param string $value String to convert to a time value
  298. * @param int $position Position at which to start the parsing in $value (zero-based).
  299. * If no error occurs before $value is consumed, $parse_pos will
  300. * contain -1 otherwise it will contain the position at which parsing
  301. * ended. If $parse_pos > strlen($value), the parse fails immediately.
  302. *
  303. * @return string Parsed value as a timestamp
  304. *
  305. * @see http://www.php.net/manual/en/intldateformatter.parse.php
  306. *
  307. * @throws MethodArgumentNotImplementedException When $position different than null, behavior not implemented
  308. */
  309. public function parse($value, &$position = null)
  310. {
  311. // We don't calculate the position when parsing the value
  312. if (null !== $position) {
  313. throw new MethodArgumentNotImplementedException(__METHOD__, 'position');
  314. }
  315. StubIntl::setErrorCode(StubIntl::U_ZERO_ERROR);
  316. $dateTime = $this->createDateTime(0);
  317. $transformer = new FullTransformer($this->getPattern(), $this->getTimeZoneId());
  318. return $transformer->parse($dateTime, $value);
  319. }
  320. /**
  321. * Set the formatter's calendar
  322. *
  323. * @param string $calendar The calendar to use. Default is IntlDateFormatter::GREGORIAN.
  324. *
  325. * @return Boolean true on success or false on failure
  326. *
  327. * @see http://www.php.net/manual/en/intldateformatter.setcalendar.php
  328. *
  329. * @throws MethodNotImplementedException
  330. */
  331. public function setCalendar($calendar)
  332. {
  333. throw new MethodNotImplementedException(__METHOD__);
  334. }
  335. /**
  336. * Set the leniency of the parser
  337. *
  338. * Define if the parser is strict or lenient in interpreting inputs that do not match the pattern
  339. * exactly. Enabling lenient parsing allows the parser to accept otherwise flawed date or time
  340. * patterns, parsing as much as possible to obtain a value. Extra space, unrecognized tokens, or
  341. * invalid values ("February 30th") are not accepted.
  342. *
  343. * @param Boolean $lenient Sets whether the parser is lenient or not, default is false (strict)
  344. *
  345. * @return Boolean true on success or false on failure
  346. *
  347. * @see http://www.php.net/manual/en/intldateformatter.setlenient.php
  348. *
  349. * @throws MethodNotImplementedException
  350. */
  351. public function setLenient($lenient)
  352. {
  353. throw new MethodNotImplementedException(__METHOD__);
  354. }
  355. /**
  356. * Set the formatter's pattern
  357. *
  358. * @param string $pattern A pattern string in conformance with the ICU IntlDateFormatter documentation
  359. *
  360. * @return Boolean true on success or false on failure
  361. *
  362. * @see http://www.php.net/manual/en/intldateformatter.setpattern.php
  363. * @see http://userguide.icu-project.org/formatparse/datetime
  364. */
  365. public function setPattern($pattern)
  366. {
  367. if (null === $pattern) {
  368. $pattern = $this->getDefaultPattern();
  369. }
  370. $this->pattern = $pattern;
  371. }
  372. /**
  373. * Set the formatter's timezone identifier
  374. *
  375. * @param string $timeZoneId The time zone ID string of the time zone to use.
  376. * If NULL or the empty string, the default time zone for the
  377. * runtime is used.
  378. *
  379. * @return Boolean true on success or false on failure
  380. *
  381. * @see http://www.php.net/manual/en/intldateformatter.settimezoneid.php
  382. */
  383. public function setTimeZoneId($timeZoneId)
  384. {
  385. if (null === $timeZoneId) {
  386. $timeZoneId = date_default_timezone_get();
  387. $this->unitializedTimeZoneId = true;
  388. }
  389. // Backup original passed time zone
  390. $timeZone = $timeZoneId;
  391. // Get an Etc/GMT time zone that is accepted for \DateTimeZone
  392. if ('GMT' !== $timeZoneId && 0 === strpos($timeZoneId, 'GMT')) {
  393. try {
  394. $timeZoneId = DateFormat\TimeZoneTransformer::getEtcTimeZoneId($timeZoneId);
  395. } catch (\InvalidArgumentException $e) {
  396. // Does nothing, will fallback to UTC
  397. }
  398. }
  399. try {
  400. $this->dateTimeZone = new \DateTimeZone($timeZoneId);
  401. } catch (\Exception $e) {
  402. $this->dateTimeZone = new \DateTimeZone('UTC');
  403. }
  404. $this->timeZoneId = $timeZone;
  405. return true;
  406. }
  407. /**
  408. * Create and returns a DateTime object with the specified timestamp and with the
  409. * current time zone
  410. *
  411. * @param int $timestamp
  412. *
  413. * @return DateTime
  414. */
  415. protected function createDateTime($timestamp)
  416. {
  417. $dateTime = new \DateTime();
  418. $dateTime->setTimestamp($timestamp);
  419. $dateTime->setTimezone($this->dateTimeZone);
  420. return $dateTime;
  421. }
  422. /**
  423. * Returns a pattern string based in the datetype and timetype values
  424. *
  425. * @return string
  426. */
  427. protected function getDefaultPattern()
  428. {
  429. $patternParts = array();
  430. if (self::NONE !== $this->datetype) {
  431. $patternParts[] = $this->defaultDateFormats[$this->datetype];
  432. }
  433. if (self::NONE !== $this->timetype) {
  434. $patternParts[] = $this->defaultTimeFormats[$this->timetype];
  435. }
  436. $pattern = implode(' ', $patternParts);
  437. return $pattern;
  438. }
  439. }