Improve datetime display
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)
This commit is contained in:
parent
1255a42cfe
commit
52b503105d
8 changed files with 175 additions and 36 deletions
|
@ -225,44 +225,46 @@ function autoLocale($headerLocale)
|
|||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -303,3 +305,33 @@ function normalize_spaces($string)
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,11 @@ class UtilsTest extends PHPUnit_Framework_TestCase
|
|||
// 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
|
||||
|
@ -31,6 +36,17 @@ class UtilsTest extends PHPUnit_Framework_TestCase
|
|||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -286,20 +302,28 @@ public function testNormalizeSpace()
|
|||
/**
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
|
|
7
tests/languages/bootstrap.php
Normal file
7
tests/languages/bootstrap.php
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
if (! empty('UT_LOCALE')) {
|
||||
setlocale(LC_ALL, getenv('UT_LOCALE'));
|
||||
}
|
||||
|
||||
require_once 'vendor/autoload.php';
|
||||
|
25
tests/languages/de/UtilsDeTest.php
Normal file
25
tests/languages/de/UtilsDeTest.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?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));
|
||||
}
|
||||
}
|
25
tests/languages/en/UtilsEnTest.php
Normal file
25
tests/languages/en/UtilsEnTest.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?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));
|
||||
}
|
||||
}
|
25
tests/languages/fr/UtilsFrTest.php
Normal file
25
tests/languages/fr/UtilsFrTest.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?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));
|
||||
}
|
||||
}
|
|
@ -171,10 +171,11 @@ <h2>
|
|||
<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}
|
||||
|
|
|
@ -99,11 +99,11 @@
|
|||
<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
|
||||
|
|
Loading…
Reference in a new issue