3 * DateFormat class file.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the BSD License.
8 * Copyright(c) 2004 by Qiang Xue. All rights reserved.
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/}
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
20 * Get the DateTimeFormatInfo class.
22 require_once(dirname(__FILE__).'/DateTimeFormatInfo.php');
25 * Get the encoding utilities
27 require_once(dirname(__FILE__).'/util.php');
32 * The DateFormat class allows you to format dates and times with
33 * predefined styles in a locale-sensitive manner. Formatting times
34 * with the DateFormat class is similar to formatting dates.
36 * Formatting dates with the DateFormat class is a two-step process.
37 * First, you create a formatter with the getDateInstance method.
38 * Second, you invoke the format method, which returns a string containing
41 * DateTime values are formatted using standard or custom patterns stored
42 * in the properties of a DateTimeFormatInfo.
44 * @author Xiang Wei Zhuo <weizhuo[at]gmail[dot]com>
45 * @version v1.0, last update on Sat Dec 04 14:10:49 EST 2004
46 * @package System.I18N.core
51 * A list of tokens and their function call.
54 protected $tokens = array(
75 * A list of methods, to be used by the token function calls.
78 protected $methods = array();
81 * The DateTimeFormatInfo, containing culture specific patterns and names.
82 * @var DateTimeFormatInfo
84 protected $formatInfo;
87 * Initialize a new DateFormat.
88 * @param mixed either, null, a CultureInfo instance,
89 * a DateTimeFormatInfo instance, or a locale.
90 * @return DateFormat instance
92 function __construct($formatInfo=null)
94 if($formatInfo === null)
95 $this->formatInfo = DateTimeFormatInfo::getInvariantInfo();
96 else if($formatInfo instanceof CultureInfo)
97 $this->formatInfo = $formatInfo->DateTimeFormat;
98 else if($formatInfo instanceof DateTimeFormatInfo)
99 $this->formatInfo = $formatInfo;
101 $this->formatInfo = DateTimeFormatInfo::getInstance($formatInfo);
103 $this->methods = get_class_methods($this);
107 * Format a date according to the pattern.
108 * @param mixed the time as integer or string in strtotime format.
109 * @return string formatted date time.
111 public function format($time, $pattern='F', $charset='UTF-8')
113 if (is_numeric($time)) //assumes unix epoch
114 $time = floatval($time);
115 else if(is_string($time))
116 $time = @strtotime($time);
118 if($pattern === null)
121 $s = Prado::createComponent('System.Util.TDateTimeStamp');
123 $date = $s->getDate($time);
125 $pattern = $this->getPattern($pattern);
127 $tokens = $this->getTokens($pattern);
129 for($i = 0, $k = count($tokens); $i<$k; ++$i)
131 $pattern = $tokens[$i];
132 if($pattern{0} == "'"
133 && $pattern{strlen($pattern)-1} == "'")
135 $sub = preg_replace('/(^\')|(\'$)/','',$pattern);
136 $tokens[$i] = str_replace('``````','\'',$sub);
138 else if($pattern == '``````')
144 $function = $this->getFunctionName($pattern);
145 if($function != null)
147 $fName = 'get'.$function;
148 if(in_array($fName, $this->methods))
150 $rs = $this->$fName($date, $pattern);
155 Exception('function '.$function.' not found.');
160 return I18N_toEncoding(implode('',$tokens), $charset);
164 * For a particular token, get the corresponding function to call.
165 * @param string token
166 * @return mixed the function if good token, null otherwise.
168 protected function getFunctionName($token)
170 if(isset($this->tokens[$token{0}]))
171 return $this->tokens[$token{0}];
175 * Get the pattern from DateTimeFormatInfo or some predefined patterns.
176 * If the $pattern parameter is an array of 2 element, it will assume
177 * that the first element is the date, and second the time
178 * and try to find an appropriate pattern and apply
179 * DateTimeFormatInfo::formatDateTime
180 * See the tutorial documentation for futher details on the patterns.
181 * @param mixed a pattern.
182 * @return string a pattern.
183 * @see DateTimeFormatInfo::formatDateTime()
185 protected function getPattern($pattern)
187 if(is_array($pattern) && count($pattern) == 2)
189 return $this->formatInfo->formatDateTime(
190 $this->getPattern($pattern[0]),
191 $this->getPattern($pattern[1]));
197 return $this->formatInfo->ShortDatePattern;
200 return $this->formatInfo->LongDatePattern;
203 return $this->formatInfo->MediumDatePattern;
206 return $this->formatInfo->FullDatePattern;
209 return $this->formatInfo->ShortTimePattern;
212 return $this->formatInfo->LongTimePattern;
215 return $this->formatInfo->MediumTimePattern;
218 return $this->formatInfo->FullTimePattern;
221 return $this->formatInfo->formatDateTime(
222 $this->formatInfo->LongDatePattern,
223 $this->formatInfo->ShortTimePattern);
226 return $this->formatInfo->formatDateTime(
227 $this->formatInfo->LongDatePattern,
228 $this->formatInfo->LongTimePattern);
231 return $this->formatInfo->formatDateTime(
232 $this->formatInfo->ShortDatePattern,
233 $this->formatInfo->ShortTimePattern);
236 return $this->formatInfo->formatDateTime(
237 $this->formatInfo->ShortDatePattern,
238 $this->formatInfo->LongTimePattern);
246 return 'EEE, dd MMM yyyy HH:mm:ss';
249 return 'yyyy-MM-ddTHH:mm:ss';
252 return 'yyyy-MM-dd HH:mm:ss z';
255 return 'EEEE dd MMMM yyyy HH:mm:ss';
267 * Tokenize the pattern. The tokens are delimited by group of
268 * similar characters, e.g. 'aabb' will form 2 tokens of 'aa' and 'bb'.
269 * Any substrings, starting and ending with a single quote (')
270 * will be treated as a single token.
271 * @param string pattern.
272 * @return array string tokens in an array.
274 protected function getTokens($pattern)
281 $pattern = preg_replace("/''/", '``````', $pattern);
283 for($i = 0; $i < strlen($pattern); $i++)
285 if($char==null || $pattern{$i} == $char || $text)
287 $token .= $pattern{$i};
291 $tokens[] = str_replace("","'",$token);
292 $token = $pattern{$i};
295 if($pattern{$i} == "'" && $text == false)
297 else if($text && $pattern{$i} == "'" && $char == "'")
299 else if($text && $char != "'" && $pattern{$i} == "'")
302 $char = $pattern{$i};
311 * "yy" will return the last two digits of year.
312 * "yyyy" will return the full integer year.
313 * @param array getdate format.
314 * @param string a pattern.
315 * @return string year
317 protected function getYear($date, $pattern='yyyy')
319 $year = $date['year'];
323 return substr($year,2);
327 throw new Exception('The pattern for year is either "yy" or "yyyy".');
333 * "M" will return integer 1 through 12
334 * "MM" will return the narrow month name, e.g. "J"
335 * "MMM" will return the abrreviated month name, e.g. "Jan"
336 * "MMMM" will return the month name, e.g. "January"
337 * @param array getdate format.
338 * @param string a pattern.
339 * @return string month name
341 protected function getMonth($date, $pattern='M')
343 $month = $date['mon'];
350 return str_pad($month, 2,'0',STR_PAD_LEFT);
352 return $this->formatInfo->AbbreviatedMonthNames[$month-1];
355 return $this->formatInfo->MonthNames[$month-1];
357 throw new Exception('The pattern for month '.
358 'is "M", "MM", "MMM", or "MMMM".');
363 * Get the day of the week.
364 * "E" will return integer 0 (for Sunday) through 6 (for Saturday).
365 * "EE" will return the narrow day of the week, e.g. "M"
366 * "EEE" will return the abrreviated day of the week, e.g. "Mon"
367 * "EEEE" will return the day of the week, e.g. "Monday"
368 * @param array getdate format.
369 * @param string a pattern.
370 * @return string day of the week.
372 protected function getDayInWeek($date, $pattern='EEEE')
374 $day = $date['wday'];
382 return $this->formatInfo->NarrowDayNames[$day];
384 return $this->formatInfo->AbbreviatedDayNames[$day];
387 return $this->formatInfo->DayNames[$day];
390 throw new Exception('The pattern for day of the week '.
391 'is "E", "EE", "EEE", or "EEEE".');
396 * Get the day of the month.
397 * "d" for non-padding, "dd" will always return 2 characters.
398 * @param array getdate format.
399 * @param string a pattern.
400 * @return string day of the month
402 protected function getDay($date, $pattern='d')
404 $day = $date['mday'];
411 return str_pad($day, 2,'0',STR_PAD_LEFT);
413 throw new Exception('The pattern for day of '.
414 'the month is "d" or "dd".');
420 * Get the era. i.e. in gregorian, year > 0 is AD, else BC.
421 * @todo How to support multiple Eras?, e.g. Japanese.
422 * @param array getdate format.
423 * @param string a pattern.
426 protected function getEra($date, $pattern='G')
430 throw new Exception('The pattern for era is "G".');
432 $year = $date['year'];
434 return $this->formatInfo->getEra(1);
436 return $this->formatInfo->getEra(0);
440 * Get the hours in 24 hour format, i.e. [0-23].
441 * "H" for non-padding, "HH" will always return 2 characters.
442 * @param array getdate format.
443 * @param string a pattern.
444 * @return string hours in 24 hour format.
446 protected function getHour24($date, $pattern='H')
448 $hour = $date['hours'];
455 return str_pad($hour, 2,'0',STR_PAD_LEFT);
457 throw new Exception('The pattern for 24 hour '.
458 'format is "H" or "HH".');
463 * Get the AM/PM designator, 12 noon is PM, 12 midnight is AM.
464 * @param array getdate format.
465 * @param string a pattern.
466 * @return string AM or PM designator
468 protected function getAMPM($date, $pattern='a')
471 throw new Exception('The pattern for AM/PM marker is "a".');
473 $hour = $date['hours'];
474 $ampm = (int)($hour/12);
475 return $this->formatInfo->AMPMMarkers[$ampm];
479 * Get the hours in 12 hour format.
480 * "h" for non-padding, "hh" will always return 2 characters.
481 * @param array getdate format.
482 * @param string a pattern.
483 * @return string hours in 12 hour format.
485 protected function getHour12($date, $pattern='h')
487 $hour = $date['hours'];
488 $hour = ($hour==12|$hour==0)?12:($hour)%12;
495 return str_pad($hour, 2,'0',STR_PAD_LEFT);
497 throw new Exception('The pattern for 24 hour '.
498 'format is "H" or "HH".');
504 * "m" for non-padding, "mm" will always return 2 characters.
505 * @param array getdate format.
506 * @param string a pattern.
507 * @return string minutes.
509 protected function getMinutes($date, $pattern='m')
511 $minutes = $date['minutes'];
518 return str_pad($minutes, 2,'0',STR_PAD_LEFT);
520 throw new Exception('The pattern for minutes is "m" or "mm".');
526 * "s" for non-padding, "ss" will always return 2 characters.
527 * @param array getdate format.
528 * @param string a pattern.
529 * @return string seconds
531 protected function getSeconds($date, $pattern='s')
533 $seconds = $date['seconds'];
540 return str_pad($seconds, 2,'0',STR_PAD_LEFT);
542 throw new Exception('The pattern for seconds is "s" or "ss".');
547 * Get the timezone from the server machine.
548 * @todo How to get the timezone for a different region?
549 * @param array getdate format.
550 * @param string a pattern.
551 * @return string time zone
553 protected function getTimeZone($date, $pattern='z')
556 throw new Exception('The pattern for time zone is "z".');
558 return @date('T', @mktime($date['hours'], $date['minutes'], $date['seconds'], $date['mon'], $date['mday'], $date['year']));
562 * Get the day in the year, e.g. [1-366]
563 * @param array getdate format.
564 * @param string a pattern.
565 * @return int hours in AM/PM format.
567 protected function getDayInYear($date, $pattern='D')
570 throw new Exception('The pattern for day in year is "D".');
572 return $date['yday'];
576 * Get day in the month.
577 * @param array getdate format.
578 * @param string a pattern.
579 * @return int day in month
581 protected function getDayInMonth($date, $pattern='FF')
585 return @date('j', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']));
588 return @date('d', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']));
591 throw new Exception('The pattern for day in month is "F" or "FF".');
596 * Get the week in the year.
597 * @param array getdate format.
598 * @param string a pattern.
599 * @return int week in year
601 protected function getWeekInYear($date, $pattern='w')
604 throw new Exception('The pattern for week in year is "w".');
606 return @date('W', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']));
610 * Get week in the month.
611 * @param array getdate format.
612 * @return int week in month
614 protected function getWeekInMonth($date, $pattern='W')
617 throw new Exception('The pattern for week in month is "W".');
619 return @date('W', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year'])) - date('W', mktime(0, 0, 0, $date['mon'], 1, $date['year']));
623 * Get the hours [1-24].
624 * @param array getdate format.
625 * @param string a pattern.
626 * @return int hours [1-24]
628 protected function getHourInDay($date, $pattern='k')
631 throw new Exception('The pattern for hour in day is "k".');
633 return $date['hours']+1;
637 * Get the hours in AM/PM format, e.g [1-12]
638 * @param array getdate format.
639 * @param string a pattern.
640 * @return int hours in AM/PM format.
642 protected function getHourInAMPM($date, $pattern='K')
645 throw new Exception('The pattern for hour in AM/PM is "K".');
647 return ($date['hours']+1)%12;