diff --git a/web/functions_table.inc b/web/functions_table.inc index 9c49ec70f4..f85ee611af 100644 --- a/web/functions_table.inc +++ b/web/functions_table.inc @@ -1586,6 +1586,7 @@ function month_room_table_innerhtml(string $view, int $view_all, int $year, int global $weekstarts, $view_week_number, $show_plus_link, $monthly_view_entries_details; global $enable_periods, $morningstarts, $morningstarts_minutes; global $prevent_booking_on_holidays, $prevent_booking_on_weekends; + global $timezone; // Check that we've got a valid, enabled room if (is_null(get_room_name($room)) || !is_visible($room)) @@ -1668,8 +1669,8 @@ function month_room_table_innerhtml(string $view, int $view_all, int $year, int 'area' => $area, 'room' => $room); - // If it's a Monday (the start of the ISO week), show the week number - if ($view_week_number && (($weekcol + $weekstarts)%DAYS_PER_WEEK == 1)) + // If it's the first day of the week, show the week number + if ($view_week_number && (($weekcol + $weekstarts)%DAYS_PER_WEEK == DateTime::firstDayOfWeek($timezone, get_mrbs_locale()))) { $vars['view'] = 'week'; $query = http_build_query($vars, '', '&'); diff --git a/web/index.php b/web/index.php index c7cc0d4187..38542e18dc 100644 --- a/web/index.php +++ b/web/index.php @@ -329,7 +329,7 @@ function get_calendar_nav(string $view, int $view_all, int $year, int $month, in function get_date_heading(string $view, int $year, int $month, int $day) : string { - global $datetime_formats, $display_timezone, + global $datetime_formats, $display_timezone, $timezone, $weekstarts, $view_week_number; $html = ''; @@ -344,9 +344,9 @@ function get_date_heading(string $view, int $year, int $month, int $day) : strin break; case 'week': - // Display the week number if required, provided the week starts on Monday, - // otherwise it's spanning two ISO weeks and doesn't make sense. - if ($view_week_number && ($weekstarts == 1)) + // Display the week number if required, provided the MRBS week starts on the first day + // of the week, otherwise it's spanning two weeks and doesn't make sense. + if ($view_week_number && ($weekstarts == DateTime::firstDayOfWeek($timezone, get_mrbs_locale()))) { $html .= '' . get_vocab('week_number', datetime_format($datetime_formats['week_number'], $time)) . diff --git a/web/js/datepicker.js.php b/web/js/datepicker.js.php index 1e5b3de761..79576fd703 100644 --- a/web/js/datepicker.js.php +++ b/web/js/datepicker.js.php @@ -337,8 +337,8 @@ function (date) { } else { - - config.weekNumbers = ; + + config.weekNumbers = ; } flatpickr('input[type="date"]', config); diff --git a/web/lib/MRBS/DateTime.php b/web/lib/MRBS/DateTime.php index 4d57107b98..4f6b3f9783 100644 --- a/web/lib/MRBS/DateTime.php +++ b/web/lib/MRBS/DateTime.php @@ -2,6 +2,7 @@ declare(strict_types=1); namespace MRBS; +use IntlCalendar; use MRBS\ICalendar\RFC5545; use UnexpectedValueException; @@ -33,6 +34,39 @@ public static function createFromFormat($format, $datetime, ?\DateTimeZone $time return new static($parent->format('Y-m-d\TH:i:s.u'), $parent->getTimezone()); } + + // Returns the first day of the week (0 = Sunday) for a given timezone and locale. + // If $timezone is null, the default timezone will be used. + // If $locale is null, the default locale will be used. + // The method relies on the IntlCalendar class. If it doesn't exist, or there's an error, + // the method assumes that the week starts on a Monday. + public static function firstDayOfWeek(?string $timezone = null, ?string $locale = null) : int + { + $default = 1; // Monday + + if (!class_exists('\\IntlCalendar')) + { + return $default; + } + + $calendar = IntlCalendar::createInstance($timezone, $locale); + if (!isset($calendar)) + { + trigger_error("Could not create IntlCalendar for timezone '$timezone' and locale '$locale'", E_USER_WARNING); + return $default; + } + + $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 + } + + // TODO: replace usages of byday_to_day() with this method // TODO: make $relative an object? // Sets the day to $relative, where relative is an RFC5545 relative day, diff --git a/web/systemdefaults.inc.php b/web/systemdefaults.inc.php index aa6b0f4bb9..d05ba7dfbf 100644 --- a/web/systemdefaults.inc.php +++ b/web/systemdefaults.inc.php @@ -436,11 +436,18 @@ // of 12. $monthly_view_entries_details = "both"; -// To show ISO week numbers in the main calendar, set this to true. The week -// numbers are only displayed if you set $weekstarts to 1 (Monday), i.e. the -// start of the ISO week. +// To show week numbers in the main calendar, set this to true. The week +// numbers are only displayed if you set $weekstarts to start on the first +// day of the week in your locale and area's timezone. (This assumes that +// the PHP IntlCalendar class is available; if not, the week is assumed to +// start on Mondays, ie the ISO stanard.) $view_week_number = false; +// To display week numbers in the mini-calendars, set this to true. The week +// numbers are only displayed if you set $weekstarts to the start of the week. +// See the comment about when the week starts above. +$mincals_week_numbers = false; + // Whether or not the mini-calendars are displayed. (Note that mini-calendars are only // displayed anyway if the window is wide enough.) $display_mincals = true; @@ -450,11 +457,6 @@ // provided the window is high enough. $display_mincals_above = false; -// To display week numbers in the mini-calendars, set this to true. The week -// numbers are only displayed if you set $weekstarts to 1 (Monday), i.e. the -// start of the ISO week. -$mincals_week_numbers = false; - // To display the endtime in the slot description, eg '09:00-09:30' instead of '09:00', set // this to true. $show_slot_endtime = false;