Skip to content

Commit

Permalink
added filters |localDate, |localTime, |money, |numberInWords, |orderN…
Browse files Browse the repository at this point in the history
…umber
  • Loading branch information
dg committed May 26, 2024
1 parent 0e2ec6b commit 7a2e6ca
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 0 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"ext-iconv": "to use filters |reverse, |substring",
"ext-mbstring": "to use filters like lower, upper, capitalize, ...",
"ext-fileinfo": "to use filter |datastream",
"ext-intl": "to use filters |localDate, |localTime, ...",
"nette/utils": "to use filter |webalize",
"nette/php-generator": "to use tag {templatePrint}"
},
Expand Down
5 changes: 5 additions & 0 deletions src/Latte/Essential/CoreExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,15 @@ public function getFilters(): array
'join' => [$this->filters, 'implode'],
'last' => [$this->filters, 'last'],
'length' => [$this->filters, 'length'],
'localDate' => [$this->filters, 'localDate'],
'localTime' => [$this->filters, 'localTime'],
'lower' => extension_loaded('mbstring')
? [$this->filters, 'lower']
: fn() => throw new RuntimeException('Filter |lower requires mbstring extension.'),
'money' => [$this->filters, 'money'],
'number' => [$this->filters, 'number'],
'numberInWords' => [$this->filters, 'numberInWords'],
'orderNumber' => [$this->filters, 'orderNumber'],
'padLeft' => [$this->filters, 'padLeft'],
'padRight' => [$this->filters, 'padRight'],
'query' => [$this->filters, 'query'],
Expand Down
75 changes: 75 additions & 0 deletions src/Latte/Essential/Filters.php
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,81 @@ public function number(
return $formatter->format($number);
}

/**
* Prints the order number according to locale.
*/
public function orderNumber(float $number): string
{
$formatter = new \NumberFormatter($this->getLocale('orderNumber'), \NumberFormatter::ORDINAL);
return $formatter->format($number);
}

/**
* Prints the number in words according to locale.
*/
public function numberInWords(float $number): string
{
$formatter = new \NumberFormatter($this->getLocale('numberInWords'), \NumberFormatter::SPELLOUT);
return $formatter->format($number);
}


/**
* Format the currency value according to locale.
*/
public function money(float $amount, ?string $currency = null): string
{
$formatter = new \NumberFormatter($this->getLocale('money'), \NumberFormatter::CURRENCY);
return $currency === null
? $formatter->format($amount, \NumberFormatter::TYPE_DEFAULT)
: $formatter->formatCurrency($amount, $currency);
}


/**
* Local date formatting.
* https://unicode-org.github.io/icu/userguide/format_parse/datetime/#datetime-format-syntax
*/
public function localDate(string|int|\DateTimeInterface|null $time, string $format = 'medium'): ?string
{
if ($time == null) { // intentionally ==
return null;
} elseif (is_numeric($time)) {
$time = (new \DateTime)->setTimestamp((int) $time);
} elseif (is_string($time)) {
$time = new \DateTime($time);
}

$format = match ($format) {
'short' => \IntlDateFormatter::SHORT,
'medium' => \IntlDateFormatter::MEDIUM,
'long' => \IntlDateFormatter::LONG,
'full' => \IntlDateFormatter::FULL,
};
$formatter = new \IntlDateFormatter($this->getLocale('localDate'), $format, \IntlDateFormatter::NONE);
$res = $formatter->format($time);
$res = preg_replace('~(\d\.) ~', "\$1\u{a0}", $res);
return $res;
}


/**
* Local time formatting.
*/
public function localTime(string|int|\DateTimeInterface|null $time, bool $withSeconds = false): ?string
{
if ($time == null) { // intentionally ==
return null;
} elseif (is_numeric($time)) {
$time = (new \DateTime)->setTimestamp((int) $time);
} elseif (is_string($time)) {
$time = new \DateTime($time);
}

$formatter = new \IntlDateFormatter($this->getLocale('localTime'), \IntlDateFormatter::NONE, $withSeconds ? \IntlDateFormatter::MEDIUM : \IntlDateFormatter::SHORT);
return $formatter->format($time);
}


private function getLocale(string $name): string
{
Expand Down
41 changes: 41 additions & 0 deletions tests/filters/localDate.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

/**
* Test: Latte\Essential\Filters::localDate()
*/

declare(strict_types=1);

use Latte\Essential\Filters;
use Tester\Assert;

require __DIR__ . '/../bootstrap.php';


ini_set('intl.default_locale', 'cs_CZ');

// types of value
Assert::null(Filters::localDate(null));
Assert::same("23.\u{a0}1.\u{a0}1978", Filters::localDate(254_400_000));
Assert::same("5.\u{a0}5.\u{a0}1978", Filters::localDate('1978-05-05'));
Assert::same("5.\u{a0}5.\u{a0}1978", Filters::localDate(new DateTime('1978-05-05')));

// predefined date format
Assert::same('05.05.78', Filters::localDate(new DateTime('1978-05-05'), 'short'));
Assert::same("5.\u{a0}5.\u{a0}1978", Filters::localDate(new DateTime('1978-05-05'), 'medium'));
Assert::same("5.\u{a0}května 1978", Filters::localDate(new DateTime('1978-05-05'), 'long'));
Assert::same("pátek 5.\u{a0}května 1978", Filters::localDate(new DateTime('1978-05-05'), 'full'));

// predefined time format
Assert::same('12:13', Filters::localDate(new DateTime('12:13:14'), 'time'));
Assert::same('12:13:14', Filters::localDate(new DateTime('12:13:14'), 'time+sec'));

// combined
Assert::same('05.05.78 12:13', Filters::localDate(new DateTime('1978-05-05'), 'short+time'));

// custom format
Assert::same("po, led 23, '78", Filters::localDate(254_400_000, "EEE, MMM d, ''yy"));

// timestamp & timezone
date_default_timezone_set('America/Los_Angeles');
Assert::same('7:09:31', Filters::localDate(1_408_284_571, 'time+sec'));

0 comments on commit 7a2e6ca

Please sign in to comment.