]> Raphaël G. Git Repositories - packbundle/blob - Util/IntlUtil.php
Version 0.5.3
[packbundle] / Util / IntlUtil.php
1 <?php declare(strict_types=1);
2
3 /*
4 * This file is part of the Rapsys PackBundle package.
5 *
6 * (c) Raphaël Gertz <symfony@rapsys.eu>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Rapsys\PackBundle\Util;
13
14 use Twig\Error\SyntaxError;
15 use Twig\Environment;
16
17 /**
18 * Manages intl conversions
19 */
20 class IntlUtil {
21 /**
22 * Format currency
23 */
24 public function currency(int|float $number, string $currency, ?string $locale = null) {
25 //Get formatter
26 $formatter = $this->getNumberFormatter($locale, 'currency');
27
28 //Return formatted currency
29 return $formatter->formatCurrency($number, $currency);
30 }
31
32 /**
33 * Format date
34 */
35 public function date(Environment $env, \DateTime $date, string $dateFormat = 'medium', string $timeFormat = 'medium', ?string $locale = null, \IntlTimeZone|\DateTimeZone|string|null $timezone = null, ?string $calendar = null, ?string $pattern = null) {
36 //Get converted date
37 $date = twig_date_converter($env, $date, $timezone);
38
39 //Set date and time formatters
40 $formatters = [
41 'none' => \IntlDateFormatter::NONE,
42 'short' => \IntlDateFormatter::SHORT,
43 'medium' => \IntlDateFormatter::MEDIUM,
44 'long' => \IntlDateFormatter::LONG,
45 'full' => \IntlDateFormatter::FULL,
46 ];
47
48 //Get formatter
49 $formatter = \IntlDateFormatter::create(
50 $locale,
51 $formatters[$dateFormat],
52 $formatters[$timeFormat],
53 \IntlTimeZone::createTimeZone($date->getTimezone()->getName()),
54 'traditional' === $calendar ? \IntlDateFormatter::TRADITIONAL : \IntlDateFormatter::GREGORIAN,
55 $pattern
56 );
57
58 //Return formatted date
59 return $formatter->format($date->getTimestamp());
60 }
61
62 /**
63 * Compute eastern for selected year
64 *
65 * @param string $year The eastern year
66 *
67 * @return DateTime The eastern date
68 */
69 public function getEastern(string $year): \DateTime {
70 //Set static results
71 static $results = [];
72
73 //Check if already computed
74 if (isset($results[$year])) {
75 //Return computed eastern
76 return $results[$year];
77 }
78
79 $d = (19 * ($year % 19) + 24) % 30;
80
81 $e = (2 * ($year % 4) + 4 * ($year % 7) + 6 * $d + 5) % 7;
82
83 $day = 22 + $d + $e;
84
85 $month = 3;
86
87 if ($day > 31) {
88 $day = $d + $e - 9;
89 $month = 4;
90 } elseif ($d == 29 && $e == 6) {
91 $day = 10;
92 $month = 4;
93 } elseif ($d == 28 && $e == 6) {
94 $day = 18;
95 $month = 4;
96 }
97
98 //Store eastern in data
99 return ($results[$year] = new \DateTime(sprintf('%04d-%02d-%02d', $year, $month, $day)));
100 }
101
102 /**
103 * Gets number formatter instance matching locale and style.
104 *
105 * @param ?string $locale Locale in which the number would be formatted
106 * @param string $style Style of the formatting
107 *
108 * @return NumberFormatter A NumberFormatter instance
109 */
110 protected function getNumberFormatter(?string $locale, string $style): \NumberFormatter {
111 //Set static formatters
112 static $formatters = [];
113
114 //Set locale
115 $locale = null !== $locale ? $locale : \Locale::getDefault();
116
117 //With existing formatter
118 if (isset($formatters[$locale][$style])) {
119 //Return the instance from previous call
120 return $formatters[$locale][$style];
121 }
122
123 //Set styles
124 static $styles = [
125 'decimal' => \NumberFormatter::DECIMAL,
126 'currency' => \NumberFormatter::CURRENCY,
127 'percent' => \NumberFormatter::PERCENT,
128 'scientific' => \NumberFormatter::SCIENTIFIC,
129 'spellout' => \NumberFormatter::SPELLOUT,
130 'ordinal' => \NumberFormatter::ORDINAL,
131 'duration' => \NumberFormatter::DURATION
132 ];
133
134 //Without styles
135 if (!isset($styles[$style])) {
136 throw new SyntaxError(sprintf('The style "%s" does not exist. Known styles are: "%s"', $style, implode('", "', array_keys($styleValues))));
137 }
138
139 //Return number formatter
140 return ($formatters[$locale][$style] = \NumberFormatter::create($locale, $styles[$style]));
141 }
142
143 /**
144 * Format number
145 */
146 public function number(int|float $number, $style = 'decimal', $type = 'default', ?string $locale = null) {
147 //Set types
148 static $types = [
149 'default' => \NumberFormatter::TYPE_DEFAULT,
150 'int32' => \NumberFormatter::TYPE_INT32,
151 'int64' => \NumberFormatter::TYPE_INT64,
152 'double' => \NumberFormatter::TYPE_DOUBLE,
153 'currency' => \NumberFormatter::TYPE_CURRENCY
154 ];
155
156 //Get formatter
157 $formatter = $this->getNumberFormatter($locale, $style);
158
159 //Without type
160 if (!isset($types[$type])) {
161 throw new SyntaxError(sprintf('The type "%s" does not exist. Known types are: "%s"', $type, implode('", "', array_keys($types))));
162 }
163
164 //Return formatted number
165 return $formatter->format($number, $types[$type]);
166 }
167
168 /**
169 * Format size
170 */
171 public function size(int|float $number, $si = true, $style = 'decimal', $type = 'default', ?string $locale = null) {
172 //Set types
173 static $types = [
174 'default' => \NumberFormatter::TYPE_DEFAULT,
175 'int32' => \NumberFormatter::TYPE_INT32,
176 'int64' => \NumberFormatter::TYPE_INT64,
177 'double' => \NumberFormatter::TYPE_DOUBLE,
178 'currency' => \NumberFormatter::TYPE_CURRENCY
179 ];
180
181 //Get formatter
182 $formatter = $this->getNumberFormatter($locale, $style);
183
184 //Without type
185 if (!isset($types[$type])) {
186 throw new SyntaxError(sprintf('The type "%s" does not exist. Known types are: "%s"', $type, implode('", "', array_keys($types))));
187 }
188
189 //Set unit
190 $unit = $si ? 1000 : 1024;
191
192 //Set index
193 $index = [ '', $si ? 'k' : 'K', 'M', 'G', 'T', 'P', 'E' ];
194
195 //Get exp
196 $exp = intval((log($number) / log($unit)));
197
198 //Rebase number
199 $number = round($number / pow($unit, $exp), 2);
200
201 //Return formatted number
202 return $formatter->format($number, $types[$type]).' '.$index[$exp].($si ? '' : 'i').'B';
203 }
204 }