Use php-intl extension to display datetimes a bit more nicely, depending on the locale.
What changes:
* the day is no longer displayed
* day number and month are ordered according to the locale
* the timezone is more readable (UTC+1 instead of CET)
$encodings = ['utf8', 'UTF-8'];
if (!empty($matches[2])) {
$second = [strtoupper($matches[2]), strtolower($matches[2])];
- $attempts = arrays_combination([$first, $separators, $second, ['.'], $encodings]);
+ $attempts = cartesian_product_generator([$first, $separators, $second, ['.'], $encodings]);
} else {
- $attempts = arrays_combination([$first, $separators, $first, ['.'], $encodings]);
+ $attempts = cartesian_product_generator([$first, $separators, $first, ['.'], $encodings]);
}
}
}
- setlocale(LC_ALL, $attempts);
+ setlocale(LC_ALL, implode('implode', iterator_to_array($attempts)));
}
/**
- * Combine multiple arrays of string to get all possible strings.
- * The order is important because this doesn't shuffle the entries.
+ * Build a Generator object representing the cartesian product from given $items.
*
* Example:
* [['a'], ['b', 'c']]
* will generate:
- * - ab
- * - ac
- *
- * TODO PHP 5.6: use the `...` operator instead of an array of array.
+ * [
+ * ['a', 'b'],
+ * ['a', 'c'],
+ * ]
*
* @param array $items array of array of string
*
- * @return array Combined string from the input array.
+ * @return Generator representing the cartesian product of given array.
+ *
+ * @see https://en.wikipedia.org/wiki/Cartesian_product
*/
-function arrays_combination($items)
+function cartesian_product_generator($items)
{
- $out = [''];
- foreach ($items as $item) {
- $add = [];
- foreach ($item as $element) {
- foreach ($out as $key => $existingEntry) {
- $add[] = $existingEntry . $element;
- }
+ if (empty($items)) {
+ yield [];
+ }
+ $subArray = array_pop($items);
+ if (empty($subArray)) {
+ return;
+ }
+ foreach (cartesian_product_generator($items) as $item) {
+ foreach ($subArray as $value) {
+ yield $item + [count($item) => $value];
}
- $out = $add;
}
- return $out;
}
/**
{
return preg_replace('/\s{2,}/', ' ', trim($string));
}
+
+/**
+ * Format the date according to the locale.
+ *
+ * Requires php-intl to display international datetimes,
+ * otherwise default format '%c' will be returned.
+ *
+ * @param DateTime $date to format.
+ * @param bool $intl Use international format if true.
+ *
+ * @return bool|string Formatted date, or false if the input is invalid.
+ */
+function format_date($date, $intl = true)
+{
+ if (! $date instanceof DateTime) {
+ return false;
+ }
+
+ if (! $intl || ! class_exists('IntlDateFormatter')) {
+ return strftime('%c', $date->getTimestamp());
+ }
+
+ $formatter = new IntlDateFormatter(
+ setlocale(LC_TIME, 0),
+ IntlDateFormatter::LONG,
+ IntlDateFormatter::LONG
+ );
+
+ return $formatter->format($date);
+}
// Expected log date format
protected static $dateFormat = 'Y/m/d H:i:s';
-
+
+ /**
+ * @var string Save the current timezone.
+ */
+ protected static $defaultTimeZone;
+
/**
* Assign reference data
public static function setUpBeforeClass()
{
self::$sidHashes = ReferenceSessionIdHashes::getHashes();
+ self::$defaultTimeZone = date_default_timezone_get();
+ // Timezone without DST for test consistency
+ date_default_timezone_set('Africa/Nairobi');
+ }
+
+ /**
+ * Reset the timezone
+ */
+ public static function tearDownAfterClass()
+ {
+ date_default_timezone_set(self::$defaultTimeZone);
}
/**
/**
* Test arrays_combine
*/
- public function testArraysCombination()
+ public function testCartesianProductGenerator()
{
$arr = [['ab', 'cd'], ['ef', 'gh'], ['ij', 'kl'], ['m']];
$expected = [
- 'abefijm',
- 'cdefijm',
- 'abghijm',
- 'cdghijm',
- 'abefklm',
- 'cdefklm',
- 'abghklm',
- 'cdghklm',
+ ['ab', 'ef', 'ij', 'm'],
+ ['ab', 'ef', 'kl', 'm'],
+ ['ab', 'gh', 'ij', 'm'],
+ ['ab', 'gh', 'kl', 'm'],
+ ['cd', 'ef', 'ij', 'm'],
+ ['cd', 'ef', 'kl', 'm'],
+ ['cd', 'gh', 'ij', 'm'],
+ ['cd', 'gh', 'kl', 'm'],
];
- $this->assertEquals($expected, arrays_combination($arr));
+ $this->assertEquals($expected, iterator_to_array(cartesian_product_generator($arr)));
}
+ /**
+ * Test date_format() with invalid parameter.
+ */
+ public function testDateFormatInvalid()
+ {
+ $this->assertFalse(format_date([]));
+ $this->assertFalse(format_date(null));
+ }
}
--- /dev/null
+<?php
+if (! empty('UT_LOCALE')) {
+ setlocale(LC_ALL, getenv('UT_LOCALE'));
+}
+
+require_once 'vendor/autoload.php';
+
--- /dev/null
+<?php
+
+require_once 'tests/UtilsTest.php';
+
+
+class UtilsDeTest extends UtilsTest
+{
+ /**
+ * Test date_format().
+ */
+ public function testDateFormat()
+ {
+ $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
+ $this->assertRegExp('/1. Januar 2017 (um )?10:11:12 GMT\+0?3(:00)?/', format_date($date, true));
+ }
+
+ /**
+ * Test date_format() using builtin PHP function strftime.
+ */
+ public function testDateFormatDefault()
+ {
+ $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
+ $this->assertEquals('So 01 Jan 2017 10:11:12 EAT', format_date($date, false));
+ }
+}
--- /dev/null
+<?php
+
+require_once 'tests/UtilsTest.php';
+
+
+class UtilsEnTest extends UtilsTest
+{
+ /**
+ * Test date_format().
+ */
+ public function testDateFormat()
+ {
+ $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
+ $this->assertRegExp('/January 1, 2017 (at )?10:11:12 AM GMT\+0?3(:00)?/', format_date($date, true));
+ }
+
+ /**
+ * Test date_format() using builtin PHP function strftime.
+ */
+ public function testDateFormatDefault()
+ {
+ $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
+ $this->assertEquals('Sun 01 Jan 2017 10:11:12 AM EAT', format_date($date, false));
+ }
+}
--- /dev/null
+<?php
+
+require_once 'tests/UtilsTest.php';
+
+
+class UtilsFrTest extends UtilsTest
+{
+ /**
+ * Test date_format().
+ */
+ public function testDateFormat()
+ {
+ $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
+ $this->assertRegExp('/1 janvier 2017 (à )?10:11:12 UTC\+0?3(:00)?/', format_date($date));
+ }
+
+ /**
+ * Test date_format() using builtin PHP function strftime.
+ */
+ public function testDateFormatDefault()
+ {
+ $date = DateTime::createFromFormat('Ymd_His', '20170101_101112');
+ $this->assertEquals('dim. 01 janv. 2017 10:11:12 EAT', format_date($date, false));
+ }
+}
<div class="linklist-item-infos-dateblock pure-u-lg-3-8 pure-u-1">
<a href="?{$value.shorturl}" title="{'Permalink'|t}">
{if="!$hide_timestamps || isLoggedIn()"}
- {$updated=$value.updated_timestamp ? 'Edited: '. strftime('%c', $value.updated_timestamp) : 'Permalink'}
+ {$updated=$value.updated_timestamp ? 'Edited: '. format_date($value.updated) : 'Permalink'}
<span class="linkdate" title="{$updated}">
<i class="fa fa-clock-o"></i>
- {function="strftime('%c', $value.timestamp)"}{if="$value.updated_timestamp"}*{/if}
+ {$value.created|format_date}
+ {if="$value.updated_timestamp"}*{/if}
·
</span>
{/if}
<br>
{if="$value.description"}<div class="linkdescription">{$value.description}</div>{/if}
{if="!$hide_timestamps || isLoggedIn()"}
- {$updated=$value.updated_timestamp ? 'Edited: '. strftime('%c', $value.updated_timestamp) : 'Permalink'}
+ {$updated=$value.updated_timestamp ? 'Edited: '. format_date($value.updated) : 'Permalink'}
<span class="linkdate" title="Permalink">
<a href="?{$value.shorturl}">
<span title="{$updated}">
- {function="strftime('%c', $value.timestamp)"}
+ {$value.created|format_date}
{if="$value.updated_timestamp"}*{/if}
</span>
- permalink