8000 [Locale] IntlDateFormatter by igorw · Pull Request #63 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Locale] IntlDateFormatter #63

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
8051e9a
[Locale] refactored Locale class
eriksencosta Jan 25, 2011
2850851
[Locale] renamed and simplified Locale::isIntlExtensionAvailable()
Jan 25, 2011
4c1ce75
[Locale] added intl's \Locale constants to the Locale class
Jan 25, 2011
2333ee3
[Locale] added NumberFormatterInterface
eriksencosta Jan 25, 2011
8f17d18
[Locale] added NumberFormatter class
Jan 25, 2011
5a51450
[Locale] changed NumberFormatInterface::getLocale() to use Locale::AC…
Jan 25, 2011
6672c39
[Locale] added SimpleNumberFormatter class (not finished)
Jan 26, 2011
d245fb8
[Locale] partialy implemented \NumberFormatter's format() and formatC…
Jan 29, 2011
af499ee
[Locale] partial impl of \NumberFormatter::parse()
eriksencosta Jan 30, 2011
8b99817
[Locale] extracted method
Feb 2, 2011
75b55ca
[Locale] extract method refactoring
Feb 2, 2011
1b0c671
[Locale] method throws exception for unsupported argument value
Feb 2, 2011
b198a9e
[Locale] refactored test code
Feb 2, 2011
ff6083f
[Locale] removed support for ceil and floor rounding modes as them do…
Feb 2, 2011
353418e
[Locale] updated docblock
Feb 2, 2011
1559557
[Locale] added implementation to getErrorCode and getErrorMessage met…
Feb 2, 2011
33bb0c0
[Locale] not implemented methods throws RuntimeException
Feb 2, 2011
cceeefd
[Locale] Removed NumberFormatterInterface and NumberFormatter wrapper…
Feb 5, 2011
4f024e3
[Locale] moved and renamed SimpleNumberFormatter to StubNumberFormatter
Feb 5, 2011
0aaf7b6
[Locale] added learning tests for the \NumberFormatter class
Feb 5, 2011
59a0f72
[Locale] first implementation of StubIntlDateFormatter
igorw Feb 5, 2011
3da4307
[Locale] add support for escaping, give specifics on implementation u…
igorw Feb 6, 2011
09b24fa
[Locale] move intl bugs to skipped tests
igorw Feb 6, 2011
43794ba
[Locale] support for G and Q placeholders in StubIntlDateFormatter::f…
igorw Feb 6, 2011
af6fae6
[Locale] add support for L, which is the same as M
igorw Feb 6, 2011
a91c970
[Locale] use assertSame instead of assertEquals
igorw Feb 6, 2011
c1aa274
[Locale] add support for h
igorw Feb 6, 2011
fec50dc
[Locale] support for D (day of year)
igorw Feb 6, 2011
b7f42f0
[Locale] support for E (day of week)
igorw Feb 6, 2011
d3e24d6
[Locale] support for a (AM/PM)
igorw Feb 6, 2011
85d05c8
[Locale] support for H (24 hour)
igorw Feb 6, 2011
0396dab
[Locale] refactor IntlDateFormatter::format to build regExp dynamically
igorw Feb 6, 2011
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[Locale] partialy implemented \NumberFormatter's format() and formatC…
…urrency() methods in PHP
  • Loading branch information
