Skip to content

Commit

Permalink
Improve datetime display
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
ArthurHoaro committed Mar 6, 2017
1 parent 1255a42 commit 52b5031
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 35 deletions.
72 changes: 52 additions & 20 deletions application/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down Expand Up @@ -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);
}
46 changes: 35 additions & 11 deletions tests/UtilsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,30 @@ 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
*/
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);
}

/**
Expand Down Expand Up @@ -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 changes: 7 additions & 0 deletions tests/languages/bootstrap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php
if (! empty('UT_LOCALE')) {
setlocale(LC_ALL, getenv('UT_LOCALE'));
}

require_once 'vendor/autoload.php';

25 changes: 25 additions & 0 deletions tests/languages/de/UtilsDeTest.php
Original file line number Diff line number Diff line change
@@ -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 changes: 25 additions & 0 deletions tests/languages/en/UtilsEnTest.php
Original file line number Diff line number Diff line change
@@ -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 changes: 25 additions & 0 deletions tests/languages/fr/UtilsFrTest.php
Original file line number Diff line number Diff line change
@@ -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));
}
}
5 changes: 3 additions & 2 deletions tpl/default/linklist.html
Original file line number Diff line number Diff line change
Expand Up @@ -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}
&middot;
</span>
{/if}
Expand Down
4 changes: 2 additions & 2 deletions tpl/vintage/linklist.html
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 52b5031

Please sign in to comment.