PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/I18N/core/DateFormat.php

https://bitbucket.org/freshflow/prado-fork-v3.10
PHP | 652 lines | 387 code | 59 blank | 206 comment | 55 complexity | 34f769cb00e60986b183429b4ebf7896 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0
  1. <?php
  2. /**
  3. * DateFormat class file.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the BSD License.
  7. *
  8. * Copyright(c) 2004 by Qiang Xue. All rights reserved.
  9. *
  10. * To contact the author write to {@link mailto:qiang.xue@gmail.com Qiang Xue}
  11. * The latest version of PRADO can be obtained from:
  12. * {@link http://prado.sourceforge.net/}
  13. *
  14. * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
  15. * @version $Revision: 1.8 $ $Date: 2005/12/15 07:14:49 $
  16. * @package System.I18N.core
  17. */
  18. /**
  19. * Get the DateTimeFormatInfo class.
  20. */
  21. require_once(dirname(__FILE__).'/DateTimeFormatInfo.php');
  22. /**
  23. * Get the encoding utilities
  24. */
  25. require_once(dirname(__FILE__).'/util.php');
  26. /**
  27. * DateFormat class.
  28. *
  29. * The DateFormat class allows you to format dates and times with
  30. * predefined styles in a locale-sensitive manner. Formatting times
  31. * with the DateFormat class is similar to formatting dates.
  32. *
  33. * Formatting dates with the DateFormat class is a two-step process.
  34. * First, you create a formatter with the getDateInstance method.
  35. * Second, you invoke the format method, which returns a string containing
  36. * the formatted date.
  37. *
  38. * DateTime values are formatted using standard or custom patterns stored
  39. * in the properties of a DateTimeFormatInfo.
  40. *
  41. * @author Xiang Wei Zhuo <weizhuo[at]gmail[dot]com>
  42. * @version v1.0, last update on Sat Dec 04 14:10:49 EST 2004
  43. * @package System.I18N.core
  44. */
  45. class DateFormat
  46. {
  47. /**
  48. * A list of tokens and their function call.
  49. * @var array
  50. */
  51. protected $tokens = array(
  52. 'G'=>'Era',
  53. 'y'=>'Year',
  54. 'M'=>'Month',
  55. 'd'=>'Day',
  56. 'h'=>'Hour12',
  57. 'H'=>'Hour24',
  58. 'm'=>'Minutes',
  59. 's'=>'Seconds',
  60. 'E'=>'DayInWeek',
  61. 'D'=>'DayInYear',
  62. 'F'=>'DayInMonth',
  63. 'w'=>'WeekInYear',
  64. 'W'=>'WeekInMonth',
  65. 'a'=>'AMPM',
  66. 'k'=>'HourInDay',
  67. 'K'=>'HourInAMPM',
  68. 'z'=>'TimeZone'
  69. );
  70. /**
  71. * A list of methods, to be used by the token function calls.
  72. * @var array
  73. */
  74. protected $methods = array();
  75. /**
  76. * The DateTimeFormatInfo, containing culture specific patterns and names.
  77. * @var DateTimeFormatInfo
  78. */
  79. protected $formatInfo;
  80. /**
  81. * Initialize a new DateFormat.
  82. * @param mixed either, null, a CultureInfo instance,
  83. * a DateTimeFormatInfo instance, or a locale.
  84. * @return DateFormat instance
  85. */
  86. function __construct($formatInfo=null)
  87. {
  88. if($formatInfo === null)
  89. $this->formatInfo = DateTimeFormatInfo::getInvariantInfo();
  90. else if($formatInfo instanceof CultureInfo)
  91. $this->formatInfo = $formatInfo->DateTimeFormat;
  92. else if($formatInfo instanceof DateTimeFormatInfo)
  93. $this->formatInfo = $formatInfo;
  94. else
  95. $this->formatInfo = DateTimeFormatInfo::getInstance($formatInfo);
  96. $this->methods = get_class_methods($this);
  97. }
  98. /**
  99. * Format a date according to the pattern.
  100. * @param mixed the time as integer or string in strtotime format.
  101. * @return string formatted date time.
  102. */
  103. public function format($time, $pattern='F', $charset='UTF-8')
  104. {
  105. if (is_numeric($time)) //assumes unix epoch
  106. $time = floatval($time);
  107. else if(is_string($time))
  108. $time = @strtotime($time);
  109. if($pattern === null)
  110. $pattern = 'F';
  111. $s = Prado::createComponent('System.Util.TDateTimeStamp');
  112. $date = $s->getDate($time);
  113. $pattern = $this->getPattern($pattern);
  114. $tokens = $this->getTokens($pattern);
  115. for($i = 0, $k = count($tokens); $i<$k; ++$i)
  116. {
  117. $pattern = $tokens[$i];
  118. if($pattern{0} == "'"
  119. && $pattern{strlen($pattern)-1} == "'")
  120. {
  121. $sub = preg_replace('/(^\')|(\'$)/','',$pattern);
  122. $tokens[$i] = str_replace('``````','\'',$sub);
  123. }
  124. else if($pattern == '``````')
  125. {
  126. $tokens[$i] = '\'';
  127. }
  128. else
  129. {
  130. $function = $this->getFunctionName($pattern);
  131. if($function != null)
  132. {
  133. $fName = 'get'.$function;
  134. if(in_array($fName, $this->methods))
  135. {
  136. $rs = $this->$fName($date, $pattern);
  137. $tokens[$i] = $rs;
  138. }
  139. else
  140. throw new
  141. Exception('function '.$function.' not found.');
  142. }
  143. }
  144. }
  145. return I18N_toEncoding(implode('',$tokens), $charset);
  146. }
  147. /**
  148. * For a particular token, get the corresponding function to call.
  149. * @param string token
  150. * @return mixed the function if good token, null otherwise.
  151. */
  152. protected function getFunctionName($token)
  153. {
  154. if(isset($this->tokens[$token{0}]))
  155. return $this->tokens[$token{0}];
  156. }
  157. /**
  158. * Get the pattern from DateTimeFormatInfo or some predefined patterns.
  159. * If the $pattern parameter is an array of 2 element, it will assume
  160. * that the first element is the date, and second the time
  161. * and try to find an appropriate pattern and apply
  162. * DateTimeFormatInfo::formatDateTime
  163. * See the tutorial documentation for futher details on the patterns.
  164. * @param mixed a pattern.
  165. * @return string a pattern.
  166. * @see DateTimeFormatInfo::formatDateTime()
  167. */
  168. protected function getPattern($pattern)
  169. {
  170. if(is_array($pattern) && count($pattern) == 2)
  171. {
  172. return $this->formatInfo->formatDateTime(
  173. $this->getPattern($pattern[0]),
  174. $this->getPattern($pattern[1]));
  175. }
  176. switch($pattern)
  177. {
  178. case 'd':
  179. return $this->formatInfo->ShortDatePattern;
  180. break;
  181. case 'D':
  182. return $this->formatInfo->LongDatePattern;
  183. break;
  184. case 'p':
  185. return $this->formatInfo->MediumDatePattern;
  186. break;
  187. case 'P':
  188. return $this->formatInfo->FullDatePattern;
  189. break;
  190. case 't':
  191. return $this->formatInfo->ShortTimePattern;
  192. break;
  193. case 'T':
  194. return $this->formatInfo->LongTimePattern;
  195. break;
  196. case 'q':
  197. return $this->formatInfo->MediumTimePattern;
  198. break;
  199. case 'Q':
  200. return $this->formatInfo->FullTimePattern;
  201. break;
  202. case 'f':
  203. return $this->formatInfo->formatDateTime(
  204. $this->formatInfo->LongDatePattern,
  205. $this->formatInfo->ShortTimePattern);
  206. break;
  207. case 'F':
  208. return $this->formatInfo->formatDateTime(
  209. $this->formatInfo->LongDatePattern,
  210. $this->formatInfo->LongTimePattern);
  211. break;
  212. case 'g':
  213. return $this->formatInfo->formatDateTime(
  214. $this->formatInfo->ShortDatePattern,
  215. $this->formatInfo->ShortTimePattern);
  216. break;
  217. case 'G':
  218. return $this->formatInfo->formatDateTime(
  219. $this->formatInfo->ShortDatePattern,
  220. $this->formatInfo->LongTimePattern);
  221. break;
  222. case 'M':
  223. case 'm':
  224. return 'MMMM dd';
  225. break;
  226. case 'R':
  227. case 'r':
  228. return 'EEE, dd MMM yyyy HH:mm:ss';
  229. break;
  230. case 's':
  231. return 'yyyy-MM-ddTHH:mm:ss';
  232. break;
  233. case 'u':
  234. return 'yyyy-MM-dd HH:mm:ss z';
  235. break;
  236. case 'U':
  237. return 'EEEE dd MMMM yyyy HH:mm:ss';
  238. break;
  239. case 'Y':
  240. case 'y':
  241. return 'yyyy MMMM';
  242. break;
  243. default :
  244. return $pattern;
  245. }
  246. }
  247. /**
  248. * Tokenize the pattern. The tokens are delimited by group of
  249. * similar characters, e.g. 'aabb' will form 2 tokens of 'aa' and 'bb'.
  250. * Any substrings, starting and ending with a single quote (')
  251. * will be treated as a single token.
  252. * @param string pattern.
  253. * @return array string tokens in an array.
  254. */
  255. protected function getTokens($pattern)
  256. {
  257. $char = null;
  258. $tokens = array();
  259. $token = null;
  260. $text = false;
  261. $pattern = preg_replace("/''/", '``````', $pattern);
  262. for($i = 0; $i < strlen($pattern); $i++)
  263. {
  264. if($char==null || $pattern{$i} == $char || $text)
  265. {
  266. $token .= $pattern{$i};
  267. }
  268. else
  269. {
  270. $tokens[] = str_replace("","'",$token);
  271. $token = $pattern{$i};
  272. }
  273. if($pattern{$i} == "'" && $text == false)
  274. $text = true;
  275. else if($text && $pattern{$i} == "'" && $char == "'")
  276. $text = true;
  277. else if($text && $char != "'" && $pattern{$i} == "'")
  278. $text = false;
  279. $char = $pattern{$i};
  280. }
  281. $tokens[] = $token;
  282. return $tokens;
  283. }
  284. /**
  285. * Get the year.
  286. * "yy" will return the last two digits of year.
  287. * "yyyy" will return the full integer year.
  288. * @param array getdate format.
  289. * @param string a pattern.
  290. * @return string year
  291. */
  292. protected function getYear($date, $pattern='yyyy')
  293. {
  294. $year = $date['year'];
  295. switch($pattern)
  296. {
  297. case 'yy':
  298. return substr($year,2);
  299. case 'yyyy':
  300. return $year;
  301. default:
  302. throw new Exception('The pattern for year is either "yy" or "yyyy".');
  303. }
  304. }
  305. /**
  306. * Get the month.
  307. * "M" will return integer 1 through 12
  308. * "MM" will return the narrow month name, e.g. "J"
  309. * "MMM" will return the abrreviated month name, e.g. "Jan"
  310. * "MMMM" will return the month name, e.g. "January"
  311. * @param array getdate format.
  312. * @param string a pattern.
  313. * @return string month name
  314. */
  315. protected function getMonth($date, $pattern='M')
  316. {
  317. $month = $date['mon'];
  318. switch($pattern)
  319. {
  320. case 'M':
  321. return $month;
  322. case 'MM':
  323. return str_pad($month, 2,'0',STR_PAD_LEFT);
  324. case 'MMM':
  325. return $this->formatInfo->AbbreviatedMonthNames[$month-1];
  326. break;
  327. case 'MMMM':
  328. return $this->formatInfo->MonthNames[$month-1];
  329. default:
  330. throw new Exception('The pattern for month '.
  331. 'is "M", "MM", "MMM", or "MMMM".');
  332. }
  333. }
  334. /**
  335. * Get the day of the week.
  336. * "E" will return integer 0 (for Sunday) through 6 (for Saturday).
  337. * "EE" will return the narrow day of the week, e.g. "M"
  338. * "EEE" will return the abrreviated day of the week, e.g. "Mon"
  339. * "EEEE" will return the day of the week, e.g. "Monday"
  340. * @param array getdate format.
  341. * @param string a pattern.
  342. * @return string day of the week.
  343. */
  344. protected function getDayInWeek($date, $pattern='EEEE')
  345. {
  346. $day = $date['wday'];
  347. switch($pattern)
  348. {
  349. case 'E':
  350. return $day;
  351. break;
  352. case 'EE':
  353. return $this->formatInfo->NarrowDayNames[$day];
  354. case 'EEE':
  355. return $this->formatInfo->AbbreviatedDayNames[$day];
  356. break;
  357. case 'EEEE':
  358. return $this->formatInfo->DayNames[$day];
  359. break;
  360. default:
  361. throw new Exception('The pattern for day of the week '.
  362. 'is "E", "EE", "EEE", or "EEEE".');
  363. }
  364. }
  365. /**
  366. * Get the day of the month.
  367. * "d" for non-padding, "dd" will always return 2 characters.
  368. * @param array getdate format.
  369. * @param string a pattern.
  370. * @return string day of the month
  371. */
  372. protected function getDay($date, $pattern='d')
  373. {
  374. $day = $date['mday'];
  375. switch($pattern)
  376. {
  377. case 'd':
  378. return $day;
  379. case 'dd':
  380. return str_pad($day, 2,'0',STR_PAD_LEFT);
  381. default:
  382. throw new Exception('The pattern for day of '.
  383. 'the month is "d" or "dd".');
  384. }
  385. }
  386. /**
  387. * Get the era. i.e. in gregorian, year > 0 is AD, else BC.
  388. * @todo How to support multiple Eras?, e.g. Japanese.
  389. * @param array getdate format.
  390. * @param string a pattern.
  391. * @return string era
  392. */
  393. protected function getEra($date, $pattern='G')
  394. {
  395. if($pattern != 'G')
  396. throw new Exception('The pattern for era is "G".');
  397. $year = $date['year'];
  398. if($year > 0)
  399. return $this->formatInfo->getEra(1);
  400. else
  401. return $this->formatInfo->getEra(0);
  402. }
  403. /**
  404. * Get the hours in 24 hour format, i.e. [0-23].
  405. * "H" for non-padding, "HH" will always return 2 characters.
  406. * @param array getdate format.
  407. * @param string a pattern.
  408. * @return string hours in 24 hour format.
  409. */
  410. protected function getHour24($date, $pattern='H')
  411. {
  412. $hour = $date['hours'];
  413. switch($pattern)
  414. {
  415. case 'H':
  416. return $hour;
  417. case 'HH':
  418. return str_pad($hour, 2,'0',STR_PAD_LEFT);
  419. default:
  420. throw new Exception('The pattern for 24 hour '.
  421. 'format is "H" or "HH".');
  422. }
  423. }
  424. /**
  425. * Get the AM/PM designator, 12 noon is PM, 12 midnight is AM.
  426. * @param array getdate format.
  427. * @param string a pattern.
  428. * @return string AM or PM designator
  429. */
  430. protected function getAMPM($date, $pattern='a')
  431. {
  432. if($pattern != 'a')
  433. throw new Exception('The pattern for AM/PM marker is "a".');
  434. $hour = $date['hours'];
  435. $ampm = (int)($hour/12);
  436. return $this->formatInfo->AMPMMarkers[$ampm];
  437. }
  438. /**
  439. * Get the hours in 12 hour format.
  440. * "h" for non-padding, "hh" will always return 2 characters.
  441. * @param array getdate format.
  442. * @param string a pattern.
  443. * @return string hours in 12 hour format.
  444. */
  445. protected function getHour12($date, $pattern='h')
  446. {
  447. $hour = $date['hours'];
  448. $hour = ($hour==12|$hour==0)?12:($hour)%12;
  449. switch($pattern)
  450. {
  451. case 'h':
  452. return $hour;
  453. case 'hh':
  454. return str_pad($hour, 2,'0',STR_PAD_LEFT);
  455. default:
  456. throw new Exception('The pattern for 24 hour '.
  457. 'format is "H" or "HH".');
  458. }
  459. }
  460. /**
  461. * Get the minutes.
  462. * "m" for non-padding, "mm" will always return 2 characters.
  463. * @param array getdate format.
  464. * @param string a pattern.
  465. * @return string minutes.
  466. */
  467. protected function getMinutes($date, $pattern='m')
  468. {
  469. $minutes = $date['minutes'];
  470. switch($pattern)
  471. {
  472. case 'm':
  473. return $minutes;
  474. case 'mm':
  475. return str_pad($minutes, 2,'0',STR_PAD_LEFT);
  476. default:
  477. throw new Exception('The pattern for minutes is "m" or "mm".');
  478. }
  479. }
  480. /**
  481. * Get the seconds.
  482. * "s" for non-padding, "ss" will always return 2 characters.
  483. * @param array getdate format.
  484. * @param string a pattern.
  485. * @return string seconds
  486. */
  487. protected function getSeconds($date, $pattern='s')
  488. {
  489. $seconds = $date['seconds'];
  490. switch($pattern)
  491. {
  492. case 's':
  493. return $seconds;
  494. case 'ss':
  495. return str_pad($seconds, 2,'0',STR_PAD_LEFT);
  496. default:
  497. throw new Exception('The pattern for seconds is "s" or "ss".');
  498. }
  499. }
  500. /**
  501. * Get the timezone from the server machine.
  502. * @todo How to get the timezone for a different region?
  503. * @param array getdate format.
  504. * @param string a pattern.
  505. * @return string time zone
  506. */
  507. protected function getTimeZone($date, $pattern='z')
  508. {
  509. if($pattern != 'z')
  510. throw new Exception('The pattern for time zone is "z".');
  511. return @date('T', @mktime($date['hours'], $date['minutes'], $date['seconds'], $date['mon'], $date['mday'], $date['year']));
  512. }
  513. /**
  514. * Get the day in the year, e.g. [1-366]
  515. * @param array getdate format.
  516. * @param string a pattern.
  517. * @return int hours in AM/PM format.
  518. */
  519. protected function getDayInYear($date, $pattern='D')
  520. {
  521. if($pattern != 'D')
  522. throw new Exception('The pattern for day in year is "D".');
  523. return $date['yday'];
  524. }
  525. /**
  526. * Get day in the month.
  527. * @param array getdate format.
  528. * @param string a pattern.
  529. * @return int day in month
  530. */
  531. protected function getDayInMonth($date, $pattern='FF')
  532. {
  533. switch ($pattern) {
  534. case 'F':
  535. return @date('j', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']));
  536. break;
  537. case 'FF':
  538. return @date('d', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']));
  539. break;
  540. default:
  541. throw new Exception('The pattern for day in month is "F" or "FF".');
  542. }
  543. }
  544. /**
  545. * Get the week in the year.
  546. * @param array getdate format.
  547. * @param string a pattern.
  548. * @return int week in year
  549. */
  550. protected function getWeekInYear($date, $pattern='w')
  551. {
  552. if($pattern != 'w')
  553. throw new Exception('The pattern for week in year is "w".');
  554. return @date('W', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']));
  555. }
  556. /**
  557. * Get week in the month.
  558. * @param array getdate format.
  559. * @return int week in month
  560. */
  561. protected function getWeekInMonth($date, $pattern='W')
  562. {
  563. if($pattern != 'W')
  564. throw new Exception('The pattern for week in month is "W".');
  565. return @date('W', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year'])) - date('W', mktime(0, 0, 0, $date['mon'], 1, $date['year']));
  566. }
  567. /**
  568. * Get the hours [1-24].
  569. * @param array getdate format.
  570. * @param string a pattern.
  571. * @return int hours [1-24]
  572. */
  573. protected function getHourInDay($date, $pattern='k')
  574. {
  575. if($pattern != 'k')
  576. throw new Exception('The pattern for hour in day is "k".');
  577. return $date['hours']+1;
  578. }
  579. /**
  580. * Get the hours in AM/PM format, e.g [1-12]
  581. * @param array getdate format.
  582. * @param string a pattern.
  583. * @return int hours in AM/PM format.
  584. */
  585. protected function getHourInAMPM($date, $pattern='K')
  586. {
  587. if($pattern != 'K')
  588. throw new Exception('The pattern for hour in AM/PM is "K".');
  589. return ($date['hours']+1)%12;
  590. }
  591. }
  592. ?>