From 50b5edc46edf14589399e4e0f22e0dcb5c030789 Mon Sep 17 00:00:00 2001 From: Seamus Lee Date: Thu, 21 Jul 2022 16:15:02 +1000 Subject: [PATCH] [REF][PHP8.1][INTL] Remove dependency on strftime function by using ts to generate day full names and abbreviations and month abbreviations Fix array order and add unit test to lock in fix --- CRM/Contribute/Form/ContributionCharts.php | 4 +- CRM/Core/Payment/Realex.php | 2 +- CRM/Utils/Date.php | 83 ++++++++++++++-------- tests/phpunit/CRM/Utils/DateTest.php | 17 +++++ 4 files changed, 72 insertions(+), 34 deletions(-) diff --git a/CRM/Contribute/Form/ContributionCharts.php b/CRM/Contribute/Form/ContributionCharts.php index 57673d9470..33822e5063 100644 --- a/CRM/Contribute/Form/ContributionCharts.php +++ b/CRM/Contribute/Form/ContributionCharts.php @@ -94,9 +94,7 @@ class CRM_Contribute_Form_ContributionCharts extends CRM_Core_Form { $chartData = $abbrMonthNames = []; if (is_array($chartInfoMonthly)) { - for ($i = 1; $i <= 12; $i++) { - $abbrMonthNames[$i] = strftime('%b', mktime(0, 0, 0, $i, 10, 1970)); - } + $abbrMonthNames = CRM_Utils_Date::getAbbrMonthNames(); foreach ($abbrMonthNames as $monthKey => $monthName) { $val = CRM_Utils_Array::value($monthKey, $chartInfoMonthly['By Month'], 0); diff --git a/CRM/Core/Payment/Realex.php b/CRM/Core/Payment/Realex.php index 56d95a7734..4757f7fee7 100644 --- a/CRM/Core/Payment/Realex.php +++ b/CRM/Core/Payment/Realex.php @@ -363,7 +363,7 @@ class CRM_Core_Payment_Realex extends CRM_Core_Payment { } // Create timestamp - $timestamp = strftime('%Y%m%d%H%M%S'); + $timestamp = date('YmdHis'); $this->_setParam('timestamp', $timestamp); } diff --git a/CRM/Utils/Date.php b/CRM/Utils/Date.php index 960f03d9c1..ff09f05e2e 100644 --- a/CRM/Utils/Date.php +++ b/CRM/Utils/Date.php @@ -161,20 +161,25 @@ class CRM_Utils_Date { */ public static function getAbbrWeekdayNames() { $key = 'abbrDays_' . \CRM_Core_I18n::getLocale(); - $days = &\Civi::$statics[__CLASS__][$key]; - if (!$days) { - $days = []; + if (empty(\Civi::$statics[__CLASS__][$key])) { + $days = [ + 0 => ts('Sun'), + 1 => ts('Mon'), + 2 => ts('Tue'), + 3 => ts('Wed'), + 4 => ts('Thu'), + 5 => ts('Fri'), + 6 => ts('Sat'), + ]; // First day of the week $firstDay = Civi::settings()->get('weekBegins'); - // set LC_TIME and build the arrays from locale-provided names - // June 1st, 1970 was a Monday - CRM_Core_I18n::setLcTime(); - for ($i = $firstDay; count($days) < 7; $i = $i > 5 ? 0 : $i + 1) { - $days[$i] = strftime('%a', mktime(0, 0, 0, 6, $i, 1970)); + \Civi::$statics[__CLASS__][$key] = []; + for ($i = $firstDay; count(\Civi::$statics[__CLASS__][$key]) < 7; $i = $i > 5 ? 0 : $i + 1) { + \Civi::$statics[__CLASS__][$key][$i] = $days[$i]; } } - return $days; + return \Civi::$statics[__CLASS__][$key]; } /** @@ -192,20 +197,25 @@ class CRM_Utils_Date { */ public static function getFullWeekdayNames() { $key = 'fullDays_' . \CRM_Core_I18n::getLocale(); - $days = &\Civi::$statics[__CLASS__][$key]; - if (!$days) { - $days = []; + if (empty(\Civi::$statics[__CLASS__][$key])) { + $days = [ + 0 => ts('Sunday'), + 1 => ts('Monday'), + 2 => ts('Tuesday'), + 3 => ts('Wednesday'), + 4 => ts('Thursday'), + 5 => ts('Friday'), + 6 => ts('Saturday'), + ]; // First day of the week $firstDay = Civi::settings()->get('weekBegins'); - // set LC_TIME and build the arrays from locale-provided names - // June 1st, 1970 was a Monday - CRM_Core_I18n::setLcTime(); - for ($i = $firstDay; count($days) < 7; $i = $i > 5 ? 0 : $i + 1) { - $days[$i] = strftime('%A', mktime(0, 0, 0, 6, $i, 1970)); + \Civi::$statics[__CLASS__][$key] = []; + for ($i = $firstDay; count(\Civi::$statics[__CLASS__][$key]) < 7; $i = $i > 5 ? 0 : $i + 1) { + \Civi::$statics[__CLASS__][$key][$i] = $days[$i]; } } - return $days; + return \Civi::$statics[__CLASS__][$key]; } /** @@ -219,19 +229,26 @@ class CRM_Utils_Date { */ public static function &getAbbrMonthNames($month = FALSE) { $key = 'abbrMonthNames_' . \CRM_Core_I18n::getLocale(); - $abbrMonthNames = &\Civi::$statics[__CLASS__][$key]; - if (!isset($abbrMonthNames)) { - - // set LC_TIME and build the arrays from locale-provided names - CRM_Core_I18n::setLcTime(); - for ($i = 1; $i <= 12; $i++) { - $abbrMonthNames[$i] = strftime('%b', mktime(0, 0, 0, $i, 10, 1970)); - } + if (empty(\Civi::$statics[__CLASS__][$key])) { + \Civi::$statics[__CLASS__][$key] = [ + 1 => ts('Jan'), + 2 => ts('Feb'), + 3 => ts('Mar'), + 4 => ts('Apr'), + 5 => ts('May'), + 6 => ts('Jun'), + 7 => ts('Jul'), + 8 => ts('Aug'), + 9 => ts('Sep'), + 10 => ts('Oct'), + 11 => ts('Nov'), + 12 => ts('Dec'), + ]; } if ($month) { - return $abbrMonthNames[$month]; + return \Civi::$statics[__CLASS__][$key][$month]; } - return $abbrMonthNames; + return \Civi::$statics[__CLASS__][$key]; } /** @@ -287,7 +304,8 @@ class CRM_Utils_Date { /** * Create a date and time string in a provided format. - * + * %A - Full day name ('Saturday'..'Sunday') + * %a - abbreviated day name ('Sat'..'Sun') * %b - abbreviated month name ('Jan'..'Dec') * %B - full month name ('January'..'December') * %d - day of the month as a decimal number, 0-padded ('01'..'31') @@ -318,6 +336,8 @@ class CRM_Utils_Date { // 1-based (January) month names arrays $abbrMonths = self::getAbbrMonthNames(); $fullMonths = self::getFullMonthNames(); + $fullWeekdayNames = self::getFullWeekdayNames(); + $abbrWeekdayNames = self::getAbbrWeekdayNames(); if (!$format) { $config = CRM_Core_Config::singleton(); @@ -381,6 +401,8 @@ class CRM_Utils_Date { $second = (int) substr($dateString, 12, 2); } + $dayInt = date('w', strtotime($dateString)); + if ($day % 10 == 1 and $day != 11) { $suffix = 'st'; } @@ -414,6 +436,8 @@ class CRM_Utils_Date { } $date = [ + '%A' => $fullWeekdayNames[$dayInt] ?? NULL, + '%a' => $abbrWeekdayNames[$dayInt] ?? NULL, '%b' => $abbrMonths[$month] ?? NULL, '%B' => $fullMonths[$month] ?? NULL, '%d' => $day > 9 ? $day : '0' . $day, @@ -430,7 +454,6 @@ class CRM_Utils_Date { '%i' => $minute > 9 ? $minute : '0' . $minute, '%p' => strtolower($type), '%P' => $type, - '%A' => $type, '%Y' => $year, '%s' => str_pad($second, 2, 0, STR_PAD_LEFT), '%S' => str_pad($second, 2, 0, STR_PAD_LEFT), diff --git a/tests/phpunit/CRM/Utils/DateTest.php b/tests/phpunit/CRM/Utils/DateTest.php index b68f1b39b8..3c32f661cd 100644 --- a/tests/phpunit/CRM/Utils/DateTest.php +++ b/tests/phpunit/CRM/Utils/DateTest.php @@ -271,6 +271,8 @@ class CRM_Utils_DateTest extends CiviUnitTestCase { $this->assertEquals(CRM_Utils_Date::customFormat($dateTime, "%P"), "PM"); $this->assertEquals(CRM_Utils_Date::customFormat($dateTime, "%Y"), "2018"); $this->assertEquals(CRM_Utils_Date::customFormat($dateTime, "%s"), "44"); + $this->assertEquals(CRM_Utils_Date::customFormat($dateTime, "%A"), "Thursday"); + $this->assertEquals(CRM_Utils_Date::customFormat($dateTime, "%a"), "Thu"); } /** @@ -293,6 +295,8 @@ class CRM_Utils_DateTest extends CiviUnitTestCase { $this->assertEquals(CRM_Utils_Date::customFormatTs($ts, "%p"), "pm"); $this->assertEquals(CRM_Utils_Date::customFormatTs($ts, "%P"), "PM"); $this->assertEquals(CRM_Utils_Date::customFormatTs($ts, "%Y"), "2018"); + $this->assertEquals(CRM_Utils_Date::customFormatTs($ts, "%A"), "Thursday"); + $this->assertEquals(CRM_Utils_Date::customFormatTs($ts, "%a"), "Thu"); } /** @@ -325,6 +329,19 @@ class CRM_Utils_DateTest extends CiviUnitTestCase { } } + public function testWeekDayArrayOrder() { + $this->callAPISuccess('Setting', 'create', ['weekBegins' => 1]); + $this->assertEquals([ + 1 => 'Monday', + 2 => 'Tuesday', + 3 => 'Wednesday', + 4 => 'Thursday', + 5 => 'Friday', + 6 => 'Saturday', + 0 => 'Sunday', + ], CRM_Utils_Date::getFullWeekdayNames()); + } + /** * Test formatDate function. * -- 2.25.1