From 5d852997c69a0b9278817d6aaa08ce73bff54ad8 Mon Sep 17 00:00:00 2001 From: campbell-m <87438215+campbell-m@users.noreply.github.com> Date: Wed, 8 Nov 2023 18:15:15 +0000 Subject: [PATCH] Add the ability to override ICU values for week numbering - useful when the ICU library can't be updated. --- web/language.inc | 29 ++++++++++++++++++++++++++++- web/lib/MRBS/DateTime.php | 31 +++++++++++++++++++++++++++---- web/systemdefaults.inc.php | 20 ++++++++++++++++++++ 3 files changed, 75 insertions(+), 5 deletions(-) diff --git a/web/language.inc b/web/language.inc index f1be869861..e14ac4ab59 100644 --- a/web/language.inc +++ b/web/language.inc @@ -786,6 +786,13 @@ function get_loc_field_name(string $table, string $name) : string function datetime_format(array $format, int $timestamp=null, string $locale=null) : string { + global $icu_override, $timezone; + + if (!isset($timestamp)) + { + $timestamp = time(); + } + if (!isset($locale)) { $locale = get_mrbs_locale(); @@ -809,7 +816,27 @@ function datetime_format(array $format, int $timestamp=null, string $locale=null null, null, $pattern ); - return $formatter->format($timestamp ?? time()); + // If we're overriding the ICU value(s) then use those, provided that we're able to make use + // of them with the IntlCalendar and (standard, not emulated - hence the check for the loaded + // extension, rather than whether the class exists, which it always will) IntlDateFormatter classes. + if (isset($icu_override[$locale]) && extension_loaded('intl') && class_exists('IntlCalendar')) + { + $cal = \IntlCalendar::createInstance($timezone, $locale); + { + if (isset($icu_override[$locale]['first_day_of_week'])) + { + $cal->setFirstDayOfWeek($icu_override[$locale]['first_day_of_week']); + } + if (isset($icu_override[$locale]['minimal_days_in_first_week'])) + { + $cal->setMinimalDaysInFirstWeek($icu_override[$locale]['minimal_days_in_first_week']); + } + } + $cal->setTime($timestamp * 1000); + return $formatter->format($cal); + } + + return $formatter->format($timestamp); } diff --git a/web/lib/MRBS/DateTime.php b/web/lib/MRBS/DateTime.php index 4f6b3f9783..7c869a4e31 100644 --- a/web/lib/MRBS/DateTime.php +++ b/web/lib/MRBS/DateTime.php @@ -42,6 +42,8 @@ public static function createFromFormat($format, $datetime, ?\DateTimeZone $time // the method assumes that the week starts on a Monday. public static function firstDayOfWeek(?string $timezone = null, ?string $locale = null) : int { + global $icu_override; + $default = 1; // Monday if (!class_exists('\\IntlCalendar')) @@ -56,11 +58,32 @@ public static function firstDayOfWeek(?string $timezone = null, ?string $locale return $default; } - $first_day = $calendar->getFirstDayOfWeek(); - if ($first_day === false) + // If we're overriding the ICU library then use that value + if (isset($icu_override[$locale]['first_day_of_week'])) { - trigger_error($calendar->getErrorMessage(), E_USER_WARNING); - return $default; + $first_day = $icu_override[$locale]['first_day_of_week']; + // Check that it's a valid day + if (!in_array($first_day, array( + IntlCalendar::DOW_SUNDAY, + IntlCalendar::DOW_MONDAY, + IntlCalendar::DOW_TUESDAY, + IntlCalendar::DOW_WEDNESDAY, + IntlCalendar::DOW_THURSDAY, + IntlCalendar::DOW_FRIDAY, + IntlCalendar::DOW_SATURDAY + ))) + { + throw new Exception('$icu_override[' . $locale . "]['first_day_of_week'] must be in the range [1..7]"); + } + } + // Otherwise just get the standard value from ICU + else + { + $first_day = $calendar->getFirstDayOfWeek(); + if ($first_day === false) { + trigger_error($calendar->getErrorMessage(), E_USER_WARNING); + return $default; + } } return $first_day - 1; // IntlCalendar::DOW_SUNDAY = 1, so we need to subtract 1 diff --git a/web/systemdefaults.inc.php b/web/systemdefaults.inc.php index 70c8561134..dbb37504f6 100644 --- a/web/systemdefaults.inc.php +++ b/web/systemdefaults.inc.php @@ -726,6 +726,26 @@ ); +/*************** + * ICU overrides + * *************/ + +// Sometimes we may want to override the standard ICU library settings, +// for example if the ICU library on the server is out of date and can't +// be updated. This can be done by setting: +// +// $icu_override[]['first_day_of_week'] and/or +// $icu_override[]['minimal_days_in_first_week'] +// +// where is a valid locale in BCP 47 format and both settings take +// integer values in the range 1..7 (IntlCalendar days start with Sunday = 1). + +// For example: +// +// $icu_override['en-AU']['first_day_of_week'] = 2; // Monday +// $icu_override['en-AU']['minimal_days_in_first_week'] = 1; + + /************************ * Miscellaneous settings ************************/