You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Date fields shift by timezone offset on every resource save when PHP date.timezone is not UTC #2431
Evolution CMS 3.5.7 and 3.3 (reproduced on both) / PHP 8.3 / date.timezone = Asia/Tokyo (default on most Japanese shared hosting: Xserver, Heteml, etc.)
Steps to reproduce:
Set date.timezone = "Asia/Tokyo" in php.ini
Edit any resource, set pub_date to 2026/09/01 10:00:00, save
Reopen the resource: field shows 2026/09/01 01:00:00 (−9h)
Save again without changes: value shifts another −9h (compounds on every save). unpub_date behaves identically; publishedon inherits the drift via its copy from pub_date. createdon/editedon are unaffected (no form round-trip).
Cause: Asymmetric timezone handling between the two converters in core/src/Core.php:
toTimeStamp() uses mktime() — interpreted in the runtime timezone (line ~4797)
toDateFormat() uses Carbon::createFromTimestamp($timestamp, 'UTC') — fixed to UTC (line ~4740)
Each open→save round-trip therefore subtracts the TZ offset. Not reproducible when date.timezone=UTC because both paths coincide.
Suggested fix: use gmmktime() in toTimeStamp() (consistent with the UTC-fixed display path), or pass date_default_timezone_get() to Carbon in toDateFormat().
Thanks for the detailed report. I can reproduce the asymmetric conversion path from the code: toDateFormat() formats timestamps in UTC while toTimeStamp() currently uses the runtime timezone through mktime().
I am taking this into work and will keep the fix focused on making the resource date round-trip stable across non-UTC PHP timezones.
Confirmed from the code path: toDateFormat() renders timestamps in UTC while toTimeStamp() used PHP runtime timezone parsing through mktime(). With Asia/Tokyo, that makes a manager date lose 9 hours on each open/save/open round trip.
Root Cause
The display and parse sides used different timezone bases: UTC for display, runtime PHP timezone for parse.
Validation
Opened PR #2435 with a focused fix and regression coverage.
Validated locally with:
git diff --check
wsl php -l core/src/Core.php
wsl php -l core/tests/Unit/CoreTest.php
WSL smoke test confirming 2026/09/01 10:00:00 stays stable through two Asia/Tokyo conversions.
Full Pest was not run locally because vendor/bin/pest is not present in the current local core/vendor.
Risk
Low. The change is scoped to the shared date parser and aligns it with the existing UTC display path.
Result: pub_date / unpub_date now survive repeated open→save round-trips with no drift. publishedon correctly inherits the stable value.
One practical note for anyone reading this later: after the fix, stored timestamps are "wall-clock time carved as UTC", so any custom snippet reading these raw values should format them with gmdate() / Carbon(…, 'UTC') rather than date() — otherwise the display shifts by the runtime TZ offset on non-UTC servers (this also applies to date formatting in third-party snippets). Once we aligned our snippets to gmdate(), everything is consistent across UTC and Asia/Tokyo environments.
Thanks again — this fixes a long-standing trap for every Evo user on Japanese hosting defaults.
Activity
MiddleSokilAI commentedon Aug 27, 2026
Thanks for the detailed report. I can reproduce the asymmetric conversion path from the code:
toDateFormat()formats timestamps in UTC whiletoTimeStamp()currently uses the runtime timezone throughmktime().I am taking this into work and will keep the fix focused on making the resource date round-trip stable across non-UTC PHP timezones.
MiddleSokilAI commentedon Aug 27, 2026
Repro
Confirmed from the code path:
toDateFormat()renders timestamps in UTC whiletoTimeStamp()used PHP runtime timezone parsing throughmktime(). WithAsia/Tokyo, that makes a manager date lose 9 hours on each open/save/open round trip.Root Cause
The display and parse sides used different timezone bases: UTC for display, runtime PHP timezone for parse.
Validation
Opened PR #2435 with a focused fix and regression coverage.
Validated locally with:
git diff --checkwsl php -l core/src/Core.phpwsl php -l core/tests/Unit/CoreTest.php2026/09/01 10:00:00stays stable through twoAsia/Tokyoconversions.Full Pest was not run locally because
vendor/bin/pestis not present in the current localcore/vendor.Risk
Low. The change is scoped to the shared date parser and aligns it with the existing UTC display path.
fix(core): keep resource date round trips timezone-stable (#2431)
Merge pull request #2435 from MiddleSokilAI/middleSokil/2431-date-tim…
andonebz commentedon Aug 27, 2026
Thank you for the incredibly fast turnaround — reported, root-caused, and merged within hours!
Confirmed the fix on our production environment:
One practical note for anyone reading this later: after the fix, stored timestamps are "wall-clock time carved as UTC", so any custom snippet reading these raw values should format them with gmdate() / Carbon(…, 'UTC') rather than date() — otherwise the display shifts by the runtime TZ offset on non-UTC servers (this also applies to date formatting in third-party snippets). Once we aligned our snippets to gmdate(), everything is consistent across UTC and Asia/Tokyo environments.
Thanks again — this fixes a long-standing trap for every Evo user on Japanese hosting defaults.