Eriksen Costa authored and eriksencosta committed Jan 30, 2011
commit d245fb8edc575173dc16aee162f60f2fc2bf5d5f
226 changes: 210 additions & 16 deletions src/Symfony/Component/Locale/SimpleNumberFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,57 +19,144 @@
*/
class SimpleNumberFormatter implements NumberFormatterInterface
{
private $formatter = null;
/**
* Default values for the en locale.
*/
private $attributes = array(
self::FRACTION_DIGITS => 0,
self::GROUPING_USED => 1,
self::ROUNDING_MODE => self::ROUND_HALFEVEN
);

/**
* The supported styles to the constructor $styles argument.
*/
private static $supportedStyles = array(
'CURRENCY' => self::CURRENCY,
'DECIMAL' => self::DECIMAL
);

/**
* Supported attributes to the setAttribute() $attr argument.
*/
private static $supportedAttributes = array(
'FRACTION_DIGITS' => self::FRACTION_DIGITS,
'GROUPING_USED' => self::GROUPING_USED,
'ROUNDING_MODE' => self::ROUNDING_MODE
);

/**
* @see http://source.icu-project.org/repos/icu/icu/trunk/source/data/curr/en.txt
* The available rounding modes for setAttribute() usage with
* SimpleNumberFormatter::ROUNDING_MODE. SimpleNumberFormatter::ROUND_DOWN
* and SimpleNumberFormatter::ROUND_UP does not have a PHP only equivalent.
*/
private static $roundingModes = array(
'ROUND_CEILING' => self::ROUND_CEILING,
'ROUND_FLOOR' => self::ROUND_FLOOR,
'ROUND_HALFEVEN' => self::ROUND_HALFEVEN,
'ROUND_HALFDOWN' => self::ROUND_HALFDOWN,
'ROUND_HALFUP' => self::ROUND_HALFUP
);

/**
* The available values for setAttribute() usage with
* SimpleNumberFormatter::GROUPING_USED.
*/
private static $groupingUsedValues = array(0, 1);

/**
* The mapping between \NumberFormatter rounding modes to the available
* modes in PHP's round() function.
*
* @see http://www.php.net/manual/en/function.round.php
*/
private static $phpRoundingMap = array(
self::ROUND_HALFDOWN => \PHP_ROUND_HALF_DOWN,
self::ROUND_HALFEVEN => \PHP_ROUND_HALF_EVEN,
self::ROUND_HALFUP => \PHP_ROUND_HALF_UP
);

/**
* The currencies symbols. Each array have the symbol definition in
* hexadecimal and the decimal digits.
*
* @see http://source.icu-project.org/repos/icu/icu/trunk/source/data/curr/en.txt
* @todo Move this to Resources/data and use \ResourceBundle to load the data.
* @todo Search in the icu data where the currency subunits (usage of cents) are defined
*/
private $currencies = array(
'ALL' => array('0x410x4c0x4c', '%.0f'),
'BRL' => array('0x520x24', '%.2f'),
'CRC' => array('0xe20x820xa1', '%.0f')
'ALL' => array('0x410x4c0x4c', 0),
'BRL' => array('0x520x24', 2),
'CRC' => array('0xe20x820xa1', 0)
);

/**
* @{inheritDoc}
*/
public function __construct($locale = 'en', $style = null, $pattern = null)
{
if ('en' != $locale) {
throw new \InvalidArgumentException('Unsupported $locale value. Only the \'en\' locale is supported. Install the intl extension for full localization capabilities.');
}

if (!in_array($style, self::$supportedStyles)) {
throw new \InvalidArgumentException(sprintf(
'Unsupported $style value. The available styles are: %s. Install the intl extension for full localization capabilities.',
implode(', ', array_keys(self::$supportedStyles))
));
}

if (!is_null($pattern)) {
throw new \InvalidArgumentException('The $pattern value must be null. Install the intl extension for full localization capabilities.');
}
}

/**
* @{inheritDoc}
* @todo With the default rounding mode (ROUND_HALFEVEN), the currency value
* seems to be correctly rounded. However, since ROUND_CEILING is
* mapping to the ceil() function, the value is being returned. This
* is wrong.
*/
public function formatCurrency($value, $currency)
{
$symbol = '';
$hexSymbol = $this->currencies[$currency][0];
$format = $this->currencies[$currency][1];

$hex = explode('0x', $hexSymbol);
unset($hex[0]);
$symbol = $this->getCurrencySymbol($currency);
$value = $this->round($value, $this->currencies[$currency][1]);

foreach ($hex as $h) {
$symbol .= chr(hexdec($h));
$negative = false;
if (0 > $value) {
$negative = true;
$value *= -1;
}

return sprintf('%s'.$format, $symbol, $value);
$value = $this->formatNumber($value, $this->currencies[$currency][1]);

$ret = $symbol.$value;
return $negative ? '('.$ret.')' : $ret;
}

/**
* @{inheritDoc}
*/
public function format($value, $type = null)
public function format($value, $type = self::TYPE_DEFAULT)
{
if (0 > ($fractionDigits = $this->getAttribute(self::FRACTION_DIGITS))) {
$fractionDigits = 0;
}

// Rounding
$value = $this->round($value, $fractionDigits);
return $this->formatNumber($value, $fractionDigits);
}

/**
* @{inheritDoc}
*/
public function getAttribute($attr)
{

if (isset($this->attributes[$attr])) {
return $this->attributes[$attr];
}
}

/**
Expand Down Expand Up @@ -138,10 +225,30 @@ public function parse($value, $type = self::TYPE_DOUBLE, &$position = null)

/**
* @{inheritDoc}
* @todo Decide between throwing an exception if ROUDING_MODE or GROUPING_USED are invalid.
* In \NumberFormatter, a true is returned and the format/parse() methods have undefined values
* in these cases.
* @throws InvalidArgumentException When the $attr is not supported
*/
public function setAttribute($attr, $value)
{
if (!in_array($attr, self::$supportedAttributes)) {
throw new \InvalidArgumentException(sprintf(
'Unsupported $attr value. The available attributes are: %s. Install the intl extension for full localization capabilities.',
implode(', ', array_keys(self::$supportedAttributes))
));
}

if (self::$supportedAttributes['ROUNDING_MODE'] == $attr && $this->isInvalidRoundingMode($value)) {
return false;
}

if (self::$supportedAttributes['GROUPING_USED'] == $attr && $this->isInvalidGroupingUsedValue($value)) {
return false;
}

$this->attributes[$attr] = $value;
return true;
}

/**
Expand All @@ -167,4 +274,91 @@ public function setTextAttribute($attr, $value)
{

}

/**
* Returns the currency symbol.
*
* @param string $currency The 3-letter ISO 4217 currency code indicating the currency to use
* @return string The currency symbol
*/
private function getCurrencySymbol($currency)
{
$symbol = '';
$hexSymbol = $this->currencies[$currency][0];
$hex = explode('0x', $hexSymbol);
unset($hex[0]);

foreach ($hex as $h) {
$symbol .= chr(hexdec($h));
}

return $symbol;
}

/**
* Rounds a value.
*
* @param numeric $value The value to round
* @param int $precision The number of decimal digits to round to
* @return numeric The rounded value
*/
private function round($value, $precision)
{
switch ($this->getAttribute(self::ROUNDING_MODE)):
case self::ROUND_CEILING:
$value = ceil($value);
break;
case self::ROUND_FLOOR:
$value = floor($value);
break;
default:
$roundingMode = self::$phpRoundingMap[$this->getAttribute(self::ROUNDING_MODE)];
$value = round($value, $precision, $roundingMode);
break;
endswitch;

return $value;
}

/**
* Formats a number.
*
* @param numeric $value The numeric value to format
* @param int $precision The number of decimal digits to use
* @return string The formatted number
*/
private function formatNumber($value, $precision)
{
return number_format($value, $precision, '.', $this->getAttribute(self::GROUPING_USED) ? ',' : '');
}

/**
* Check if the rounding mode is invalid.
*
* @param int $value The rounding mode value to check
* @return bool true if the rounding mode is invalid, false otherwise
*/
private function isInvalidRoundingMode($value)
{
if (in_array($value, self::$roundingModes, true)) {
return false;
}

return true;
}

/**
* Check if the grouping value is invalid.
*
* @param int $value The grouping value to check
* @return bool true if the grouping value is invalid, false otherwise
*/
private function isInvalidGroupingUsedValue($value)
{
if (in_array($value, self::$groupingUsedValues, true)) {
return false;
}

return true;
}
}
Loading
0