Skip to content

Commit

Permalink
feat: allow different cp timezone from app timezone
Browse files Browse the repository at this point in the history
  • Loading branch information
florianbrinkmann committed Jan 22, 2025
1 parent c45d71f commit 75ff9cc
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 11 deletions.
19 changes: 19 additions & 0 deletions config/system.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,25 @@

'date_format' => 'F jS, Y',

/*
|--------------------------------------------------------------------------
| Client Timezone
|--------------------------------------------------------------------------
|
| If specified, this timezone is used as the timezone for visible date and
| time values in the control panel and in Antlers. That allows you to keep
| the app timezone in UTC while having, for example, the `Europe/Berlin`
| timezone for the control panel.
|
| That means, if you publish an entry at 2024-05-22 10:15 with the
| client timezone being set to `Europe/Berlin` and the app timezone being
| set to `UTC`, the entry date will be 2024-05-22 08:15 internally, but
| displayed as 2024-05-22 10:15 in the control panel and in antlers.
|
*/

'client_timezone' => null,

/*
|--------------------------------------------------------------------------
| Default Character Set
Expand Down
9 changes: 9 additions & 0 deletions src/Data/AbstractAugmented.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Statamic\Data;

use Carbon\Carbon;
use Statamic\Contracts\Data\Augmented;
use Statamic\Fields\Value;
use Statamic\Statamic;
Expand Down Expand Up @@ -55,6 +56,14 @@ private function transientValue($key)
$value->setFieldtype($deferred->fieldtype());
$value->setAugmentable($deferred->augmentable());

if ($deferred->raw() instanceof Carbon) {
$clientTimezone = config('statamic.system.client_timezone');
$appTimezone = config('app.timezone');
if ($clientTimezone && $clientTimezone !== $appTimezone) {
$deferred->raw()->setTimezone($clientTimezone);
}
}

return $deferred->raw();
};

Expand Down
43 changes: 32 additions & 11 deletions src/Fieldtypes/Date.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ private function preProcessSingle($value)
$value = $value['start'];
}

$date = $this->parseSaved($value);
$date = $this->parseSaved($value, true);

return $this->splitDateTimeForPreProcessSingle($date);
}
Expand All @@ -168,8 +168,8 @@ private function preProcessRange($value)
}

return $this->splitDateTimeForPreProcessRange([
'start' => $this->parseSaved($value['start'])->format($vueFormat),
'end' => $this->parseSaved($value['end'])->format($vueFormat),
'start' => $this->parseSaved($value['start'], true)->format($vueFormat),
'end' => $this->parseSaved($value['end'], true)->format($vueFormat),
]);
}

Expand Down Expand Up @@ -221,14 +221,28 @@ private function processDateTime($value)
{
$date = Carbon::parse($value);

return $this->formatAndCast($date, $this->saveFormat());
return $this->formatAndCast($this->convertTimezoneForSave($date), $this->saveFormat());
}

private function processDateTimeEndOfDay($value)
{
$date = Carbon::parse($value)->endOfDay();

return $this->formatAndCast($date, $this->saveFormat());
return $this->formatAndCast($this->convertTimezoneForSave($date), $this->saveFormat());
}

private function convertTimezoneForSave(Carbon $date): Carbon
{
$clientTimezone = config('statamic.system.client_timezone');
$appTimezone = config('app.timezone');
if (! $clientTimezone || $clientTimezone === $appTimezone) {
return $date;
}

// Date has the app timezone set, so we need to shift that to the CP timezone first without modifying the time.
return $date
->shiftTimezone($clientTimezone)
->setTimezone($appTimezone);
}

public function preProcessIndex($value)
Expand All @@ -244,8 +258,8 @@ public function preProcessIndex($value)
$value = ['start' => $value, 'end' => $value];
}

$start = $this->parseSaved($value['start'])->format($this->indexDisplayFormat());
$end = $this->parseSaved($value['end'])->format($this->indexDisplayFormat());
$start = $this->parseSaved($value['start'], true)->format($this->indexDisplayFormat());
$end = $this->parseSaved($value['end'], true)->format($this->indexDisplayFormat());

return $start.' - '.$end;
}
Expand All @@ -255,7 +269,7 @@ public function preProcessIndex($value)
$value = $value['start'];
}

return $this->parseSaved($value)->format($this->indexDisplayFormat());
return $this->parseSaved($value, true)->format($this->indexDisplayFormat());
}

private function saveFormat()
Expand Down Expand Up @@ -346,13 +360,20 @@ public function toQueryableValue($value)
return $this->augment($value);
}

private function parseSaved($value)
private function parseSaved($value, $convertTz = false)
{
try {
return Carbon::createFromFormat($this->saveFormat(), $value);
$carbon = Carbon::createFromFormat($this->saveFormat(), $value);
} catch (InvalidFormatException|InvalidArgumentException $e) {
return Carbon::parse($value);
$carbon = Carbon::parse($value);
}

$clientTimezone = config('statamic.system.client_timezone');
if ($convertTz && $clientTimezone && $clientTimezone !== config('app.timezone')) {
$carbon->setTimezone($clientTimezone);
}

return $carbon;
}

public function timeEnabled()
Expand Down

0 comments on commit 75ff9cc

Please sign in to comment.