Skip to content

Commit 5d5f28b

Browse files
committed
“Time Zone” user preference
Resolves #8518
1 parent 99cec49 commit 5d5f28b

6 files changed

Lines changed: 48 additions & 5 deletions

File tree

CHANGELOG-WIP.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
- Entries’ “Entry type settings” and “Section settings” action menu items are now only shown for element edit screens’ primary action menus.
1616
- Category indexes can now have “Group” columns. ([#18553](https://github.com/craftcms/cms/discussions/18553))
1717
- Element slideouts now automatically refresh when the same element is updated in another tab/slideout. ([#18625](https://github.com/craftcms/cms/pull/18625))
18+
- Added the “Time Zone” user preference. ([#8518](https://github.com/craftcms/cms/discussions/8518))
1819

1920
### Administration
2021
- Time fields’ “Max Time” settings can now be set to an earlier time than “Min Time”, for overnight time ranges. ([#18575](https://github.com/craftcms/cms/pull/18575))

src/base/ApplicationTrait.php

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,11 +1585,13 @@ private function _preInit(): void
15851585
$this->getRequest();
15861586
$this->getLog();
15871587

1588+
$isCpRequest = $this->getRequest()->getIsCpRequest();
1589+
15881590
// Set the timezone
1589-
$this->_setTimeZone();
1591+
$this->_setTimeZone($isCpRequest);
15901592

15911593
// Set the language
1592-
$this->updateTargetLanguage();
1594+
$this->updateTargetLanguage($isCpRequest);
15931595

15941596
// Register the variable dumper
15951597
VarDumper::setHandler(function($var) {
@@ -1644,9 +1646,24 @@ private function _postInit(): void
16441646
/**
16451647
* Sets the system timezone.
16461648
*/
1647-
private function _setTimeZone(): void
1649+
private function _setTimeZone(bool $useUserTz): void
16481650
{
1649-
$timeZone = $this->getConfig()->getGeneral()->timezone ?? $this->getProjectConfig()->get('system.timeZone');
1651+
$timeZone = null;
1652+
1653+
if ($useUserTz) {
1654+
// If the user is logged in *and* has a preferred time zone, use that
1655+
// (don't actually try to fetch the user, as plugins haven't been loaded yet)
1656+
/** @var UserSession $user */
1657+
$user = $this->getUser();
1658+
$id = Session::get($user->idParam);
1659+
if ($id) {
1660+
$timeZone = $this->getUsers()->getUserPreference($id, 'timeZone');
1661+
}
1662+
}
1663+
1664+
if (!$timeZone) {
1665+
$timeZone = $this->getConfig()->getGeneral()->timezone ?? $this->getProjectConfig()->get('system.timeZone');
1666+
}
16501667

16511668
if ($timeZone) {
16521669
$this->setTimeZone(App::parseEnv($timeZone));

src/controllers/UsersController.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
use craft\web\UploadedFile;
5252
use craft\web\View;
5353
use DateTime;
54+
use DateTimeZone;
5455
use Throwable;
5556
use yii\base\Exception;
5657
use yii\base\InvalidArgumentException;
@@ -1361,10 +1362,17 @@ public function actionPreferences(): Response
13611362
$userLocale = Craft::$app->getConfig()->getGeneral()->defaultCpLocale;
13621363
}
13631364

1365+
// time zone
1366+
$timeZone = new DateTimeZone(Craft::$app->getTimeZone());
1367+
$offsetDate = (new DateTime())->setTimezone(new DateTimeZone('UTC'));
1368+
$transition = $timeZone->getTransitions($offsetDate->getTimestamp(), $offsetDate->getTimestamp());
1369+
$timeZoneAbbr = $transition[0]['abbr'];
1370+
13641371
$response->action('users/save-preferences');
13651372
$response->contentTemplate('users/_preferences', compact(
13661373
'userLanguage',
13671374
'userLocale',
1375+
'timeZoneAbbr',
13681376
));
13691377

13701378
return $response;
@@ -1385,10 +1393,15 @@ public function actionSavePreferences(): Response
13851393
if ($preferredLocale === '__blank__') {
13861394
$preferredLocale = null;
13871395
}
1396+
$timeZone = $this->request->getBodyParam('timeZone', $user->getPreference('timezone')) ?: null;
1397+
if ($timeZone === '__blank__') {
1398+
$timeZone = null;
1399+
}
13881400
$preferences = [
13891401
'language' => $this->request->getBodyParam('preferredLanguage', $user->getPreference('language')),
13901402
'locale' => $preferredLocale,
13911403
'weekStartDay' => $this->request->getBodyParam('weekStartDay', $user->getPreference('weekStartDay')),
1404+
'timeZone' => $timeZone,
13921405
'useShapes' => (bool)$this->request->getBodyParam('useShapes', $user->getPreference('useShapes')),
13931406
'underlineLinks' => (bool)$this->request->getBodyParam('underlineLinks', $user->getPreference('underlineLinks')),
13941407
'disableAutofocus' => $this->request->getBodyParam('disableAutofocus', $user->getPreference('disableAutofocus')),

src/templates/_includes/forms/timeZone.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{% set id = id ?? "timezone#{random()}" %}
22

33
{% include '_includes/forms/selectize' with {
4-
options: craft.cp.getTimeZoneOptions(offsetDate ?? null),
4+
options: options ?? craft.cp.getTimeZoneOptions(offsetDate ?? null),
55
inputAttributes: {
66
aria: {
77
label: 'Time Zone'|t('app'),

src/templates/users/_preferences.twig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@
3333
options: craft.app.locale.getWeekDayNames(),
3434
value: currentUser.getPreference('weekStartDay', craft.app.config.general.defaultWeekStartDay)
3535
}) }}
36+
37+
{{ forms.timeZoneField({
38+
label: 'Time Zone'|t('app'),
39+
id: 'time-zone',
40+
name: 'timeZone',
41+
options: [
42+
{label: 'System time zone ({abbr})'|t('app', {abbr: timeZoneAbbr}), value: '__blank__'},
43+
...craft.cp.getTimeZoneOptions(offsetDate ?? null),
44+
],
45+
value: currentUser.getPreference('timeZone'),
46+
}) }}
3647
</div>
3748

3849
<hr>

src/translations/en/app.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,6 +1664,7 @@
16641664
'System Name' => 'System Name',
16651665
'System Report' => 'System Report',
16661666
'System Status' => 'System Status',
1667+
'System time zone ({abbr})' => 'System time zone ({abbr})',
16671668
'System' => 'System',
16681669
'Table Columns' => 'Table Columns',
16691670
'Table' => 'Table',

0 commit comments

Comments
 (0)