ci4

Форк
0
/
number_helper.php 
220 строк · 7.4 Кб
1
<?php
2

3
declare(strict_types=1);
4

5
/**
6
 * This file is part of CodeIgniter 4 framework.
7
 *
8
 * (c) CodeIgniter Foundation <admin@codeigniter.com>
9
 *
10
 * For the full copyright and license information, please view
11
 * the LICENSE file that was distributed with this source code.
12
 */
13

14
// CodeIgniter Number Helpers
15

16
if (! function_exists('number_to_size')) {
17
    /**
18
     * Formats a numbers as bytes, based on size, and adds the appropriate suffix
19
     *
20
     * @param int|string            $num    Will be cast as int
21
     * @param non-empty-string|null $locale [optional]
22
     *
23
     * @return bool|string
24
     */
25
    function number_to_size($num, int $precision = 1, ?string $locale = null)
26
    {
27
        // Strip any formatting & ensure numeric input
28
        try {
29
            // @phpstan-ignore-next-line
30
            $num = 0 + str_replace(',', '', (string) $num);
31
        } catch (ErrorException) {
32
            // Catch "Warning:  A non-numeric value encountered"
33
            return false;
34
        }
35

36
        // ignore sub part
37
        $generalLocale = $locale;
38
        if ($locale !== null && $locale !== '' && ($underscorePos = strpos($locale, '_'))) {
39
            $generalLocale = substr($locale, 0, $underscorePos);
40
        }
41

42
        if ($num >= 1_000_000_000_000) {
43
            $num  = round($num / 1_099_511_627_776, $precision);
44
            $unit = lang('Number.terabyteAbbr', [], $generalLocale);
45
        } elseif ($num >= 1_000_000_000) {
46
            $num  = round($num / 1_073_741_824, $precision);
47
            $unit = lang('Number.gigabyteAbbr', [], $generalLocale);
48
        } elseif ($num >= 1_000_000) {
49
            $num  = round($num / 1_048_576, $precision);
50
            $unit = lang('Number.megabyteAbbr', [], $generalLocale);
51
        } elseif ($num >= 1000) {
52
            $num  = round($num / 1024, $precision);
53
            $unit = lang('Number.kilobyteAbbr', [], $generalLocale);
54
        } else {
55
            $unit = lang('Number.bytes', [], $generalLocale);
56
        }
57

58
        return format_number($num, $precision, $locale, ['after' => ' ' . $unit]);
59
    }
60
}
61

62
if (! function_exists('number_to_amount')) {
63
    /**
64
     * Converts numbers to a more readable representation
65
     * when dealing with very large numbers (in the thousands or above),
66
     * up to the quadrillions, because you won't often deal with numbers
67
     * larger than that.
68
     *
69
     * It uses the "short form" numbering system as this is most commonly
70
     * used within most English-speaking countries today.
71
     *
72
     * @see https://simple.wikipedia.org/wiki/Names_for_large_numbers
73
     *
74
     * @param int|string            $num       Will be cast as int
75
     * @param int                   $precision [optional] The optional number of decimal digits to round to.
76
     * @param non-empty-string|null $locale    [optional]
77
     *
78
     * @return bool|string
79
     */
80
    function number_to_amount($num, int $precision = 0, ?string $locale = null)
81
    {
82
        // Strip any formatting & ensure numeric input
83
        try {
84
            // @phpstan-ignore-next-line
85
            $num = 0 + str_replace(',', '', (string) $num);
86
        } catch (ErrorException) {
87
            // Catch "Warning:  A non-numeric value encountered"
88
            return false;
89
        }
90

91
        $suffix = '';
92

93
        // ignore sub part
94
        $generalLocale = $locale;
95
        if ($locale !== null && $locale !== '' && ($underscorePos = strpos($locale, '_'))) {
96
            $generalLocale = substr($locale, 0, $underscorePos);
97
        }
98

99
        if ($num >= 1_000_000_000_000_000) {
100
            $suffix = lang('Number.quadrillion', [], $generalLocale);
101
            $num    = round(($num / 1_000_000_000_000_000), $precision);
102
        } elseif ($num >= 1_000_000_000_000) {
103
            $suffix = lang('Number.trillion', [], $generalLocale);
104
            $num    = round(($num / 1_000_000_000_000), $precision);
105
        } elseif ($num >= 1_000_000_000) {
106
            $suffix = lang('Number.billion', [], $generalLocale);
107
            $num    = round(($num / 1_000_000_000), $precision);
108
        } elseif ($num >= 1_000_000) {
109
            $suffix = lang('Number.million', [], $generalLocale);
110
            $num    = round(($num / 1_000_000), $precision);
111
        } elseif ($num >= 1000) {
112
            $suffix = lang('Number.thousand', [], $generalLocale);
113
            $num    = round(($num / 1000), $precision);
114
        }
115

116
        return format_number($num, $precision, $locale, ['after' => $suffix]);
117
    }
118
}
119

