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'];
|
$encodings = ['utf8', 'UTF-8'];
|
||||||
if (!empty($matches[2])) {
|
if (!empty($matches[2])) {
|
||||||
$second = [strtoupper($matches[2]), strtolower($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 {
|
} 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.
|
* Build a Generator object representing the cartesian product from given $items.
|
||||||
* The order is important because this doesn't shuffle the entries.
|
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* [['a'], ['b', 'c']]
|
* [['a'], ['b', 'c']]
|
||||||
* will generate:
|
* will generate:
|
||||||
* - ab
|
* [
|
||||||
* - ac
|
* ['a', 'b'],
|
||||||
*
|
* ['a', 'c'],
|
||||||
* TODO PHP 5.6: use the `...` operator instead of an array of array.
|
* ]
|
||||||
*
|
*
|
||||||
* @param array $items array of array of string
|
* @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 = [''];
|
if (empty($items)) {
|
||||||
foreach ($items as $item) {
|
yield [];
|
||||||
$add = [];
|
}
|
||||||
foreach ($item as $element) {
|
$subArray = array_pop($items);
|
||||||
foreach ($out as $key => $existingEntry) {
|
if (empty($subArray)) {
|
||||||
$add[] = $existingEntry . $element;
|
return;
|
||||||
}
|
}
|
||||||
}
|
foreach (cartesian_product_generator($items) as $item) {
|
||||||
$out = $add;
|
foreach ($subArray as $value) {
|
||||||
|
yield $item + [count($item) => $value];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -303,3 +305,33 @@ function normalize_spaces($string)
|
||||||
{
|
{
|
||||||
return preg_replace('/\s{2,}/', ' ', trim($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
|
// Expected log date format
|
||||||
protected static $dateFormat = 'Y/m/d H:i:s';
|
protected static $dateFormat = 'Y/m/d H:i:s';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Save the current timezone.
|
||||||
|
*/
|
||||||
|
protected static $defaultTimeZone;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assign reference data
|
* Assign reference data
|
||||||
|
@ -31,6 +36,17 @@ class UtilsTest extends PHPUnit_Framework_TestCase
|
||||||
public static function setUpBeforeClass()
|
public static function setUpBeforeClass()
|
||||||
{
|
{
|
||||||
self::$sidHashes = ReferenceSessionIdHashes::getHashes();
|
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
|
* Test arrays_combine
|
||||||
*/
|
*/
|
||||||
public function testArraysCombination()
|
public function testCartesianProductGenerator()
|
||||||
{
|
{
|
||||||
$arr = [['ab', 'cd'], ['ef', 'gh'], ['ij', 'kl'], ['m']];
|
$arr = [['ab', 'cd'], ['ef', 'gh'], ['ij', 'kl'], ['m']];
|
||||||
$expected = [
|
$expected = [
|
||||||
'abefijm',
|
['ab', 'ef', 'ij', 'm'],
|
||||||
'cdefijm',
|
['ab', 'ef', 'kl', 'm'],
|
||||||
'abghijm',
|
['ab', 'gh', 'ij', 'm'],
|
||||||
'cdghijm',
|
['ab', 'gh', 'kl', 'm'],
|
||||||
'abefklm',
|
['cd', 'ef', 'ij', 'm'],
|
||||||
'cdefklm',
|
['cd', 'ef', 'kl', 'm'],
|
||||||
'abghklm',
|
['cd', 'gh', 'ij', 'm'],
|
||||||
'cdghklm',
|
['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">
|
<div class="linklist-item-infos-dateblock pure-u-lg-3-8 pure-u-1">
|
||||||
<a href="?{$value.shorturl}" title="{'Permalink'|t}">
|
<a href="?{$value.shorturl}" title="{'Permalink'|t}">
|
||||||
{if="!$hide_timestamps || isLoggedIn()"}
|
{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}">
|
<span class="linkdate" title="{$updated}">
|
||||||
<i class="fa fa-clock-o"></i>
|
<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>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -99,11 +99,11 @@
|
||||||
<br>
|
<br>
|
||||||
{if="$value.description"}<div class="linkdescription">{$value.description}</div>{/if}
|
{if="$value.description"}<div class="linkdescription">{$value.description}</div>{/if}
|
||||||
{if="!$hide_timestamps || isLoggedIn()"}
|
{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">
|
<span class="linkdate" title="Permalink">
|
||||||
<a href="?{$value.shorturl}">
|
<a href="?{$value.shorturl}">
|
||||||
<span title="{$updated}">
|
<span title="{$updated}">
|
||||||
{function="strftime('%c', $value.timestamp)"}
|
{$value.created|format_date}
|
||||||
{if="$value.updated_timestamp"}*{/if}
|
{if="$value.updated_timestamp"}*{/if}
|
||||||
</span>
|
</span>
|
||||||
- permalink
|
- permalink
|
||||||
|
|
Loading…
Reference in a new issue