| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- <?php
- namespace app\components;
- use yii\base\Component;
- class NumberToText extends Component
- {
- private array $units = [
- ['нуль'],
- ['один', 'одна'],
- ['два', 'дві'],
- ['три'],
- ['чотири'],
- ['п’ять'],
- ['шість'],
- ['сім'],
- ['вісім'],
- ['дев’ять'],
- ];
- private array $teens = [
- 'десять','одинадцять','дванадцять','тринадцять',
- 'чотирнадцять','п’ятнадцять','шістнадцять',
- 'сімнадцять','вісімнадцять','дев’ятнадцять'
- ];
- private array $tens = [
- '', '', 'двадцять','тридцять','сорок',
- 'п’ятдесят','шістдесят','сімдесят',
- 'вісімдесят','дев’яносто'
- ];
- private array $hundreds = [
- 'сто','двісті','триста','чотириста',
- 'п’ятсот','шістсот','сімсот',
- 'вісімсот','дев’ятсот'
- ];
- private array $orders = [
- [ ['тисяча','тисячі','тисяч'], 'f'],
- [ ['мільйон','мільйони','мільйонів'], 'm'],
- [ ['мільярд','мільярди','мільярдів'], 'm'],
- ];
- public function money(float $amount): string
- {
- $amount = round($amount, 2);
- $hryvnias = floor($amount);
- $kopecks = (int)round(($amount - $hryvnias) * 100);
- $result = $this->convert($hryvnias, ['гривня','гривні','гривень'], 'f');
- $result .= ' ';
- $result .= $this->convert($kopecks, ['копійка','копійки','копійок'], 'f');
- return $result;
- }
- private function convert(int $number, array $forms, string $gender): string
- {
- if ($number === 0) {
- return 'нуль ' . $forms[2];
- }
- $result = [];
- $order = 0;
- while ($number > 0) {
- $chunk = $number % 1000;
- if ($chunk > 0) {
- $chunkGender = $order === 0 ? $gender : $this->orders[$order-1][1];
- $words = $this->convertChunk($chunk, $chunkGender);
- $plural = $this->pluralForm($chunk);
- if ($order === 0) {
- $words[] = $forms[$plural];
- } else {
- $words[] = $this->orders[$order-1][0][$plural];
- }
- $result = array_merge($words, $result);
- }
- $number = intdiv($number, 1000);
- $order++;
- }
- return implode(' ', $result);
- }
- private function convertChunk(int $number, string $gender): array
- {
- $words = [];
- if ($number >= 100) {
- $words[] = $this->hundreds[intdiv($number,100)-1];
- $number %= 100;
- }
- if ($number >= 10 && $number <= 19) {
- $words[] = $this->teens[$number-10];
- return $words;
- }
- if ($number >= 20) {
- $words[] = $this->tens[intdiv($number,10)];
- $number %= 10;
- }
- if ($number > 0) {
- if ($number == 1 || $number == 2) {
- $words[] = $this->units[$number][$gender === 'f' ? 1 : 0];
- } else {
- $words[] = $this->units[$number][0];
- }
- }
- return $words;
- }
- private function pluralForm(int $number): int
- {
- $number %= 100;
- if ($number >= 11 && $number <= 19) return 2;
- $number %= 10;
- if ($number == 1) return 0;
- if ($number >= 2 && $number <= 4) return 1;
- return 2;
- }
- public function moneyFormatted(float $amount): string
- {
- $amount = round($amount, 2);
- $hryvnias = floor($amount);
- $kopecks = (int)round(($amount - $hryvnias) * 100);
- $numberFormatted = number_format($amount, 2, ',', ' ');
- $textHryvnias = $this->convert(
- $hryvnias,
- ['','',''],
- 'f'
- );
- $plural = $this->pluralForm($hryvnias);
- $forms = ['гривня','гривні','гривень'];
- return sprintf(
- "%s (%s) %s %02d копійок",
- $numberFormatted,
- $textHryvnias,
- $forms[$plural],
- $kopecks
- );
- }
- }
|