Skip to content

Commit

Permalink
Bug fix in I18n
Browse files Browse the repository at this point in the history
Changing calls from date to strftime in TimeHelper
Implementing TimeHelper::converSpecifiers() to conver format strings to be windows safe and I18n friendly
Implementing TimeHelper::i18nFormat() to format dates with preferred locale date format
Changing TimeHelper::format() to handle inversion of first two parameters, while being backwards compatible. If called with the first parameter as a time string it will call TimeHelper::i18nFormat()
  • Loading branch information
lorenzo committed Jan 14, 2010
1 parent a980f72 commit 0b3758d
Show file tree
Hide file tree
Showing 4 changed files with 334 additions and 20 deletions.
4 changes: 2 additions & 2 deletions cake/libs/i18n.php
Expand Up @@ -307,7 +307,7 @@ function __bindTextDomain($domain) {
$this->__loadPo($f, $domain);
$this->__noLocale = false;
break 2;
} elseif (file_exists($localeDef) && ($f = fopen($localeDef, "r"))) {
} elseif (is_file($localeDef) && ($f = fopen($localeDef, "r"))) {
$this->__loadLocaleDefinition($f, $domain);
$this->__noLocale = false;
return $domain;
Expand Down Expand Up @@ -455,7 +455,7 @@ function __loadPo($file, $domain) {
/**
* Parses a locale definition file following the POSIX standard
*
* @param string $file file to load
* @param resource $file file handler
* @param string $domain Domain where locale definitions will be stored
* @return void
* @access private
Expand Down
176 changes: 158 additions & 18 deletions cake/libs/view/helpers/time.php
Expand Up @@ -28,6 +28,110 @@
*/
class TimeHelper extends AppHelper {

/**
* Converts a string representing the format for the function strftime and returns a
* windows safe and i18n aware format.
*
* @param string $format Format with specifiers for strftime function. Accepts the special specifier %S which mimics th modifier S for date()
* @param string UNIX timestamp
* @return string windows safe and date() function compatible format for strftime
*/
function convertSpecifiers($format, $time = null) {
if (!$time) {
$time = time();
}
$this->__time = $time;
return preg_replace_callback('/\%(\w+)/',array($this,'__translateSpecifier'),$format);
}

/**
* Auxiliary function to translate a matched specifier element from a regular expresion into
* a windows safe and i18n aware specifier
*
* @param array $specifier match from regular expression
* @return string converted element
*/
function __translateSpecifier($specifier) {
switch ($specifier[1]) {
case 'a':
$abday = __c('abday',5,true);
if (is_array($abday)) {
return $abday[date('w',$this->__time)];
}
break;
case 'A':
$day = __c('day',5,true);
if (is_array($day)) {
return $day[date('w',$this->__time)];
}
break;
case 'c':
$format = __c('d_t_fmt',5,true);
if ($format != 'd_t_fmt') {
return $this->convertSpecifiers($format,$this->__time);
}
break;
case 'C':
return sprintf("%02d", date('Y', $this->__time) / 100);
case 'D':
return '%m/%d/%y';
case 'eS' :
return date('jS',$this->__time);
case 'b':
case 'h':
$months = __c('abmon',5,true);
if (is_array($months)) {
return $months[date('n',$this->__time) -1];
}
return '%b';
case 'B':
$months = __c('mon',5,true);
if (is_array($months)) {
return $months[date('n',$this->__time) -1];
}
break;
case 'n':
return "\n";
case 'p':
case 'P':
$default = array('am' => 0, 'pm' => 1);
$meridiem = $default[date('a',$this->__time)];
$format = __c('am_pm',5,true);
if (is_array($format)) {
$meridiem = $format[$meridiem];
return ($specifier[1] == 'P') ? strtolower($meridiem) : strtoupper($meridiem);
}
break;
case 'r':
$complete = __c('t_fmt_ampm',5,true);
if ($complete != 't_fmt_ampm') {
return str_replace('%p',$this->__translateSpecifier(array('%p','p')),$complete);
}
break;
case 'R':
return date('H:i', $this->__time);
case 't':
return "\t";
case 'T':
return '%H:%M:%S';
case 'u':
return ($weekDay = date('w', $this->__time)) ? $weekDay : 7;
case 'x':
$format = __c('d_fmt',5,true);
if ($format != 'd_fmt') {
return $this->convertSpecifiers($format,$this->__time);
}
break;
case 'X':
$format = __c('t_fmt',5,true);
if ($format != 't_fmt') {
return $this->convertSpecifiers($format,$this->__time);
}
break;
}
return $specifier[0];
}

/**
* Converts given time (in server's time zone) to user's local time, given his/her offset from GMT.
*
Expand Down Expand Up @@ -62,7 +166,7 @@ function fromString($dateString, $userOffset = null) {
if (empty($dateString)) {
return false;
}
if (is_int($dateString) || is_numeric($dateString)) {
if (is_integer($dateString) || is_numeric($dateString)) {
$date = intval($dateString);
} else {
$date = strtotime($dateString);
Expand All @@ -86,8 +190,9 @@ function nice($dateString = null, $userOffset = null) {
} else {
$date = time();
}

return date("D, M jS Y, H:i", $date);
$format = $this->convertSpecifiers('%a, %b %eS %Y, %H:%M',$date);
$ret = strftime($format, $date);
return $this->output($ret);
}

/**
Expand All @@ -105,16 +210,18 @@ function nice($dateString = null, $userOffset = null) {
function niceShort($dateString = null, $userOffset = null) {
$date = $dateString ? $this->fromString($dateString, $userOffset) : time();

$y = $this->isThisYear($date) ? '' : ' Y';
$y = $this->isThisYear($date) ? '' : ' %Y';

if ($this->isToday($date)) {
$ret = sprintf(__('Today, %s',true), date("H:i", $date));
$ret = sprintf(__('Today, %s',true), strftime("%H:%M", $date));
} elseif ($this->wasYesterday($date)) {
$ret = sprintf(__('Yesterday, %s',true), date("H:i", $date));
$ret = sprintf(__('Yesterday, %s',true), strftime("%H:%M", $date));
} else {
$ret = date("M jS{$y}, H:i", $date);
$format = $this->convertSpecifiers("%b %eS{$y}, %H:%M",$date);
$ret = strftime($format, $date);
}
return $ret;

return $this->output($ret);
}

/**
Expand All @@ -132,7 +239,8 @@ function daysAsSql($begin, $end, $fieldName, $userOffset = null) {
$begin = date('Y-m-d', $begin) . ' 00:00:00';
$end = date('Y-m-d', $end) . ' 23:59:59';

return "($fieldName >= '$begin') AND ($fieldName <= '$end')";
$ret ="($fieldName >= '$begin') AND ($fieldName <= '$end')";
return $this->output($ret);
}

/**
Expand All @@ -146,7 +254,8 @@ function daysAsSql($begin, $end, $fieldName, $userOffset = null) {
*/
function dayAsSql($dateString, $fieldName, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return $this->daysAsSql($dateString, $dateString, $fieldName);
$ret = $this->daysAsSql($dateString, $dateString, $fieldName);
return $this->output($ret);
}

/**
Expand Down Expand Up @@ -250,7 +359,7 @@ function toQuarter($dateString, $range = false) {
break;
}
}
return $date;
return $this->output($date);
}

/**
Expand All @@ -261,7 +370,8 @@ function toQuarter($dateString, $range = false) {
* @return integer Unix timestamp
*/
function toUnix($dateString, $userOffset = null) {
return $this->fromString($dateString, $userOffset);
$ret = $this->fromString($dateString, $userOffset);
return $this->output($ret);
}

/**
Expand All @@ -273,7 +383,8 @@ function toUnix($dateString, $userOffset = null) {
*/
function toAtom($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return date('Y-m-d\TH:i:s\Z', $date);
$ret = date('Y-m-d\TH:i:s\Z', $date);
return $this->output($ret);
}

/**
Expand All @@ -285,7 +396,8 @@ function toAtom($dateString, $userOffset = null) {
*/
function toRSS($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return date("r", $date);
$ret = date("r", $date);
return $this->output($ret);
}

/**
Expand Down Expand Up @@ -465,7 +577,7 @@ function timeAgoInWords($dateTime, $options = array()) {
$relativeDate = sprintf(__('%s ago', true), $relativeDate);
}
}
return $relativeDate;
return $this->output($relativeDate);
}

/**
Expand Down Expand Up @@ -532,18 +644,46 @@ function gmt($string = null) {
/**
* Returns a formatted date string, given either a UNIX timestamp or a valid strtotime() date string.
*
* @param string $format date format string. defaults to 'd-m-Y'
* @param string $format date format string.
* @param string $dateString Datetime string
* @param boolean $invalid flag to ignore results of fromString == false
* @param int $userOffset User's offset from GMT (in hours)
* @return string Formatted date string
*/
function format($format = 'd-m-Y', $date, $invalid = false, $userOffset = null) {
function format($format, $date = null, $invalid = false, $userOffset = null) {
$time = $this->fromString($date, $userOffset);
$_time = $this->fromString($format, $userOffset);

if (is_numeric($_time) && $time === false) {
$format = $date;
return $this->i18nFormat($_time,$format,$invalid,$userOffset);
}
if ($time === false && $invalid !== false) {
return $invalid;
}
return date($format, $time);
}

/**
* Returns a formatted date string, given either a UNIX timestamp or a valid strtotime() date string.
* It take in account the default date format for the current language if a LC_TIME file is used.
* You must set the correct locale using setlocale() in order to translate day and month names
* @param string $dateString Datetime string
* @param string $format strftime format string.
* @param boolean $invalid flag to ignore results of fromString == false
* @param int $userOffset User's offset from GMT (in hours)
* @return string Formatted and translated date string
*/
function i18nFormat($date, $format = null, $invalid = false, $userOffset = null) {
$date = $this->fromString($date, $userOffset);
if ($date === false && $invalid !== false) {
return $invalid;
}
return date($format, $date);
if (empty($format)) {
$format = '%x';
}
$format = $this->convertSpecifiers($format,$date);
return strftime($format,$date);
}
}
?>

0 comments on commit 0b3758d

Please sign in to comment.