2013-05-08 39 views
9

我想解析本地貨幣字符串貨幣和浮動值。如何更改NumberFormatter :: parseCurrency()接受空白和非破壞空間的行爲?

一切運作良好一段時間,現在我們遇到一些問題。看來的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 
)); 

輸出:

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... 
} 

正如你所看到的,有在輸出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 

hexdump都非工作值:

00000000 38 38 2c 32 32 20 e2 82 ac 0a     |88,22 ....| 
0000000a 

EDIT2:

這似乎是使用白色皮膚的問題。 c2 a0是NO-BREAK SPACE和NumberFormatter :: parseCurrency()所需的(可能?)。但0x20是默認空間(在輸入表單中輸入)。 當前的解決辦法與$value = str_replace("\x20", "\xC2\xA0", $value);

EDIT3替換爲NO-BREAK SPACE的空白:

在另一個系統(與Zend服務器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 €" 
} 

Edit4:

與S工作之間的主要區別節奏和非休息空間配置工作是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 

不工作的版本:

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 
+1

只是一個想法:格式化程序UTF-8編碼(0x20AC)和鍵盤Latin-1(0x80)中的€符號?據我所知strlen()函數不知道Unicode字符。如果它由var_dump()內部使用,那將解釋附加字符。 – CodeZombie 2013-05-08 10:54:13

+0

我的終端應用程序(iTerm2)使用Unicode(UTF-8)作爲終端仿真。此外,這種錯誤/行爲發生在瀏覽器通過html表單文本輸入字段的輸入數據中。爲了澄清,我添加了hexdump輸出。 – nofreeusername 2013-05-08 11:05:45

+0

是保存爲UTF-8的文件嗎? – 2013-05-09 16:23:22

回答

3

NumberFormatter::parseCurrency是圍繞ICU庫函數unum_parseDoubleCurrency瘦包裝( see source)。

ICU庫的功能是限制性的,因爲它只會解析由雙功能unum_formatDoubleCurrency產生的字符串。該格式由Unicode區域設置數據驅動,該數據指定貨幣值與數值之間的非間隔空格。很明顯,早期版本的庫接受了其他空白字符。

總之,您不能讓NumberFormatter::parseCurrency接受空格。然而,Zend_Currency也應該輸出不間斷空格默認:

$currency = new Zend_Currency(array(
    'currency' => 'EUR', 
    'value' => 88.22, 
), 'de_DE'); 

var_dump(
    strval($currency),    // 88,22 € 
    strpos($currency, "\x20"),  // false 
    strpos($currency, "\xc2\xa0") // 5 
); 

的問題是,您的應用程序的一部分,輸出空間,如何解決這個問題。你提到它是你的表單的一部分,所以也許你可以看看讓表單返回貨幣和價值作爲單獨的領域,所以你不必擔心解析數字。如果用戶自己輸入字符串「88,22€」,則可能會遇到更多問題,而不僅僅是空白問題。話雖如此,你提到的解決方法(用\xc2\xa0代替\x20)是解決這個問題的唯一方法,如果你想使用NumberFormatter

+0

thx的解釋! Zend_Currency返回正確的值。但是我的表單允許直接用戶輸入帶浮點的貨幣符號的本地格式。 Zend Framework的完整解決方案是添加到元素的自定義過濾器,因爲這對NumberFormatter或pecl-intl來說不是真正的問題。 – nofreeusername 2013-05-13 18:58:10