如何更改接受空格和非空格的NumberFormatter :: parseCurrency()行为?

nof*_*ame 9 php icu numberformatter intl

我正在尝试将本地化的货币字符串解析为货币和浮动值.

一切都运作良好,现在我们遇到了一些问题.看起来NumberFormatter :: parseCurrency使用了一个额外的不可见字符:

Testcode:

<?php
$formatter = new NumberFormatter("de_DE", NumberFormatter::CURRENCY);
var_dump(array(
    $formatter->parseCurrency("88,22 €", $curr), // taken from output of $formatter->format(88.22)
    $formatter->parseCurrency("88,22 €", $curr), // input with keyboard
    $formatter->parseCurrency("88,22 \xE2\x82\xAc", $curr), // just a test
    $formatter->format(88.22),
    "88,22 €" // keyboard input
));
Run Code Online (Sandbox Code Playgroud)

输出:

array(5) {
  [0]=> float(88,22)
  [1]=> bool(false)
  [2]=> bool(false)
  [3]=> string(10) "88,22 €" // this as input works
  [4]=> string(9) "88,22 €" // this not...
}
Run Code Online (Sandbox Code Playgroud)

如您所见,输出3和4的字符串长度存在差异.

我在PHP 5.3(启用了mbstring的ubuntu)和5.4(Mac OS X上的Zend Server)中得到了相同的结果.

主要问题是,来自我的表单(ZF1应用程序)的输入值与索引4的输出相同...

有什么建议?提前致谢

EDIT1:

工作价值的hexdump:

00000000  38 38 2c 32 32 c2 a0 e2  82 ac 0a                 |88,22......|
0000000b
Run Code Online (Sandbox Code Playgroud)

非工作价值的hexdump:

00000000  38 38 2c 32 32 20 e2 82  ac 0a                    |88,22 ....|
0000000a
Run Code Online (Sandbox Code Playgroud)

EDIT2:

使用的whitepsace似乎是一个问题.c2 a0是NO-BREAK SPACE,并且(可能?)是NumberFormatter :: parseCurrency()所必需的.但0x20是默认空格(在输入表单中输入).当前的解决方法是使用NO-BREAK SPACE替换空白$value = str_replace("\x20", "\xC2\xA0", $value);

EDIT3:

在另一个系统(带有Zend Server 5.6的Mac OS X,启用了mbstring,PHP 5.3.14)中,一切都按预期工作:

array(5) {
  [0]=> float(88,22)
  [1]=> float(88,22)
  [2]=> float(88,22)
  [3]=> string(9) "88,22 €"
  [4]=> string(9) "88,22 €"
}
Run Code Online (Sandbox Code Playgroud)

Edit4:

使用空间和使用非中断空间配置之间的主要区别是ICU版本:

工作版:

intl

Internationalization support => enabled
version => 1.1.0
ICU version => 3.8.1

Directive => Local Value => Master Value
intl.default_locale => no value => no value
intl.error_level => 0 => 0
Run Code Online (Sandbox Code Playgroud)

不工作版本:

intl

Internationalization support => enabled
version => 1.1.0
ICU version => 4.8.1.1
ICU Data version => 4.8.1

Directive => Local Value => Master Value
intl.default_locale => no value => no value
intl.error_level => 0 => 0
Run Code Online (Sandbox Code Playgroud)

cmb*_*ley 3

NumberFormatter::parseCurrency是 ICU 库函数的薄包装unum_parseDoubleCurrency参见源代码)。

\n\n

ICU 库函数具有限制性,因为它只能解析由其双重函数产生的字符串unum_formatDoubleCurrency。该格式由 Unicode 区域设置数据驱动,该数据指定货币值和数值之间的不间断空格。显然,该库的早期版本接受其他空白字符。

\n\n

简而言之,您不能使用NumberFormatter::parseCurrency接受空格。但是,Zend_Currency默认情况下还应该输出不间断空格:

\n\n
$currency = new Zend_Currency(array(\n     \'currency\' => \'EUR\',\n     \'value\'    => 88.22,\n), \'de_DE\');\n\nvar_dump(\n    strval($currency),             // 88,22\xc2\xa0\xe2\x82\xac\n    strpos($currency, "\\x20"),     // false\n    strpos($currency, "\\xc2\\xa0")  // 5\n);\n
Run Code Online (Sandbox Code Playgroud)\n\n

问题是应用程序的哪一部分正在输出空格以及如何处理它。您提到它是表单的一部分,因此也许您可以考虑让表单将货币和值作为单独的字段返回,这样您就不必担心解析数字。如果用户自己输入字符串“88,22 \xe2\x82\xac”,则可能会遇到更多问题,而不仅仅是空格问题。话虽如此,如果您想使用 ,您提到的解决方法(替换为\\x20\\xc2\\xa0是解决该问题的唯一方法NumberFormatter

\n