X-Git-Url: https://git.rapsys.eu/packbundle/blobdiff_plain/f214dc95feac5ecffbc9846887ecb520dc2f669d..fedbe97d37d0056de407abcc44ee180f84e1ca7c:/Util/IntlUtil.php

diff --git a/Util/IntlUtil.php b/Util/IntlUtil.php
index a9096df..84d468f 100644
--- a/Util/IntlUtil.php
+++ b/Util/IntlUtil.php
@@ -15,101 +15,190 @@ use Twig\Error\SyntaxError;
 use Twig\Environment;
 
 /**
- * Helps manage intl conversions
- *
- * @TODO Makes this class strict !!!
+ * Manages intl conversions
  */
 class IntlUtil {
 	/**
-	 * Construct intl util
+	 * Format currency
 	 */
-	public function __construct() {
+	public function currency(int|float $number, string $currency, ?string $locale = null) {
+		//Get formatter
+		$formatter = $this->getNumberFormatter($locale, 'currency');
+
+		//Return formatted currency
+		return $formatter->formatCurrency($number, $currency);
 	}
 
-	public function date(Environment $env, $date, $dateFormat = 'medium', $timeFormat = 'medium', $locale = null, $timezone = null, $format = null, $calendar = 'gregorian') {
+	/**
+	 * Format date
+	 */
+	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) {
+		//Get converted date
 		$date = twig_date_converter($env, $date, $timezone);
 
-		$formatValues = array(
+		//Set date and time formatters
+		$formatters = [
 			'none' => \IntlDateFormatter::NONE,
 			'short' => \IntlDateFormatter::SHORT,
 			'medium' => \IntlDateFormatter::MEDIUM,
 			'long' => \IntlDateFormatter::LONG,
 			'full' => \IntlDateFormatter::FULL,
-		);
+		];
 
+		//Get formatter
 		$formatter = \IntlDateFormatter::create(
 			$locale,
-			$formatValues[$dateFormat],
-			$formatValues[$timeFormat],
+			$formatters[$dateFormat],
+			$formatters[$timeFormat],
 			\IntlTimeZone::createTimeZone($date->getTimezone()->getName()),
-			'gregorian' === $calendar ? \IntlDateFormatter::GREGORIAN : \IntlDateFormatter::TRADITIONAL,
-			$format
+			'traditional' === $calendar ? \IntlDateFormatter::TRADITIONAL : \IntlDateFormatter::GREGORIAN,
+			$pattern
 		);
 
+		//Return formatted date
 		return $formatter->format($date->getTimestamp());
 	}
 
-	public function number($number, $style = 'decimal', $type = 'default', $locale = null) {
-		static $typeValues = array(
-			'default' => NumberFormatter::TYPE_DEFAULT,
-			'int32' => NumberFormatter::TYPE_INT32,
-			'int64' => NumberFormatter::TYPE_INT64,
-			'double' => NumberFormatter::TYPE_DOUBLE,
-			'currency' => NumberFormatter::TYPE_CURRENCY,
-		);
+	/**
+	 * Compute eastern for selected year
+	 *
+	 * @param string $year The eastern year
+	 *
+	 * @return DateTime The eastern date
+	 */
+	public function getEastern(string $year): \DateTime {
+		//Set static results
+		static $results = [];
+
+		//Check if already computed
+		if (isset($results[$year])) {
+			//Return computed eastern
+			return $results[$year];
+		}
 
-		$formatter = $this->getNumberFormatter($locale, $style);
+		$d = (19 * ($year % 19) + 24) % 30;
 
-		if (!isset($typeValues[$type])) {
-			throw new SyntaxError(sprintf('The type "%s" does not exist. Known types are: "%s"', $type, implode('", "', array_keys($typeValues))));
-		}
+		$e = (2 * ($year % 4) + 4 * ($year % 7) + 6 * $d + 5) % 7;
 
-		return $formatter->format($number, $typeValues[$type]);
-	}
+		$day = 22 + $d + $e;
 
-	public function currency($number, $currency = null, $locale = null) {
-		$formatter = $this->getNumberFormatter($locale, 'currency');
+		$month = 3;
 
-		return $formatter->formatCurrency($number, $currency);
+		if ($day > 31) {
+			$day = $d + $e - 9;
+			$month = 4;
+		} elseif ($d == 29 && $e == 6) {
+			$day = 10;
+			$month = 4;
+		} elseif ($d == 28 && $e == 6) {
+			$day = 18;
+			$month = 4;
+		}
+
+		//Store eastern in data
+		return ($results[$year] = new \DateTime(sprintf('%04d-%02d-%02d', $year, $month, $day)));
 	}
 
 	/**
-	 * Gets a number formatter instance according to given locale and formatter.
+	 * Gets number formatter instance matching locale and style.
 	 *
-	 * @param string $locale Locale in which the number would be formatted
-	 * @param int    $style  Style of the formatting
+	 * @param ?string $locale Locale in which the number would be formatted
+	 * @param string $style Style of the formatting
 	 *
 	 * @return NumberFormatter A NumberFormatter instance
 	 */
-	protected function getNumberFormatter($locale, $style): \NumberFormatter {
-		static $formatter, $currentStyle;
+	protected function getNumberFormatter(?string $locale, string $style): \NumberFormatter {
+		//Set static formatters
+		static $formatters = [];
 
-		$locale = null !== $locale ? $locale : Locale::getDefault();
+		//Set locale
+		$locale = null !== $locale ? $locale : \Locale::getDefault();
 
-		if ($formatter && $formatter->getLocale() === $locale && $currentStyle === $style) {
-			// Return same instance of NumberFormatter if parameters are the same
-			// to those in previous call
-			return $formatter;
+		//With existing formatter
+		if (isset($formatters[$locale][$style])) {
+			//Return the instance from previous call
+			return $formatters[$locale][$style];
 		}
 
-		static $styleValues = array(
+		//Set styles
+		static $styles = [
 			'decimal' => \NumberFormatter::DECIMAL,
 			'currency' => \NumberFormatter::CURRENCY,
 			'percent' => \NumberFormatter::PERCENT,
 			'scientific' => \NumberFormatter::SCIENTIFIC,
 			'spellout' => \NumberFormatter::SPELLOUT,
 			'ordinal' => \NumberFormatter::ORDINAL,
-			'duration' => \NumberFormatter::DURATION,
-		);
+			'duration' => \NumberFormatter::DURATION
+		];
 
-		if (!isset($styleValues[$style])) {
+		//Without styles
+		if (!isset($styles[$style])) {
 			throw new SyntaxError(sprintf('The style "%s" does not exist. Known styles are: "%s"', $style, implode('", "', array_keys($styleValues))));
 		}
 
-		$currentStyle = $style;
+		//Return number formatter
+		return ($formatters[$locale][$style] = \NumberFormatter::create($locale, $styles[$style]));
+	}
+
+	/**
+	 * Format number
+	 */
+	public function number(int|float $number, $style = 'decimal', $type = 'default', ?string $locale = null) {
+		//Set types
+		static $types = [
+			'default' => \NumberFormatter::TYPE_DEFAULT,
+			'int32' => \NumberFormatter::TYPE_INT32,
+			'int64' => \NumberFormatter::TYPE_INT64,
+			'double' => \NumberFormatter::TYPE_DOUBLE,
+			'currency' => \NumberFormatter::TYPE_CURRENCY
+		];
+
+		//Get formatter
+		$formatter = $this->getNumberFormatter($locale, $style);
+
+		//Without type
+		if (!isset($types[$type])) {
+			throw new SyntaxError(sprintf('The type "%s" does not exist. Known types are: "%s"', $type, implode('", "', array_keys($types))));
+		}
+
+		//Return formatted number
+		return $formatter->format($number, $types[$type]);
+	}
+
+	/**
+	 * Format size
+	 */
+	public function size(int|float $number, $si = true, $style = 'decimal', $type = 'default', ?string $locale = null) {
+		//Set types
+		static $types = [
+			'default' => \NumberFormatter::TYPE_DEFAULT,
+			'int32' => \NumberFormatter::TYPE_INT32,
+			'int64' => \NumberFormatter::TYPE_INT64,
+			'double' => \NumberFormatter::TYPE_DOUBLE,
+			'currency' => \NumberFormatter::TYPE_CURRENCY
+		];
+
+		//Get formatter
+		$formatter = $this->getNumberFormatter($locale, $style);
+
+		//Without type
+		if (!isset($types[$type])) {
+			throw new SyntaxError(sprintf('The type "%s" does not exist. Known types are: "%s"', $type, implode('", "', array_keys($types))));
+		}
+
+		//Set unit
+		$unit = $si ? 1000 : 1024;
+
+		//Set index
+		$index = [ '', $si ? 'k' : 'K', 'M', 'G', 'T', 'P', 'E' ];
+
+		//Get exp
+		$exp = intval((log($number) / log($unit)));
 
-		$formatter = \NumberFormatter::create($locale, $styleValues[$style]);
+		//Rebase number
+		$number = round($number / pow($unit, $exp), 2);
 
-		return $formatter;
+		//Return formatted number
+		return $formatter->format($number, $types[$type]).' '.$index[$exp].($si ? '' : 'i').'B';
 	}
 }