120
if (! function_exists('number_to_currency')) {
121
    function number_to_currency(float $num, string $currency, ?string $locale = null, int $fraction = 0): string
122
    {
123
        return format_number($num, 1, $locale, [
124
            'type'     => NumberFormatter::CURRENCY,
125
            'currency' => $currency,
126
            'fraction' => $fraction,
127
        ]);
128
    }
129
}
130

131
if (! function_exists('format_number')) {
132
    /**
133
     * A general purpose, locale-aware, number_format method.
134
     * Used by all of the functions of the number_helper.
135
     */
136
    function format_number(float $num, int $precision = 1, ?string $locale = null, array $options = []): string
137
    {
138
        // If locale is not passed, get from the default locale that is set from our config file
139
        // or set by HTTP content negotiation.
140
        $locale ??= Locale::getDefault();
141

142
        // Type can be any of the NumberFormatter options, but provide a default.
143
        $type = (int) ($options['type'] ?? NumberFormatter::DECIMAL);
144

145
        $formatter = new NumberFormatter($locale, $type);
146

147
        // Try to format it per the locale
148
        if ($type === NumberFormatter::CURRENCY) {
149
            $formatter->setAttribute(NumberFormatter::FRACTION_DIGITS, (float) $options['fraction']);
150
            $output = $formatter->formatCurrency($num, $options['currency']);
151
        } else {
152
            // In order to specify a precision, we'll have to modify
153
            // the pattern used by NumberFormatter.
154
            $pattern = '#,##0.' . str_repeat('#', $precision);
155

156
            $formatter->setPattern($pattern);
157
            $output = $formatter->format($num);
158
        }
159

160
        // This might lead a trailing period if $precision == 0
161
        $output = trim($output, '. ');
162

163
        if (intl_is_failure($formatter->getErrorCode())) {
164
            throw new BadFunctionCallException($formatter->getErrorMessage());
165
        }
166

167
        // Add on any before/after text.
168
        if (isset($options['before']) && is_string($options['before'])) {
169
            $output = $options['before'] . $output;
170
        }
171

172
        if (isset($options['after']) && is_string($options['after'])) {
173
            $output .= $options['after'];
174
        }
175

176
        return $output;
177
    }
178
}
179

180
if (! function_exists('number_to_roman')) {
181
    /**
182
     * Convert a number to a roman numeral.
183
     *
184
     * @param int|string $num it will convert to int
185
     */
186
    function number_to_roman($num): ?string
187
    {
188
        static $map = [
189
            'M'  => 1000,
190
            'CM' => 900,
191
            'D'  => 500,
192
            'CD' => 400,
193
            'C'  => 100,
194
            'XC' => 90,
195
            'L'  => 50,
196
            'XL' => 40,
197
            'X'  => 10,
198
            'IX' => 9,
199
            'V'  => 5,
200
            'IV' => 4,
201
            'I'  => 1,
202
        ];
203

204
        $num = (int) $num;
205

206
        if ($num < 1 || $num > 3999) {
207
            return null;
208
        }
209

210
        $result = '';
211

212
        foreach ($map as $roman => $arabic) {
213
            $repeat = (int) floor($num / $arabic);
214
            $result .= str_repeat($roman, $repeat);
215
            $num %= $arabic;
216
        }
217

218
        return $result;
219
    }
220
}
221

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.