Skip to content

Relative date display is off by one day for users west of UTC #19634

@matthew-petty

Description

@matthew-petty

Bug Description

When a DATE field is set to display in RELATIVE format, the displayed value can be off by one day depending on the user's timezone. For example, setting a date to tomorrow shows "Today" instead of "Tomorrow."

Root Cause

In formatDateISOStringToRelativeDate.ts, the ISO date string is parsed with new Date(isoDate). DATE field values are stored as plain date strings (e.g. "2026-04-14") with no time or timezone component. Per the ECMAScript spec, new Date("2026-04-14") interprets a date-only ISO string as UTC midnight, producing 2026-04-14T00:00:00.000Z.

However, the date-fns functions used afterward (isToday, isTomorrow, isYesterday, differenceInDays) all compare against the browser's local timezone. For users west of UTC, UTC midnight on April 14 falls on the evening of April 13 in local time. This shifts the relative comparison by a day.

Steps to Reproduce

  1. Set your system timezone to any timezone west of UTC (e.g. US Eastern, US Pacific)
  2. Create or open a record with a DATE field
  3. Configure that field to use the RELATIVE display format
  4. Set the date to tomorrow's date
  5. Observe that it displays "Today" instead of "Tomorrow"

Expected Behavior

A date set to tomorrow should display "Tomorrow" regardless of the user's timezone.

Suggested Fix

In formatDateISOStringToRelativeDate.ts, parse date-only strings as local midnight instead of UTC midnight:

// For date-only strings (yyyy-MM-dd), append T00:00:00 (no Z)
// to force local-time parsing instead of the spec's default UTC interpretation
const targetDate = isoDate.length === 10
  ? new Date(isoDate + 'T00:00:00')
  : new Date(isoDate);

Appending T00:00:00 without a trailing Z causes the Date constructor to use local time, so the date stays on the correct calendar day.

Note that the rest of Twenty's date pipeline handles this correctly. The USER_SETTINGS and CUSTOM format branches both use formatInTimeZone with an explicit timezone parameter. The RELATIVE branch is the only path where a bare new Date(isoDate) is used without timezone handling.

Affected File

packages/twenty-front/src/modules/localization/utils/formatDateISOStringToRelativeDate.ts (line 22)

Metadata

Metadata

Assignees

Labels

Type

Projects

Status

🔖 Planned

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions