2017-04-02 3 views
0

Nach vieler Forschung Ich bin eigentlich die folgende Funktion Format Nummern auf den vom Benutzer gefassten locale mit:PHP Formatierung Zahlen locale und zurück

function number_format_i18n($number, $decimals=0) { 
    $locale = localeconv(); 
    return number_format($number,$decimals, $locale['decimal_point'], $locale['thousands_sep']); 
} 

ich diese Zahlen Format von DB verwenden werde .

Aber wenn ich ein Formular habe, wo ein Benutzer eine Nummer eingeben kann, brauche ich eine Funktion, um es zurück zu formatieren, damit ich in der DB speichern kann. Hier fand ich diese Lösung:

function number_format_en($number) { 
    // $_SESSION['lang']['locale'] has the locale like de_DE, ar_AE, tr_TR, ... 
    $fmt = numfmt_create($_SESSION['lang']['locale'], NumberFormatter::DECIMAL); 
    return numfmt_parse($fmt, $number); 
} 

Dies funktioniert mit den meisten Locales, die ich getestet habe, aber nicht mit jedem! Als Beispiel: Wenn ich arabicum verwenden (ar_AE):

$randomNumber = 3171003633.95; 
$number2locale = number_format_i18n($randomNumber, 2); 
// works as expected: 3,171,003,633.95 
// now format it back: 
$locale2number = number_format_en($number2locale); 
// here I get this: 3.171 

Wie kann ich eine locale formatieren Nummer in einer sicheren Art und Weise eingegeben "zurück" zu en-Format? Oder gibt es eine Möglichkeit, irgendeine Art von Zahlenformat zu erkennen und es zu en-formatieren, damit ich es in der Datenbank speichern kann?

Antwort

0

Also, nicht wirklich wissen, ob dies eine gute Lösung ist oder nicht - aber es scheint gut zu funktionieren:

function number_format_en($number) { 
    // first remove everything execpt -,. 
    $cleanNumber = preg_replace('/[^\\d-,.]+/', '', $number); 

    $last_dot = strrpos($cleanNumber, '.'); 
    $last_comma = strrpos($cleanNumber, ','); 

    if($last_dot !== false || $last_comma !== false) { 
     if($last_dot > $last_comma) { // decimal seperator = dot 
      $decimal_point = '.'; 
      if(substr_count($cleanNumber, '.') > 1) { 
       // could be totaly wrong 1,234.567.890 
       // or there are no decimals 1.234.567.890 
       // removing all dots and commas and returning the value 
       return preg_replace('/[^\\d-]+/', '', $cleanNumber); 
      } 
     } else { // decimal seperator = comma 
      $decimal_point = ','; 
      if(substr_count($cleanNumber, ',') > 1) { 
       // could be totaly wrong 1.234,567,890 
       // or there are no decimals 1,234,567,890 
       // removing all dots and commas and returning the value 
       return preg_replace('/[^\\d-]+/', '', $cleanNumber); 
      } 
     } 
    } else { // no decimals 
     $decimal_point = false; 
     $decimals = 0; 
    } 

    if($decimal_point !== false) { 
     // if decimals are delivered, get the count of them 
     $length = strlen($cleanNumber); 
     $position = strpos($cleanNumber, $decimal_point); 
     $decimals = $length - $position - 1; 

     if($decimal_point == '.') { 
      // remove all commas if seperator = . 
      $cleanNumber = str_replace(',', '', $cleanNumber); 
     } elseif($decimal_point == ',') { 
      // remove all dots if seperator = , 
      $cleanNumber = str_replace('.', '', $cleanNumber); 
      // now switch comma with dot 
      $cleanNumber = str_replace(',', '.', $cleanNumber); 
     } 
    } 
    return $cleanNumber; 
} 

Ich werde den letzten Punkt oder Komma prüfen und in Abhängigkeit von diesem I-Format Die Funktion number gibt die gleiche Anzahl an Dezimalzahlen zurück wie die ursprüngliche Zahl. gibt es einen „bekannten“ Fehler: wenn jemand eine volle Zahl wie 1.000.000 oder 1.000.000 geht es zurück 1000000

Als Beispiel:

number_format_en('1.234.567,89') // 1234567.89 
number_format_en('-1,234,567.89') // -1234567.89 
number_format_en('1.234.567.89') // 123456789 (only dots) 
number_format_en('1,234,567,89') // 123456789 (only commas) 

Wäre schön, wenn jemand einen Kommentar, wenn diese Beiträge schreiben kann ist ein guter Weg oder nicht oder eine Antwort mit einer besseren Lösung :)