diff --git a/.github/workflows/php-cs-fixer.yml b/.github/workflows/php-cs-fixer.yml index f6413bb..39cb7f6 100644 --- a/.github/workflows/php-cs-fixer.yml +++ b/.github/workflows/php-cs-fixer.yml @@ -24,5 +24,5 @@ jobs: - name: PHP-CS-Fixer Check run: | - php-cs-fixer fix -v --dry-run ./src --rules=@PSR12 - php-cs-fixer fix -v --dry-run ./.tests --rules=@PSR12 + php-cs-fixer fix -v --dry-run ./src --rules=@PSR12,-blank_line_after_opening_tag + php-cs-fixer fix -v --dry-run ./.tests --rules=@PSR12,-blank_line_after_opening_tag diff --git a/.tests/NumberFormatterTest.php b/.tests/NumberFormatterTest.php index f43663f..db1170f 100644 --- a/.tests/NumberFormatterTest.php +++ b/.tests/NumberFormatterTest.php @@ -227,3 +227,48 @@ echo 'Test failed: ' . $Case . ':L' . __LINE__ . '().' . PHP_EOL; exit($ExitCode); } + +$Formats = [ + 'Arabic-1', + 'Arabic-2', + 'Arabic-3', + 'Arabic-4', + 'Bengali-1', + 'Burmese-1', + 'Fullwidth', + 'Geez', + 'India-1', + 'India-2', + 'India-3', + 'India-4', + 'India-5', + 'India-6', + 'Javanese', + 'Kaktovik', + 'Khmer-1', + 'Lao-1', + 'Latin-1', + 'Latin-2', + 'Latin-3', + 'Latin-4', + 'Latin-5', + 'Mayan', + 'Mongolian', + 'Odia', + 'Thai-1', + 'Thai-2', + 'Tibetan' +]; + +$ExitCode++; +foreach ($Formats as $Format) { + $Obj = new \Maikuolan\Common\NumberFormatter($Format); + foreach (['123456789', '987654321', '102030405060708090', '100', '1000', '10000'] as $Number) { + $Try = $Obj->format($Number); + $Compare = $Obj->unformat($Try); + if ($Compare !== $Number) { + echo 'Test failed: ' . $Case . ':L' . __LINE__ . '(). ' . $Compare . ' !== ' . $Number . ' (' . $Format . ')!' . PHP_EOL; + exit($ExitCode); + } + } +} diff --git a/.tests/OperationTest.php b/.tests/OperationTest.php index 192c53e..f1fc58e 100644 --- a/.tests/OperationTest.php +++ b/.tests/OperationTest.php @@ -280,8 +280,6 @@ } } -echo $Out; - $ExitCode++; if ($Out !== $Expected) { echo 'Test failed: ' . $Case . ':L' . __LINE__ . '().' . PHP_EOL; diff --git a/Changelog.txt b/Changelog.txt index 688a71f..bbb30f9 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -11,7 +11,8 @@ found at: === Changes made since last versioned release === -(none) +- [2025.05.02; Maikuolan]: Added some limited support to the number formatter + class for unformatting a formatted number. === Version/Release 2.12.3 === PATCH RELEASE. diff --git a/_docs/NumberFormatter.md b/_docs/NumberFormatter.md index 5639223..f2fa99b 100644 --- a/_docs/NumberFormatter.md +++ b/_docs/NumberFormatter.md @@ -10,6 +10,7 @@ - [NumberFormatter constructor.](#numberformatter-constructor) - [format method.](#format-method) - [getSetJSON method.](#getsetjson-method) +- [unformat method.](#unformat-method) - [ConversionSet member.](#conversionset-member) - [GroupSeparator member.](#groupseparator-member) - [GroupSize member.](#groupsize-member) @@ -226,6 +227,52 @@ Output: ["\u06f0","\u06f1","\u06f2","\u06f3","\u06f4","\u06f5","\u06f6","\u06f7","\u06f8","\u06f9"] ``` + +#### unformat method. + +Unformats the formatted number according to predefined patterns and lookup tables. + +*Warning: Doesn't work for ALL formats (..yet), won't work for fractions (only intended for whole numbers), and other data (e.g., decimal separators, thousands separators) will be disregarded entirely.* + +```PHP +$Obj = new \Maikuolan\Common\NumberFormatter('Arabic-2'); +$Try = $Obj->format('12345678987654321'); +echo $Try . PHP_EOL; +$Try = $Obj->unformat($Try); +echo $Try . PHP_EOL; + +$Obj = new \Maikuolan\Common\NumberFormatter('India-2'); +$Try = $Obj->format('12345678987654321'); +echo $Try . PHP_EOL; +$Try = $Obj->unformat($Try); +echo $Try . PHP_EOL; + +$Obj = new \Maikuolan\Common\NumberFormatter('Geez'); +$Try = $Obj->format('12345678987654321'); +echo $Try . PHP_EOL; +$Try = $Obj->unformat($Try); +echo $Try . PHP_EOL; + +$Obj = new \Maikuolan\Common\NumberFormatter('Kaktovik'); +$Try = $Obj->format('12345678987654321'); +echo $Try . PHP_EOL; +$Try = $Obj->unformat($Try); +echo $Try . PHP_EOL; +``` + +Output: + +``` +١٢٬٣٤٥٬٦٧٨٬٩٨٧٬٦٥٤٬٣٢١ +12345678987654321 +१२,३४,५६,७८,९८,७६,५४,३२१ +12345678987654321 +፼፳፫፻፵፭፼፷፯፻፹፱፼፹፯፻፷፭፼፵፫፻፳፩ +12345678987654321 +������������� +12345678987654321 +``` + #### ConversionSet member. ```PHP @@ -547,4 +594,4 @@ Base 36: a.i000 ~ 74.9000 --- -Last Updated: 26 June 2024 (2024.06.26). +Last Updated: 5 February 2025 (2025.02.05). diff --git a/src/NumberFormatter.php b/src/NumberFormatter.php index 94b7690..f9cc35a 100644 --- a/src/NumberFormatter.php +++ b/src/NumberFormatter.php @@ -1,6 +1,6 @@ '35' ]; + /** + * @var array Lookup table for unformatting a number. + */ + private $UnformatTable = [ + '0' => ['٠', '۰', '০', '०', '૦', '੦', '೦', '౦', '၀', '០', '๐', '໐', '꧐', '୦', '༠', '᠐', '0', '᱐', '〇', '零', 'Z', '௰'], + '1' => ['١', '۱', '১', '१', '૧', '੧', '೧', '౧', '၁', '១', '๑', '໑', '꧑', '୧', '༡', '᠑', '1', '᱑', '一', '壹', '፩', '፲', '௧'], + '2' => ['٢', '۲', '২', '२', '૨', '੨', '೨', '౨', '၂', '២', '๒', '໒', '꧒', '୨', '༢', '᠒', '2', '᱒', '二', '贰', '貳', '፪', '፳', '௨'], + '3' => ['٣', '۳', '৩', '३', '૩', '੩', '೩', '౩', '၃', '៣', '๓', '໓', '꧓', '୩', '༣', '᠓', '3', '᱓', '三', '叁', '叄', '፫', '፴', '௩'], + '4' => ['٤', '۴', '৪', '४', '૪', '੪', '೪', '౪', '၄', '៤', '๔', '໔', '꧔', '୪', '༤', '᠔', '4', '᱔', '四', '肆', '፬', '፵', '௪'], + '5' => ['٥', '۵', '৫', '५', '૫', '੫', '೫', '౫', '၅', '៥', '๕', '໕', '꧕', '୫', '༥', '᠕', '5', '᱕', '五', '伍', '፭', '፶', '௫'], + '6' => ['٦', '۶', '৬', '६', '૬', '੬', '೬', '౬', '၆', '៦', '๖', '໖', '꧖', '୬', '༦', '᠖', '6', '᱖', '六', '陆', '陸', '፮', '፷', '௬'], + '7' => ['٧', '۷', '৭', '७', '૭', '੭', '೭', '౭', '၇', '៧', '๗', '໗', '꧗', '୭', '༧', '᠗', '7', '᱗', '七', '柒', '፯', '፸', '௭'], + '8' => ['٨', '۸', '৮', '८', '૮', '੮', '೮', '౮', '၈', '៨', '๘', '໘', '꧘', '୮', '༨', '᠘', '8', '᱘', '八', '捌', '፰', '፹', '௮'], + '9' => ['٩', '۹', '৯', '९', '૯', '੯', '೯', '౯', '၉', '៩', '๙', '໙', '꧙', '୯', '༩', '᠙', '9', '᱙', '九', '玖', '፱', '፺', '௯'] + ]; + + /** + * @var array Patterns for unformatting a number. + */ + private $UnformatPattern = [ + '~(? '1\1', + '~^(፻|፼|十|百|千|拾|万|億|兆|京|垓|௰|௱|௲)~' => '1\1', + '~(፻|፼)(?!፲|፳|፴|፵|፶|፷|፸|፹|፺|\d)~' => '\1Z', + '~(፻[\dZ]|፼[\dZ])(?!፩|፪|፫|፬|፭|፮|፯|፰|፱|\d)~' => '\1Z', + '~(፲|፳|፴|፵|፶|፷|፸|፹|፺)(?!፩|፪|፫|፬|፭|፮|፯|፰|፱)~' => '\1Z', + '~(十|拾)$~' => '0', + '~(፻|百)$~' => '00', + '~千$~' => '000', + '~፼$~' => '0000' + ]; + + /** + * @var array Lookup table for unformatting a base-20 number. + */ + private $UnformatTableKakMay = [ + '0' => ['𝋀', '𝋠'], + '1' => ['𝋁', '𝋡'], + '2' => ['𝋂', '𝋢'], + '3' => ['𝋃', '𝋣'], + '4' => ['𝋄', '𝋤'], + '5' => ['𝋅', '𝋥'], + '6' => ['𝋆', '𝋦'], + '7' => ['𝋇', '𝋧'], + '8' => ['𝋈', '𝋨'], + '9' => ['𝋉', '𝋩'], + 'a' => ['𝋊', '𝋪'], + 'b' => ['𝋋', '𝋫'], + 'c' => ['𝋌', '𝋬'], + 'd' => ['𝋍', '𝋭'], + 'e' => ['𝋎', '𝋮'], + 'f' => ['𝋏', '𝋯'], + 'g' => ['𝋐', '𝋰'], + 'h' => ['𝋑', '𝋱'], + 'i' => ['𝋒', '𝋲'], + 'j' => ['𝋓', '𝋳'], + ]; + /** * Constructor. * @@ -1384,6 +1441,38 @@ public function getSetJSON(string $Set = ''): string return isset($this->{$Set}) ? json_encode($this->{$Set}) : '[]'; } + /** + * Unformats the formatted number according to predefined patterns and lookup + * tables. Warning: Doesn't work for all formats (..yet), won't work for + * fractions (only intended for whole numbers), and other data (e.g., decimal + * separators, thousands separators) will be disregarded entirely. + * + * @param string $Number The number to unformat. + * @return string The unformatted number (returned as string rather than as an + * integer or a float in order to retain decimal precision). + */ + public function unformat(string $Number): string + { + if (preg_match('~\D~', $Number)) { + foreach ($this->UnformatPattern as $Pattern => $Replacement) { + $Number = preg_replace($Pattern, $Replacement, $Number); + } + foreach ($this->UnformatTable as $Replacement => $Lookup) { + $Number = str_replace($Lookup, $Replacement, $Number); + } + $KakMay = $Number; + foreach ($this->UnformatTableKakMay as $Replacement => $Lookup) { + $KakMay = str_replace($Lookup, $Replacement, $KakMay); + } + if ($KakMay !== $Number) { + $Number = base_convert(preg_replace('~[^\da-j]~', '', $KakMay), 20, 10); + } else { + $Number = preg_replace('~\D~', '', $Number); + } + } + return preg_replace('~^0+~', '', $Number); + } + /** * Prepare to convert a fraction. *