Zeitzone Europe/Berlin: unnoetige UTC-Konvertierung entfernt

Beim Speichern/Veroeffentlichen waren Termine 2 Stunden versetzt: die
App-Zeitzone stand auf UTC, Termine wurden nach UTC umgerechnet, aber
published_at roh angezeigt.

- config/app.php: timezone UTC -> Europe/Berlin
- PressRelease: DISPLAY_TIMEZONE + setTimezone-Umrechnung entfernt
- Admin-/Customer-Formulare: scheduledAtUtc() -> resolveScheduledAt(),
  parst direkt in App-Zeitzone; Edit-Hydration ohne setTimezone
- ProofPdfRenderer + Boost-Anzeige: setTimezone entfernt
- Tests an verschiebungsfreies Verhalten angepasst

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-06-18 12:40:19 +00:00
parent 326ff9b2a0
commit 624fca68a8
12 changed files with 56 additions and 68 deletions

View file

@ -108,8 +108,7 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung bearbeiten')] cl
?? $this->defaultContactIdFor((int) $pr->company_id);
if ($pr->scheduled_at) {
// DB-Wert ist UTC; für die Eingabefelder nach Europe/Berlin wandeln.
$scheduledAt = $pr->scheduled_at->copy()->setTimezone(PressRelease::DISPLAY_TIMEZONE);
$scheduledAt = $pr->scheduled_at;
$this->publishMode = 'scheduled';
$this->scheduledAt = $scheduledAt->format('Y-m-d\TH:i');
$this->scheduledDate = $scheduledAt->format('Y-m-d');
@ -289,7 +288,7 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung bearbeiten')] cl
// Termin wird in Europe/Berlin erfasst; deshalb hier zeitzonen-
// bewusst prüfen statt über die naive `after:`-Regel.
function (string $attribute, mixed $value, \Closure $fail): void {
$scheduledAt = $this->scheduledAtUtc();
$scheduledAt = $this->resolveScheduledAt();
if ($scheduledAt === null || $scheduledAt->lessThanOrEqualTo(now()->addMinutes(5))) {
$fail(__('Der Veröffentlichungstermin muss mindestens 5 Minuten in der Zukunft liegen.'));
@ -333,16 +332,16 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung bearbeiten')] cl
}
/**
* Wandelt den in Europe/Berlin erfassten Termin in den UTC-Zeitpunkt,
* wie er in der Datenbank gespeichert wird. Null, wenn kein Termin gesetzt.
* Parst den erfassten Termin in der Anwendungs-Zeitzone (Europe/Berlin).
* Null, wenn kein Termin gesetzt ist.
*/
protected function scheduledAtUtc(): ?\Carbon\Carbon
protected function resolveScheduledAt(): ?\Carbon\Carbon
{
if (blank($this->scheduledAt)) {
return null;
}
return \Carbon\Carbon::parse($this->scheduledAt, PressRelease::DISPLAY_TIMEZONE)->utc();
return \Carbon\Carbon::parse($this->scheduledAt);
}
protected function validateScheduledAtWhenReady(): void
@ -353,7 +352,7 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung bearbeiten')] cl
$this->resetErrorBag('scheduledAt');
$scheduledAt = $this->scheduledAtUtc();
$scheduledAt = $this->resolveScheduledAt();
if ($scheduledAt === null || $scheduledAt->lessThanOrEqualTo(now()->addMinutes(5))) {
$this->addError('scheduledAt', __('Der Veröffentlichungstermin muss mindestens 5 Minuten in der Zukunft liegen.'));
@ -435,7 +434,7 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung bearbeiten')] cl
'keywords' => $this->keywords ?: null,
'backlink_url' => $this->backlinkUrl ?: null,
'scheduled_at' => $this->publishMode === 'scheduled'
? $this->scheduledAtUtc()
? $this->resolveScheduledAt()
: null,
'embargo_at' => null,
]);