Incorrect Payment Dates displayed in customer portal

Setup

Self-hosted

Version

v5.13.30

Environment

  • PHP 8.2, MySQL, LiteSpeed
  • Company timezone: America/New_York (EDT, UTC−4)

Describe the bug

In the client portal, a payment’s date displays one day earlier than the stored date. The payments.date value is stored correctly, but the portal renders this date-only value as if it were UTC midnight, then converts it to the company timezone — shifting it into the previous calendar day.

To Reproduce

  1. Set the company timezone to a negative-UTC-offset zone (e.g. America/New_York).
  2. Record a payment dated 2026-08-12 (e.g. an online/gateway payment made in the afternoon, local time).
  3. Log in to the client portal as that client and view the payment (payments list / payment detail).

Expected behavior

The client portal shows the payment date as Aug 12, 2026, matching the stored payments.date and the admin/database.

Actual behavior

The client portal shows Aug 11, 2026 (one day early).

Data confirming the stored value is correct

  • payments.date = 2026-08-12
  • payments.created_at (UTC) = 2026-08-12 19:47:09 = 2026-08-12 15:47 America/New_York
  • Company timezone_id = 15 (America/New_York)
  • Admin UI and database both show Aug 12 — only the client portal shows Aug 11.

Suspected root cause

A date-only field (payments.date, no time component) is parsed as 2026-08-12 00:00:00 UTC and then converted to the company timezone (−4h) → 2026-08-11 20:00, which formats as Aug 11. Date-only fields should be formatted without timezone conversion.

Impact

Customer-facing: clients see payment dates a day early on the portal. Data, reporting, totals, and paid status are all correct — only the portal display is affected. Impacts any self-hosted instance in a behind-UTC timezone.

Additional context

  • Reproduces on the latest release (5.13.30).
  • Switching the company timezone to UTC avoids the date shift but makes all time displays 4 hours off, so it isn’t a viable workaround.

Hi,

Thank you for the detailed error report, please create an issue on GitHub to track the problem.