diff options
Diffstat (limited to 'framework/I18N/core/DateFormat.php')
-rw-r--r-- | framework/I18N/core/DateFormat.php | 645 |
1 files changed, 645 insertions, 0 deletions
diff --git a/framework/I18N/core/DateFormat.php b/framework/I18N/core/DateFormat.php new file mode 100644 index 00000000..1e340d95 --- /dev/null +++ b/framework/I18N/core/DateFormat.php @@ -0,0 +1,645 @@ +<?php
+/**
+ * DateFormat class file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the BSD License.
+ *
+ * Copyright(c) 2004 by Qiang Xue. All rights reserved.
+ *
+ * To contact the author write to {@link mailto:qiang.xue@gmail.com Qiang Xue}
+ * The latest version of PRADO can be obtained from:
+ * {@link http://prado.sourceforge.net/}
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @version $Revision: 1.8 $ $Date: 2005/12/15 07:14:49 $
+ * @package System.I18N.core
+ */
+
+/**
+ * Get the DateTimeFormatInfo class.
+ */
+require_once(dirname(__FILE__).'/DateTimeFormatInfo.php');
+
+/**
+ * Get the encoding utilities
+ */
+require_once(dirname(__FILE__).'/util.php');
+
+/**
+ * DateFormat class.
+ *
+ * The DateFormat class allows you to format dates and times with
+ * predefined styles in a locale-sensitive manner. Formatting times
+ * with the DateFormat class is similar to formatting dates.
+ *
+ * Formatting dates with the DateFormat class is a two-step process.
+ * First, you create a formatter with the getDateInstance method.
+ * Second, you invoke the format method, which returns a string containing
+ * the formatted date.
+ *
+ * DateTime values are formatted using standard or custom patterns stored
+ * in the properties of a DateTimeFormatInfo.
+ *
+ * @author Xiang Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @version v1.0, last update on Sat Dec 04 14:10:49 EST 2004
+ * @package System.I18N.core
+ */
+class DateFormat
+{
+ /**
+ * A list of tokens and their function call.
+ * @var array
+ */
+ protected $tokens = array(
+ 'G'=>'Era',
+ 'y'=>'Year',
+ 'M'=>'Month',
+ 'd'=>'Day',
+ 'h'=>'Hour12',
+ 'H'=>'Hour24',
+ 'm'=>'Minutes',
+ 's'=>'Seconds',
+ 'E'=>'DayInWeek',
+ 'D'=>'DayInYear',
+ 'F'=>'DayInMonth',
+ 'w'=>'WeekInYear',
+ 'W'=>'WeekInMonth',
+ 'a'=>'AMPM',
+ 'k'=>'HourInDay',
+ 'K'=>'HourInAMPM',
+ 'z'=>'TimeZone'
+ );
+
+ /**
+ * A list of methods, to be used by the token function calls.
+ * @var array
+ */
+ protected $methods = array();
+
+ /**
+ * The DateTimeFormatInfo, containing culture specific patterns and names.
+ * @var DateTimeFormatInfo
+ */
+ protected $formatInfo;
+
+ /**
+ * Initialize a new DateFormat.
+ * @param mixed either, null, a CultureInfo instance,
+ * a DateTimeFormatInfo instance, or a locale.
+ * @return DateFormat instance
+ */
+ function __construct($formatInfo=null)
+ {
+ if(is_null($formatInfo))
+ $this->formatInfo = DateTimeFormatInfo::getInvariantInfo();
+ else if($formatInfo instanceof CultureInfo)
+ $this->formatInfo = $formatInfo->DateTimeFormat;
+ else if($formatInfo instanceof DateTimeFormatInfo)
+ $this->formatInfo = $formatInfo;
+ else
+ $this->formatInfo = DateTimeFormatInfo::getInstance($formatInfo);
+
+ $this->methods = get_class_methods($this);
+ }
+
+ /**
+ * Format a date according to the pattern.
+ * @param mixed the time as integer or string in strtotime format.
+ * @return string formatted date time.
+ */
+ public function format($time, $pattern='F', $charset='UTF-8')
+ {
+ if(is_string($time))
+ $time = @strtotime($time);
+
+ if(is_null($pattern))
+ $pattern = 'F';
+
+ $date = @getdate($time);
+
+ $pattern = $this->getPattern($pattern);
+
+ $tokens = $this->getTokens($pattern);
+
+ for($i = 0; $i<count($tokens); $i++)
+ {
+ $pattern = $tokens[$i];
+ if($pattern{0} == "'"
+ && $pattern{strlen($pattern)-1} == "'")
+ {
+ $tokens[$i] = preg_replace('/(^\')|(\'$)/','',$pattern);
+ }
+ else
+ {
+ $function = $this->getFunctionName($pattern);
+ if($function != null)
+ {
+ $fName = 'get'.$function;
+ if(in_array($fName, $this->methods))
+ {
+ $rs = $this->$fName($date, $pattern);
+ $tokens[$i] = $rs;
+ }
+ else
+ throw new
+ Exception('function '.$function.' not found.');
+ }
+ }
+ }
+
+ return I18N_toEncoding(implode('',$tokens), $charset);
+ }
+
+ /**
+ * For a particular token, get the corresponding function to call.
+ * @param string token
+ * @return mixed the function if good token, null otherwise.
+ */
+ protected function getFunctionName($token)
+ {
+ if(isset($this->tokens[$token{0}]))
+ return $this->tokens[$token{0}];
+ }
+
+ /**
+ * Get the pattern from DateTimeFormatInfo or some predefined patterns.
+ * If the $pattern parameter is an array of 2 element, it will assume
+ * that the first element is the date, and second the time
+ * and try to find an appropriate pattern and apply
+ * DateTimeFormatInfo::formatDateTime
+ * See the tutorial documentation for futher details on the patterns.
+ * @param mixed a pattern.
+ * @return string a pattern.
+ * @see DateTimeFormatInfo::formatDateTime()
+ */
+ protected function getPattern($pattern)
+ {
+ if(is_array($pattern) && count($pattern) == 2)
+ {
+ return $this->formatInfo->formatDateTime(
+ $this->getPattern($pattern[0]),
+ $this->getPattern($pattern[1]));
+ }
+
+ switch($pattern)
+ {
+ case 'd':
+ return $this->formatInfo->ShortDatePattern;
+ break;
+ case 'D':
+ return $this->formatInfo->LongDatePattern;
+ break;
+ case 'p':
+ return $this->formatInfo->MediumDatePattern;
+ break;
+ case 'P':
+ return $this->formatInfo->FullDatePattern;
+ break;
+ case 't':
+ return $this->formatInfo->ShortTimePattern;
+ break;
+ case 'T':
+ return $this->formatInfo->LongTimePattern;
+ break;
+ case 'q':
+ return $this->formatInfo->MediumTimePattern;
+ break;
+ case 'Q':
+ return $this->formatInfo->FullTimePattern;
+ break;
+ case 'f':
+ return $this->formatInfo->formatDateTime(
+ $this->formatInfo->LongDatePattern,
+ $this->formatInfo->ShortTimePattern);
+ break;
+ case 'F':
+ return $this->formatInfo->formatDateTime(
+ $this->formatInfo->LongDatePattern,
+ $this->formatInfo->LongTimePattern);
+ break;
+ case 'g':
+ return $this->formatInfo->formatDateTime(
+ $this->formatInfo->ShortDatePattern,
+ $this->formatInfo->ShortTimePattern);
+ break;
+ case 'G':
+ return $this->formatInfo->formatDateTime(
+ $this->formatInfo->ShortDatePattern,
+ $this->formatInfo->LongTimePattern);
+ break;
+ case 'M':
+ case 'm':
+ return 'MMMM dd';
+ break;
+ case 'R':
+ case 'r':
+ return 'EEE, dd MMM yyyy HH:mm:ss';
+ break;
+ case 's':
+ return 'yyyy-MM-ddTHH:mm:ss';
+ break;
+ case 'u':
+ return 'yyyy-MM-dd HH:mm:ss z';
+ break;
+ case 'U':
+ return 'EEEE dd MMMM yyyy HH:mm:ss';
+ break;
+ case 'Y':
+ case 'y':
+ return 'yyyy MMMM';
+ break;
+ default :
+ return $pattern;
+ }
+ }
+
+ /**
+ * Tokenize the pattern. The tokens are delimited by group of
+ * similar characters, e.g. 'aabb' will form 2 tokens of 'aa' and 'bb'.
+ * Any substrings, starting and ending with a single quote (')
+ * will be treated as a single token.
+ * @param string pattern.
+ * @return array string tokens in an array.
+ */
+ protected function getTokens($pattern)
+ {
+ $char = null;
+ $tokens = array();
+ $token = null;
+
+ $text = false;
+
+ for($i = 0; $i < strlen($pattern); $i++)
+ {
+ if($char==null || $pattern{$i} == $char || $text)
+ {
+ $token .= $pattern{$i};
+ }
+ else
+ {
+ $tokens[] = str_replace("''","'",$token);
+ $token = $pattern{$i};
+ }
+
+ if($pattern{$i} == "'" && $text == false)
+ $text = true;
+ else if($text && $pattern{$i} == "'" && $char == "'")
+ $text = true;
+ else if($text && $char != "'" && $pattern{$i} == "'")
+ $text = false;
+
+ $char = $pattern{$i};
+
+ }
+ $tokens[] = $token;
+ return $tokens;
+ }
+
+ /**
+ * Get the year.
+ * "yy" will return the last two digits of year.
+ * "yyyy" will return the full integer year.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string year
+ */
+ protected function getYear($date, $pattern='yyyy')
+ {
+ $year = $date['year'];
+ switch($pattern)
+ {
+ case 'yy':
+ return substr($year,2);
+ case 'yyyy':
+ return $year;
+ default:
+ throw new Exception('The pattern for year is either "yy" or "yyyy".');
+ }
+ }
+
+ /**
+ * Get the month.
+ * "M" will return integer 1 through 12
+ * "MM" will return the narrow month name, e.g. "J"
+ * "MMM" will return the abrreviated month name, e.g. "Jan"
+ * "MMMM" will return the month name, e.g. "January"
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string month name
+ */
+ protected function getMonth($date, $pattern='M')
+ {
+ $month = $date['mon'];
+
+ switch($pattern)
+ {
+ case 'M':
+ return $month;
+ case 'MM':
+ return str_pad($month, 2,'0',STR_PAD_LEFT);
+ case 'MMM':
+ return $this->formatInfo->AbbreviatedMonthNames[$month-1];
+ break;
+ case 'MMMM':
+ return $this->formatInfo->MonthNames[$month-1];
+ default:
+ throw new Exception('The pattern for month '.
+ 'is "M", "MM", "MMM", or "MMMM".');
+ }
+ }
+
+ /**
+ * Get the day of the week.
+ * "E" will return integer 0 (for Sunday) through 6 (for Saturday).
+ * "EE" will return the narrow day of the week, e.g. "M"
+ * "EEE" will return the abrreviated day of the week, e.g. "Mon"
+ * "EEEE" will return the day of the week, e.g. "Monday"
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string day of the week.
+ */
+ protected function getDayInWeek($date, $pattern='EEEE')
+ {
+ $day = $date['wday'];
+
+ switch($pattern)
+ {
+ case 'E':
+ return $day;
+ break;
+ case 'EE':
+ return $this->formatInfo->NarrowDayNames[$day];
+ case 'EEE':
+ return $this->formatInfo->AbbreviatedDayNames[$day];
+ break;
+ case 'EEEE':
+ return $this->formatInfo->DayNames[$day];
+ break;
+ default:
+ throw new Exception('The pattern for day of the week '.
+ 'is "E", "EE", "EEE", or "EEEE".');
+ }
+ }
+
+ /**
+ * Get the day of the month.
+ * "d" for non-padding, "dd" will always return 2 characters.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string day of the month
+ */
+ protected function getDay($date, $pattern='d')
+ {
+ $day = $date['mday'];
+
+ switch($pattern)
+ {
+ case 'd':
+ return $day;
+ case 'dd':
+ return str_pad($day, 2,'0',STR_PAD_LEFT);
+ default:
+ throw new Exception('The pattern for day of '.
+ 'the month is "d" or "dd".');
+ }
+ }
+
+
+ /**
+ * Get the era. i.e. in gregorian, year > 0 is AD, else BC.
+ * @todo How to support multiple Eras?, e.g. Japanese.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string era
+ */
+ protected function getEra($date, $pattern='G')
+ {
+
+ if($pattern != 'G')
+ throw new Exception('The pattern for era is "G".');
+
+ $year = $date['year'];
+ if($year > 0)
+ return $this->formatInfo->getEra(1);
+ else
+ return $this->formatInfo->getEra(0);
+ }
+
+ /**
+ * Get the hours in 24 hour format, i.e. [0-23].
+ * "H" for non-padding, "HH" will always return 2 characters.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string hours in 24 hour format.
+ */
+ protected function getHour24($date, $pattern='H')
+ {
+ $hour = $date['hours'];
+
+ switch($pattern)
+ {
+ case 'H':
+ return $hour;
+ case 'HH':
+ return str_pad($hour, 2,'0',STR_PAD_LEFT);
+ default:
+ throw new Exception('The pattern for 24 hour '.
+ 'format is "H" or "HH".');
+ }
+ }
+
+ /**
+ * Get the AM/PM designator, 12 noon is PM, 12 midnight is AM.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string AM or PM designator
+ */
+ protected function getAMPM($date, $pattern='a')
+ {
+ if($pattern != 'a')
+ throw new Exception('The pattern for AM/PM marker is "a".');
+
+ $hour = $date['hours'];
+ $ampm = intval($hour/12);
+ return $this->formatInfo->AMPMMarkers[$ampm];
+ }
+
+ /**
+ * Get the hours in 12 hour format.
+ * "h" for non-padding, "hh" will always return 2 characters.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string hours in 12 hour format.
+ */
+ protected function getHour12($date, $pattern='h')
+ {
+ $hour = $date['hours'];
+ $hour = ($hour==12|$hour==0)?12:($hour)%12;
+
+ switch($pattern)
+ {
+ case 'h':
+ return $hour;
+ case 'hh':
+ return str_pad($hour, 2,'0',STR_PAD_LEFT);
+ default:
+ throw new Exception('The pattern for 24 hour '.
+ 'format is "H" or "HH".');
+ }
+ }
+
+ /**
+ * Get the minutes.
+ * "m" for non-padding, "mm" will always return 2 characters.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string minutes.
+ */
+ protected function getMinutes($date, $pattern='m')
+ {
+ $minutes = $date['minutes'];
+
+ switch($pattern)
+ {
+ case 'm':
+ return $minutes;
+ case 'mm':
+ return str_pad($minutes, 2,'0',STR_PAD_LEFT);
+ default:
+ throw new Exception('The pattern for minutes is "m" or "mm".');
+ }
+ }
+
+ /**
+ * Get the seconds.
+ * "s" for non-padding, "ss" will always return 2 characters.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string seconds
+ */
+ protected function getSeconds($date, $pattern='s')
+ {
+ $seconds = $date['seconds'];
+
+ switch($pattern)
+ {
+ case 's':
+ return $seconds;
+ case 'ss':
+ return str_pad($seconds, 2,'0',STR_PAD_LEFT);
+ default:
+ throw new Exception('The pattern for seconds is "s" or "ss".');
+ }
+ }
+
+ /**
+ * Get the timezone from the server machine.
+ * @todo How to get the timezone for a different region?
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return string time zone
+ */
+ protected function getTimeZone($date, $pattern='z')
+ {
+ if($pattern != 'z')
+ throw new Exception('The pattern for time zone is "z".');
+
+ return @date('T', @mktime($date['hours'], $date['minutes'], $date['seconds'], $date['mon'], $date['mday'], $date['year']));
+ }
+
+ /**
+ * Get the day in the year, e.g. [1-366]
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return int hours in AM/PM format.
+ */
+ protected function getDayInYear($date, $pattern='D')
+ {
+ if($pattern != 'D')
+ throw new Exception('The pattern for day in year is "D".');
+
+ return $date['yday'];
+ }
+
+ /**
+ * Get day in the month.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return int day in month
+ */
+ protected function getDayInMonth($date, $pattern='FF')
+ {
+ switch ($pattern) {
+ case 'F':
+ return @date('j', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']));
+ break;
+ case 'FF':
+ return @date('d', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']));
+ break;
+ default:
+ throw new Exception('The pattern for day in month is "F" or "FF".');
+ }
+ }
+
+ /**
+ * Get the week in the year.
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return int week in year
+ */
+ protected function getWeekInYear($date, $pattern='w')
+ {
+ if($pattern != 'w')
+ throw new Exception('The pattern for week in year is "w".');
+
+ return @date('W', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']));
+ }
+
+ /**
+ * Get week in the month.
+ * @param array getdate format.
+ * @return int week in month
+ */
+ protected function getWeekInMonth($date, $pattern='W')
+ {
+ if($pattern != 'W')
+ throw new Exception('The pattern for week in month is "W".');
+
+ return @date('W', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year'])) - date('W', mktime(0, 0, 0, $date['mon'], 1, $date['year']));
+ }
+
+ /**
+ * Get the hours [1-24].
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return int hours [1-24]
+ */
+ protected function getHourInDay($date, $pattern='k')
+ {
+ if(is_null($dateTimeInfo))
+ $dateTimeInfo = $this->dateTimeInfo;
+
+ if($pattern != 'k')
+ throw new Exception('The pattern for hour in day is "k".');
+
+ return $date['hours']+1;
+ }
+
+ /**
+ * Get the hours in AM/PM format, e.g [1-12]
+ * @param array getdate format.
+ * @param string a pattern.
+ * @return int hours in AM/PM format.
+ */
+ protected function getHourInAMPM($date, $pattern='K')
+ {
+ if($pattern != 'K')
+ throw new Exception('The pattern for hour in AM/PM is "K".');
+
+ return ($date['hours']+1)%12;
+ }
+
+}
+
+?>
\ No newline at end of file |