Blame | Letzte Änderung | Log anzeigen | RSS feed
<?php/*** NumberFormat 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.6 $ $Date: 2005/12/20 09:32:42 $* @package System.I18N.core*//*** Get the NumberFormatInfo class file.*/require_once(dirname(__FILE__).'/NumberFormatInfo.php');/*** Get the encoding utilities*/require_once(dirname(__FILE__).'/util.php');/*** NumberFormat class.** NumberFormat formats decimal numbers in any locale. The decimal* number is formatted according to a particular pattern. These* patterns can arise from the NumberFormatInfo object which is* culturally sensitive. The NumberFormat class can be instantiated in* many ways. E.g.** <code>* //create a invariant number formatter.* $formatter = new NumberFormat();** //create a number format for the french language locale.* $fr = new NumberFormat('fr');** //create a number format base on a NumberFormatInfo instance $numberInfo.* $format = new NumberFormat($numberInfo);* </code>** A normal decimal number can also be displayed as a currency* or as a percentage. For example* <code>* $format->format(1234.5); //Decimal number "1234.5"* $format->format(1234.5,'c'); //Default currency "$1234.50"* $format->format(0.25, 'p') //Percent "25%"* </code>** Currency is formated using the localized currency pattern. For example* to format the number as Japanese Yen:* <code>* $ja = new NumberFormat('ja_JP');** //Japanese currency pattern, and using Japanese Yen symbol* $ja->format(123.14,'c','JPY'); //�?123 (Yen 123)* </code>* For each culture, the symbol for each currency may be different.** @author Xiang Wei Zhuo <weizhuo[at]gmail[dot]com>* @version v1.0, last update on Fri Dec 10 18:10:20 EST 2004* @package System.I18N.core*/class NumberFormat{/*** The DateTimeFormatInfo, containing culture specific patterns and names.* @var DateTimeFormatInfo*/protected $formatInfo;/*** Create a new number format instance. The constructor can be instantiated* with a string that represent a culture/locale. Similarly, passing* a CultureInfo or NumberFormatInfo instance will instantiated a instance* for that particular culture.* @param mixed either null, a CultureInfo, a NumberFormatInfo, or string* @return NumberFormat*/function __construct($formatInfo=null){if($formatInfo === null)$this->formatInfo = NumberFormatInfo::getInvariantInfo();else if($formatInfo instanceof CultureInfo)$this->formatInfo = $formatInfo->NumberFormat;else if($formatInfo instanceof NumberFormatInfo)$this->formatInfo = $formatInfo;else$this->formatInfo =NumberFormatInfo::getInstance($formatInfo);}/*** For the number for a certain pattern. The valid patterns are* 'c', 'd', 'e', 'p' or a custom pattern, such as "#.000" for* 3 decimal places.* @param mixed the number to format.* @param string the format pattern, either, 'c', 'd', 'e', 'p'* or a custom pattern. E.g. "#.000" will format the number to* 3 decimal places.* @param string 3-letter ISO 4217 code. For example, the code* "USD" represents the US Dollar and "EUR" represents the Euro currency.* @return string formatted number string*/function format($number, $pattern='d', $currency='USD', $charset='UTF-8'){$this->setPattern($pattern);if(strtolower($pattern) == 'p')$number = $number * 100;$string = (string)$number;$decimal = $this->formatDecimal($string);$integer = $this->formatInteger(abs($number));if(strlen($decimal)>0)$result = $integer.$decimal;else$result = $integer;//get the suffixif($number >= 0)$suffix = $this->formatInfo->PositivePattern;else if($number < 0)$suffix = $this->formatInfo->NegativePattern;else$suffix = array("","");//append and prepend suffix$result = $suffix[0].$result.$suffix[1];//replace currency sign$symbol = @$this->formatInfo->getCurrencySymbol($currency);if($symbol === null) {$symbol = $currency;}$result = str_replace('¤',$symbol, $result);return I18N_toEncoding($result, $charset);}/*** For the integer, perform groupings and string padding.* @param string the decimal number in string form.* @return string formatted integer string with grouping*/protected function formatInteger($string){$string = (string)$string;$decimalDigits = $this->formatInfo->DecimalDigits;//if not decimal digits, assume 0 decimal points.if(is_int($decimalDigits) && $decimalDigits > 0)$string = (string)round(floatval($string),$decimalDigits);$dp = strpos($string, '.');if(is_int($dp))$string = substr($string, 0, $dp);$integer = '';$digitSize = $this->formatInfo->getDigitSize();$string = str_pad($string, $digitSize, '0',STR_PAD_LEFT);$len = strlen($string);$groupSeparator = $this->formatInfo->GroupSeparator;$groupSize = $this->formatInfo->GroupSizes;$firstGroup = true;$multiGroup = is_int($groupSize[1]);$count = 0;if(is_int($groupSize[0])){//now for the integer groupingsfor($i=0; $i<$len; $i++){$char = $string{$len-$i-1};if($multiGroup && $count == 0){if($i != 0 && $i%$groupSize[0] == 0){$integer = $groupSeparator . $integer;$count++;}}else if($multiGroup && $count >= 1){if($i != 0 && ($i-$groupSize[0])%$groupSize[1] == 0){$integer = $groupSeparator . $integer;$count++;}}else{if($i != 0 && $i%$groupSize[0] == 0){$integer = $groupSeparator . $integer;$count++;}}$integer = $char . $integer;}}else$integer = $string;return $integer;}/*** Format the decimal places.* @param string the decimal number in string form.* @return string formatted decimal places.*/protected function formatDecimal($string){$dp = strpos($string, '.');$decimal = '';$decimalDigits = $this->formatInfo->DecimalDigits;$decimalSeparator = $this->formatInfo->DecimalSeparator;//do the correct rounding here//$string = round(floatval($string), $decimalDigits);if(is_int($dp)){if($decimalDigits == -1){$decimal = substr($string, $dp+1);}else if(is_int($decimalDigits)){$float = round((float)$string, $decimalDigits);if(strpos((string)$float, '.') === false){$decimal = str_pad($decimal,$decimalDigits,'0');}else{$decimal = substr($float, strpos($float,'.')+1);if(strlen($decimal)<$decimalDigits)$decimal = str_pad($decimal,$decimalDigits,'0');}}elsereturn $decimal;return $decimalSeparator.$decimal;}else if ($decimalDigits > 0)return $decimalSeparator.str_pad($decimal,$decimalDigits,'0');return $decimal;}/*** Set the pattern to format against. The default patterns* are retrieved from the NumberFormatInfo instance.* @param string the requested patterns.* @return string a number format pattern.*/protected function setPattern($pattern){switch($pattern){case 'c':case 'C':$this->formatInfo->setPattern(NumberFormatInfo::CURRENCY);break;case 'd':case 'D':$this->formatInfo->setPattern(NumberFormatInfo::DECIMAL);break;case 'e':case 'E':$this->formatInfo->setPattern(NumberFormatInfo::SCIENTIFIC);break;case 'p':case 'P':$this->formatInfo->setPattern(NumberFormatInfo::PERCENTAGE);break;default:$this->formatInfo->setPattern($pattern);break;}}}