diff options
author | sgiehl <stefan@piwik.org> | 2015-07-04 22:28:26 +0300 |
---|---|---|
committer | sgiehl <stefan@piwik.org> | 2015-09-25 21:07:47 +0300 |
commit | 4e6f8349ac42dd26917687d873e935a6afb34642 (patch) | |
tree | 79f4ee5c0e56a74d8d5124dc13c49b42024890bc /core | |
parent | 7f375924db9328f20a0b7cb1e41397f2309b60a7 (diff) |
prepare date class to handle cldr date/time formats
Diffstat (limited to 'core')
-rw-r--r-- | core/Date.php | 210 |
1 files changed, 190 insertions, 20 deletions
diff --git a/core/Date.php b/core/Date.php index 1448c23826..4fac9d8595 100644 --- a/core/Date.php +++ b/core/Date.php @@ -29,7 +29,7 @@ use Piwik\Container\StaticContainer; * * $date = Date::factory('2007-07-24 14:04:24', 'EST'); * $date->addHour(5); - * echo $date->getLocalized("%longDay% the %day% of %longMonth% at %time%"); + * echo $date->getLocalized("EEE, d. MMM y 'at' HH:mm:ss"); * * @api */ @@ -604,8 +604,33 @@ class Date /** * Returns a localized date string using the given template. * The template should contain tags that will be replaced with localized date strings. + * + * @param string $template eg. `"MMM y"` + * @return string eg. `"Aug 2009"` + */ + public function getLocalized($template) + { + $template = $this->replaceLegacyPlaceholders($template); + + $tokens = self::parseFormat($template); + + $out = ''; + + foreach ($tokens AS $token) { + if (is_array($token)) { + $out .= $this->formatToken(array_shift($token)); + + } else { + $out .= $token; + } + } + + return $out; + } + /** + * Replaces legacy placeholders * - * Allowed tags include: + * @deprecated should be removed in Piwik 3.0.0 or later * * - **%day%**: replaced with the day of the month without leading zeros, eg, **1** or **20**. * - **%shortMonth%**: the short month in the current language, eg, **Jan**, **Feb**. @@ -615,28 +640,173 @@ class Date * - **%longYear%**: the four digit year, eg, **2007**, **2013**. * - **%shortYear%**: the two digit year, eg, **07**, **13**. * - **%time%**: the time of day, eg, **07:35:00**, or **15:45:00**. - * - * @param string $template eg. `"%shortMonth% %longYear%"` - * @return string eg. `"Aug 2009"` */ - public function getLocalized($template) + protected function replaceLegacyPlaceholders($template) + { + $mapping = array( + '%day%' => 'd', + '%shortMonth%' => 'MMM', + '%longMonth%' => 'MMMM', + '%shortDay%' => 'EEE', + '%longDay%' => 'EEEE', + '%longYear%' => 'y', + '%shortYear%' => 'yy', + '%time%' => 'HH:mm:ss' + ); + + return str_replace(array_keys($mapping), array_values($mapping), $template); + } + + protected function formatToken($token) { - $translator = StaticContainer::get('Piwik\Translation\Translator'); - $day = $this->toString('j'); $dayOfWeek = $this->toString('N'); $monthOfYear = $this->toString('n'); - $patternToValue = array( - "%day%" => $day, - "%shortMonth%" => $translator->translate('Intl_ShortMonth_' . $monthOfYear), - "%longMonth%" => $translator->translate('Intl_LongMonth_' . $monthOfYear), - "%shortDay%" => $translator->translate('Intl_ShortDay_' . $dayOfWeek), - "%longDay%" => $translator->translate('Intl_LongDay_' . $dayOfWeek), - "%longYear%" => $this->toString('Y'), - "%shortYear%" => $this->toString('y'), - "%time%" => $this->toString('H:i:s') - ); - $out = str_replace(array_keys($patternToValue), array_values($patternToValue), $template); - return $out; + $translator = StaticContainer::get('Piwik\Translation\Translator'); + + switch ($token) { + // year + case "yyyy": + case "y": + return $this->toString('Y'); + case "yy": + return $this->toString('y'); + // month + case "MMMM": + return $translator->translate('Intl_Month_Long_' . $monthOfYear); + case "MMM": + return $translator->translate('Intl_Month_Short_' . $monthOfYear); + case "MM": + return $this->toString('n'); + case "M": + return $this->toString('m'); + case "LLLL": + return $translator->translate('Intl_Month_Long_StandAlone_' . $monthOfYear); + case "LLL": + return $translator->translate('Intl_Month_Short_StandAlone_' . $monthOfYear); + case "LL": + return $this->toString('n'); + case "L": + return $this->toString('m'); + // day + case "dd": + return $this->toString('d'); + case "d": + return $this->toString('j'); + case "EEEE": + return $translator->translate('Intl_Day_Long_' . $dayOfWeek); + case "EEE": + case "EE": + case "E": + return $translator->translate('Intl_Day_Short_' . $dayOfWeek); + case "CCCC": + return $translator->translate('Intl_Day_Long_StandAlone_' . $dayOfWeek); + case "CCC": + case "CC": + case "C": + return $translator->translate('Intl_Day_Short_StandAlone_' . $dayOfWeek); + case "D": + return 1 + (int)$this->toString('z'); // 1 - 366 + case "F": + return (int)(((int)$this->toString('j')+6)/7); + // week in month + case "w": + $weekDay=date('N',mktime(0,0,0,$this->toString('m'),1,$this->toString('y'))); + return floor(($weekDay+(int)$this->toString('m')-2)/7)+1; + // week in year + case "W": + return $this->toString('N'); + // hour + case "HH": + return $this->toString('H'); + case "H": + return $this->toString('G'); + case "hh": + return $this->toString('h'); + case "h": + return $this->toString('g'); + // minute + case "mm": + case "m": + return $this->toString('i'); + // second + case "ss": + case "s": + return $this->toString('s'); + // am / pm + case "a": + return $this->toString('a') == 'am' ? $translator->translate('Intl_Time_AM') : $translator->translate('Intl_Time_PM'); + + // currently not implemented: + case "G": + case "GG": + case "GGG": + case "GGGG": + case "GGGGG": + return ''; // era + case "z": + case "Z": + case "v": + return ''; // time zone + + } + + return ''; + } + + protected static $tokens = array( + 'G', 'y', 'M', 'L', 'd', 'h', 'H', 'm', 's', 'E', 'c', 'e', 'D', 'F', 'w', 'W', 'a', 'z', 'Z', 'v', + ); + + /** + * Parses the datetime format pattern. + * @param string $pattern the pattern to be parsed + * @return array tokenized parsing result + */ + protected static function parseFormat($pattern) + { + static $formats = array(); // cache + if (isset($formats[$pattern])) { + return $formats[$pattern]; + } + $tokens = array(); + $n = strlen($pattern); + $isLiteral = false; + $literal = ''; + for ($i = 0; $i < $n; ++$i) { + $c = $pattern[$i]; + if ($c === "'") { + if ($i < $n - 1 && $pattern[$i + 1] === "'") { + $tokens[] = "'"; + $i++; + } elseif ($isLiteral) { + $tokens[] = $literal; + $literal = ''; + $isLiteral = false; + } else { + $isLiteral = true; + $literal = ''; + } + } elseif ($isLiteral) { + $literal .= $c; + } else { + for ($j = $i + 1; $j < $n; ++$j) { + if ($pattern[$j] !== $c) { + break; + } + } + $p = str_repeat($c, $j - $i); + if (in_array($c, self::$tokens)) { + $tokens[] = array($p); + } else { + $tokens[] = $p; + } + $i = $j - 1; + } + } + if ($literal !== '') { + $tokens[] = $literal; + } + return $formats[$pattern] = $tokens; } /** |