Fix Github #1844 - Monthly views previous/next month links during month

end. Avoid deprecated strftime function. Got tests to pass in PHP 8.1.
This commit is contained in:
Keith Carangelo 2022-03-31 15:42:25 -04:00
parent f6076a9275
commit 6ecc4745f4
8 changed files with 106 additions and 49 deletions

View file

@ -197,7 +197,7 @@ function generateLocation($referer, $host, $loopTerms = [])
function autoLocale($headerLocale) function autoLocale($headerLocale)
{ {
// Default if browser does not send HTTP_ACCEPT_LANGUAGE // Default if browser does not send HTTP_ACCEPT_LANGUAGE
$locales = ['en_US', 'en_US.utf8', 'en_US.UTF-8']; $locales = ['en_US.UTF-8', 'en_US.utf8', 'en_US'];
if (! empty($headerLocale)) { if (! empty($headerLocale)) {
if (preg_match_all('/([a-z]{2,3})[-_]?([a-z]{2})?,?/i', $headerLocale, $matches, PREG_SET_ORDER)) { if (preg_match_all('/([a-z]{2,3})[-_]?([a-z]{2})?,?/i', $headerLocale, $matches, PREG_SET_ORDER)) {
$attempts = []; $attempts = [];
@ -314,10 +314,12 @@ function format_date($date, $time = true, $intl = true)
} }
if (! $intl || ! class_exists('IntlDateFormatter')) { if (! $intl || ! class_exists('IntlDateFormatter')) {
$format = $time ? '%c' : '%x'; $format = 'F j, Y';
return strftime($format, $date->getTimestamp()); if ($time) {
$format .= ' h:i:s A \G\M\TP';
}
return $date->format( $format );
} }
$formatter = new IntlDateFormatter( $formatter = new IntlDateFormatter(
setlocale(LC_TIME, 0), setlocale(LC_TIME, 0),
IntlDateFormatter::LONG, IntlDateFormatter::LONG,

View file

@ -60,6 +60,11 @@ public static function extractRequestedDateTime(
; ;
} }
// Don't use today's day of month (github issue #1844)
if ($type === static::MONTH) {
$format = '!' . $format;
}
// W is not supported by createFromFormat... // W is not supported by createFromFormat...
if ($type === static::WEEK) { if ($type === static::WEEK) {
return (new DateTimeImmutable()) return (new DateTimeImmutable())

View file

@ -30,9 +30,13 @@ function is_iterable($var)
require_once 'tests/container/ShaarliTestContainer.php'; require_once 'tests/container/ShaarliTestContainer.php';
require_once 'tests/front/controller/visitor/FrontControllerMockHelper.php'; require_once 'tests/front/controller/visitor/FrontControllerMockHelper.php';
require_once 'tests/front/controller/admin/FrontAdminControllerMockHelper.php'; require_once 'tests/front/controller/admin/FrontAdminControllerMockHelper.php';
require_once 'tests/updater/DummyUpdater.php';
require_once 'tests/utils/FakeApplicationUtils.php';
require_once 'tests/utils/FakeBookmarkService.php';
require_once 'tests/utils/FakeConfigManager.php'; require_once 'tests/utils/FakeConfigManager.php';
require_once 'tests/utils/ReferenceHistory.php'; require_once 'tests/utils/ReferenceHistory.php';
require_once 'tests/utils/ReferenceLinkDB.php'; require_once 'tests/utils/ReferenceLinkDB.php';
require_once 'tests/utils/ReferenceSessionIdHashes.php';
ReferenceSessionIdHashes::genAllHashes(); ReferenceSessionIdHashes::genAllHashes();

View file

@ -667,11 +667,11 @@ public function testSimpleRssWeekly(): void
public function testSimpleRssMonthly(): void public function testSimpleRssMonthly(): void
{ {
$dates = [ $dates = [
new \DateTimeImmutable('2020-05-19'), new \DateTimeImmutable('2022-02-19'),
new \DateTimeImmutable('2020-04-13'), new \DateTimeImmutable('2020-04-13'),
]; ];
$expectedDates = [ $expectedDates = [
new \DateTimeImmutable('2020-05-31 23:59:59'), new \DateTimeImmutable('2022-02-28 23:59:59'),
new \DateTimeImmutable('2020-04-30 23:59:59'), new \DateTimeImmutable('2020-04-30 23:59:59'),
]; ];
@ -710,7 +710,7 @@ public function testSimpleRssMonthly(): void
static::assertEquals($date, $day['date']); static::assertEquals($date, $day['date']);
static::assertSame($date->format(\DateTime::RSS), $day['date_rss']); static::assertSame($date->format(\DateTime::RSS), $day['date_rss']);
static::assertSame('May, 2020', $day['date_human']); static::assertSame('February, 2022', $day['date_human']);
static::assertSame('http://shaarli/subfolder/daily?month=' . $dates[0]->format('Ym'), $day['absolute_url']); static::assertSame('http://shaarli/subfolder/daily?month=' . $dates[0]->format('Ym'), $day['absolute_url']);
static::assertCount(1, $day['links']); static::assertCount(1, $day['links']);

View file

@ -258,7 +258,7 @@ public function getStartDatesByType(): array
return [ return [
[DailyPageHelper::DAY, new DateTimeImmutable('2020-10-09 04:05:06'), new DateTime('2020-10-09 00:00:00')], [DailyPageHelper::DAY, new DateTimeImmutable('2020-10-09 04:05:06'), new DateTime('2020-10-09 00:00:00')],
[DailyPageHelper::WEEK, new DateTimeImmutable('2020-10-09 04:05:06'), new DateTime('2020-10-05 00:00:00')], [DailyPageHelper::WEEK, new DateTimeImmutable('2020-10-09 04:05:06'), new DateTime('2020-10-05 00:00:00')],
[DailyPageHelper::MONTH, new DateTimeImmutable('2020-10-09 04:05:06'), new DateTime('2020-10-01 00:00:00')], [DailyPageHelper::MONTH, new DateTimeImmutable('2022-03-30 04:05:06'), new DateTime('2022-03-01 00:00:00')],
]; ];
} }
@ -270,7 +270,8 @@ public function getEndDatesByType(): array
return [ return [
[DailyPageHelper::DAY, new DateTimeImmutable('2020-10-09 04:05:06'), new DateTime('2020-10-09 23:59:59')], [DailyPageHelper::DAY, new DateTimeImmutable('2020-10-09 04:05:06'), new DateTime('2020-10-09 23:59:59')],
[DailyPageHelper::WEEK, new DateTimeImmutable('2020-10-09 04:05:06'), new DateTime('2020-10-11 23:59:59')], [DailyPageHelper::WEEK, new DateTimeImmutable('2020-10-09 04:05:06'), new DateTime('2020-10-11 23:59:59')],
[DailyPageHelper::MONTH, new DateTimeImmutable('2020-10-09 04:05:06'), new DateTime('2020-10-31 23:59:59')], [DailyPageHelper::MONTH, new DateTimeImmutable('2022-02-28 04:05:06'), new DateTime('2022-02-28 23:59:59')],
[DailyPageHelper::MONTH, new DateTimeImmutable('2022-03-30 04:05:06'), new DateTime('2022-03-31 23:59:59')],
]; ];
} }

View file

@ -6,13 +6,25 @@
class UtilsDeTest extends UtilsTest class UtilsDeTest extends UtilsTest
{ {
/**
* Test for international date formatter class. Other tests
* will fail without it!
*/
public function testIntlDateFormatter()
{
$this->assertTrue( class_exists('IntlDateFormatter') );
}
/** /**
* Test date_format(). * Test date_format().
*/ */
public function testDateFormat() public function testDateFormat()
{ {
$date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); $current = setlocale(LC_ALL, 0);
$this->assertRegExp('/1\. Januar 2017 (um )?10:11:12 GMT\+0?3(:00)?/', format_date($date, true, true)); autoLocale('de-de');
$date = DateTime::createFromFormat('Ymd_His', '20170102_201112');
$this->assertRegExp('/2\. Januar 2017 (um )?20:11:12 GMT\+0?3(:00)?/', format_date($date, true, true));
setlocale(LC_ALL, $current);
} }
/** /**
@ -20,26 +32,29 @@ public function testDateFormat()
*/ */
public function testDateFormatNoTime() public function testDateFormatNoTime()
{ {
$date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); $current = setlocale(LC_ALL, 0);
$this->assertRegExp('/1\. Januar 2017/', format_date($date, false, true)); autoLocale('de-de');
$date = DateTime::createFromFormat('Ymd_His', '20170102_201112');
$this->assertRegExp('/2\. Januar 2017/', format_date($date, false, true));
setlocale(LC_ALL, $current);
} }
/** /**
* Test date_format() using builtin PHP function strftime. * Test date_format() using DateTime
*/ */
public function testDateFormatDefault() public function testDateFormatDefault()
{ {
$date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); $date = DateTime::createFromFormat('Ymd_His', '20170102_101112');
$this->assertEquals('So 01 Jan 2017 10:11:12 EAT', format_date($date, true, false)); $this->assertEquals('January 2, 2017 10:11:12 AM GMT+03:00', format_date($date, true, false));
} }
/** /**
* Test date_format() using builtin PHP function strftime without time. * Test date_format() using DateTime
*/ */
public function testDateFormatDefaultNoTime() public function testDateFormatDefaultNoTime()
{ {
$date = DateTime::createFromFormat('Ymd_His', '20170201_101112'); $date = DateTime::createFromFormat('Ymd_His', '20170201_101112');
$this->assertEquals('01.02.2017', format_date($date, false, false)); $this->assertEquals('February 1, 2017', format_date($date, false, false));
} }
/** /**
@ -61,7 +76,7 @@ public function testAutoLocaleValid()
public function testAutoLocaleValidAlternative() public function testAutoLocaleValidAlternative()
{ {
$current = setlocale(LC_ALL, 0); $current = setlocale(LC_ALL, 0);
$header = 'en_us.UTF8'; $header = 'en_US.UTF-8';
autoLocale($header); autoLocale($header);
$this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); $this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0));
@ -87,7 +102,7 @@ public function testAutoLocaleMultipleFirstValid()
public function testAutoLocaleMultipleSecondAvailable() public function testAutoLocaleMultipleSecondAvailable()
{ {
$current = setlocale(LC_ALL, 0); $current = setlocale(LC_ALL, 0);
$header = 'mag_IN,fr-fr'; $header = 'mgg_IN,fr-fr';
autoLocale($header); autoLocale($header);
$this->assertEquals('fr_FR.utf8', setlocale(LC_ALL, 0)); $this->assertEquals('fr_FR.utf8', setlocale(LC_ALL, 0));
@ -101,7 +116,7 @@ public function testAutoLocaleBlank()
{ {
$current = setlocale(LC_ALL, 0); $current = setlocale(LC_ALL, 0);
autoLocale(''); autoLocale('');
$this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0));
setlocale(LC_ALL, $current); setlocale(LC_ALL, $current);
} }
@ -112,8 +127,8 @@ public function testAutoLocaleBlank()
public function testAutoLocaleUnavailable() public function testAutoLocaleUnavailable()
{ {
$current = setlocale(LC_ALL, 0); $current = setlocale(LC_ALL, 0);
autoLocale('mag_IN'); autoLocale('mgg_IN');
$this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0));
setlocale(LC_ALL, $current); setlocale(LC_ALL, $current);
} }

View file

@ -6,13 +6,25 @@
class UtilsEnTest extends UtilsTest class UtilsEnTest extends UtilsTest
{ {
/**
* Test for international date formatter class. Other tests
* will fail without it!
*/
public function testIntlDateFormatter()
{
$this->assertTrue( class_exists('IntlDateFormatter') );
}
/** /**
* Test date_format(). * Test date_format().
*/ */
public function testDateFormat() public function testDateFormat()
{ {
$date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); $current = setlocale(LC_ALL, 0);
$this->assertRegExp('/January 1, 2017 (at )?10:11:12 AM GMT\+0?3(:00)?/', format_date($date, true, true)); autoLocale('en_US.UTF-8');
$date = DateTime::createFromFormat('Ymd_His', '20170102_201112');
$this->assertRegExp('/January 2, 2017 (at )?8:11:12 PM GMT\+0?3(:00)?/', format_date($date, true, true));
setlocale(LC_ALL, $current);
} }
/** /**
@ -20,26 +32,29 @@ public function testDateFormat()
*/ */
public function testDateFormatNoTime() public function testDateFormatNoTime()
{ {
$date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); $current = setlocale(LC_ALL, 0);
$this->assertRegExp('/January 1, 2017/', format_date($date, false, true)); autoLocale('en_US.UTF-8');
$date = DateTime::createFromFormat('Ymd_His', '20170102_201112');
$this->assertRegExp('/January 2, 2017/', format_date($date, false, true));
setlocale(LC_ALL, $current);
} }
/** /**
* Test date_format() using builtin PHP function strftime. * Test date_format() using DateTime
*/ */
public function testDateFormatDefault() public function testDateFormatDefault()
{ {
$date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); $date = DateTime::createFromFormat('Ymd_His', '20170102_101112');
$this->assertEquals('Sun 01 Jan 2017 10:11:12 AM EAT', format_date($date, true, false)); $this->assertEquals('January 2, 2017 10:11:12 AM GMT+03:00', format_date($date, true, false));
} }
/** /**
* Test date_format() using builtin PHP function strftime without time. * Test date_format() using DateTime
*/ */
public function testDateFormatDefaultNoTime() public function testDateFormatDefaultNoTime()
{ {
$date = DateTime::createFromFormat('Ymd_His', '20170201_101112'); $date = DateTime::createFromFormat('Ymd_His', '20170201_101112');
$this->assertEquals('02/01/2017', format_date($date, false, false)); $this->assertEquals('February 1, 2017', format_date($date, false, false));
} }
/** /**
@ -87,7 +102,7 @@ public function testAutoLocaleMultipleFirstValid()
public function testAutoLocaleMultipleSecondAvailable() public function testAutoLocaleMultipleSecondAvailable()
{ {
$current = setlocale(LC_ALL, 0); $current = setlocale(LC_ALL, 0);
$header = 'mag_IN,fr-fr'; $header = 'mgg_IN,fr-fr';
autoLocale($header); autoLocale($header);
$this->assertEquals('fr_FR.utf8', setlocale(LC_ALL, 0)); $this->assertEquals('fr_FR.utf8', setlocale(LC_ALL, 0));
@ -101,7 +116,7 @@ public function testAutoLocaleBlank()
{ {
$current = setlocale(LC_ALL, 0); $current = setlocale(LC_ALL, 0);
autoLocale(''); autoLocale('');
$this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0));
setlocale(LC_ALL, $current); setlocale(LC_ALL, $current);
} }
@ -112,8 +127,8 @@ public function testAutoLocaleBlank()
public function testAutoLocaleUnavailable() public function testAutoLocaleUnavailable()
{ {
$current = setlocale(LC_ALL, 0); $current = setlocale(LC_ALL, 0);
autoLocale('mag_IN'); autoLocale('mgg_IN');
$this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0));
setlocale(LC_ALL, $current); setlocale(LC_ALL, $current);
} }

View file

@ -6,13 +6,25 @@
class UtilsFrTest extends UtilsTest class UtilsFrTest extends UtilsTest
{ {
/**
* Test for international date formatter class. Other tests
* will fail without it!
*/
public function testIntlDateFormatter()
{
$this->assertTrue( class_exists('IntlDateFormatter') );
}
/** /**
* Test date_format(). * Test date_format().
*/ */
public function testDateFormat() public function testDateFormat()
{ {
$date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); $current = setlocale(LC_ALL, 0);
$this->assertRegExp('/1 janvier 2017 (à )?10:11:12 UTC\+0?3(:00)?/', format_date($date)); autoLocale('fr-fr');
$date = DateTime::createFromFormat('Ymd_His', '20170102_201112');
$this->assertRegExp('/2 janvier 2017 (à )?20:11:12 UTC\+0?3(:00)?/', format_date($date));
setlocale(LC_ALL, $current);
} }
/** /**
@ -20,26 +32,29 @@ public function testDateFormat()
*/ */
public function testDateFormatNoTime() public function testDateFormatNoTime()
{ {
$date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); $current = setlocale(LC_ALL, 0);
$this->assertRegExp('/1 janvier 2017/', format_date($date, false, true)); autoLocale('fr-fr');
$date = DateTime::createFromFormat('Ymd_His', '20170102_201112');
$this->assertRegExp('/2 janvier 2017/', format_date($date, false, true));
setlocale(LC_ALL, $current);
} }
/** /**
* Test date_format() using builtin PHP function strftime. * Test date_format() using DateTime
*/ */
public function testDateFormatDefault() public function testDateFormatDefault()
{ {
$date = DateTime::createFromFormat('Ymd_His', '20170101_101112'); $date = DateTime::createFromFormat('Ymd_His', '20170102_101112');
$this->assertEquals('dim. 01 janv. 2017 10:11:12 EAT', format_date($date, true, false)); $this->assertEquals('January 2, 2017 10:11:12 AM GMT+03:00', format_date($date, true, false));
} }
/** /**
* Test date_format() using builtin PHP function strftime without time. * Test date_format() using DateTime
*/ */
public function testDateFormatDefaultNoTime() public function testDateFormatDefaultNoTime()
{ {
$date = DateTime::createFromFormat('Ymd_His', '20170201_101112'); $date = DateTime::createFromFormat('Ymd_His', '20170201_101112');
$this->assertEquals('01/02/2017', format_date($date, false, false)); $this->assertEquals('February 1, 2017', format_date($date, false, false));
} }
/** /**
@ -87,7 +102,7 @@ public function testAutoLocaleMultipleFirstValid()
public function testAutoLocaleMultipleSecondAvailable() public function testAutoLocaleMultipleSecondAvailable()
{ {
$current = setlocale(LC_ALL, 0); $current = setlocale(LC_ALL, 0);
$header = 'mag_IN,de-de'; $header = 'mgg_IN,de-de';
autoLocale($header); autoLocale($header);
$this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0)); $this->assertEquals('de_DE.utf8', setlocale(LC_ALL, 0));
@ -101,7 +116,7 @@ public function testAutoLocaleBlank()
{ {
$current = setlocale(LC_ALL, 0); $current = setlocale(LC_ALL, 0);
autoLocale(''); autoLocale('');
$this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0));
setlocale(LC_ALL, $current); setlocale(LC_ALL, $current);
} }
@ -112,8 +127,8 @@ public function testAutoLocaleBlank()
public function testAutoLocaleUnavailable() public function testAutoLocaleUnavailable()
{ {
$current = setlocale(LC_ALL, 0); $current = setlocale(LC_ALL, 0);
autoLocale('mag_IN'); autoLocale('mgg_IN');
$this->assertEquals('en_US.utf8', setlocale(LC_ALL, 0)); $this->assertEquals('en_US.UTF-8', setlocale(LC_ALL, 0));
setlocale(LC_ALL, $current); setlocale(LC_ALL, $current);
} }