SaketSingh

SitecoreAI: Fix Event Timezone Issues with Next.js

šŸ‘¤Saket Singh
|
šŸ“…October 20, 2026
|
ā±ļø7 min read
SitecoreAI: Fix Event Timezone Issues with Next.js

While working on a calendar events feature for a healthcare website, I encountered a frustrating bug that many Sitecore developers face.

The problem looked like this:

  • Author enters event time: 10:00 AM - 11:30 AM
  • Local development shows: 10:00 AM - 11:30 AM (correct)
  • Production shows: 5:00 AM - 6:30 AM (wrong)

The Sitecore Content Editor showed the correct time. The local environment displayed it correctly. But production? Completely wrong.

This guide explains why this happens and how to fix it properly in SitecoreAI (XM Cloud) with a Next.js rendering host.


šŸ” Understanding Why Times Display Differently Across Environments

The root cause involves two factors working against each other:

Factor 1: Sitecore's ServerTimeZone Setting

When Sitecore's ServerTimeZone setting is empty (the default), Sitecore uses the server's OS timezone to interpret datetime inputs.
Environment Server Timezone Author Enters 10:00 AM Stored as UTC
Local (India) IST (UTC+5:30) 10:00 AM IST 04:30 UTC
Production (Cloud) UTC 10:00 AM UTC 10:00 UTC
SitecoreAI (XM Cloud) servers run in UTC. So when an author enters 10:00 AM, Sitecore interprets it as 10:00 UTC and stores T100000Z.

Factor 2: Frontend Timezone Conversion

The frontend typically converts UTC to a display timezone (like Eastern Time):

  • T100000Z (10:00 UTC) converts to 5:00 AM ET

But for a 10:00 AM Eastern event, we need:

  • T150000Z (15:00 UTC) which converts to 10:00 AM ET

The mismatch happens because the author intended Eastern Time, but Sitecore stored it as UTC.


šŸ› ļø The Solution: Fixing the Timezone Issue

āš™ļø Part 1: Configure Sitecore ServerTimeZone

Add the ServerTimeZone setting to ensure all datetime inputs are interpreted consistently:
  • File: App_config/Include/YourProject/SiteSettings.config
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <settings>
      <setting name="ServerTimeZone" value="Eastern Standard Time"></setting>
    </settings>
  </sitecore>
</configuration>

What this does:

  • Author enters 10:00 AM
  • Sitecore interprets as 10:00 AM Eastern Time
  • Sitecore converts and stores as T150000Z (15:00 UTC)
  • Frontend converts back to 10:00 AM ET (correct)
Note: Use the Windows timezone ID (Eastern Standard Time), not the IANA ID. Windows handles daylight saving (EDT/EST) automatically.

šŸ’» Part 2: Create a Shared Frontend Utility

Create a consistent date formatting utility for all event components:

// lib/utils/eventDateHelper.ts
import { parseSitecoreDate } from './helpers';

// Default timezone - used when dictionary entry is missing
export const DEFAULT_EVENT_TIMEZONE = 'America/New_York';

/**
 * Formats a date range for event details display.
 * Output: "Jan 27, 10:00 AM - Jan 27, 11:30 AM" or "Jan 27, 10:00 AM" if no end date
 */
export function formatEventDateRange(
  startDate?: string,
  endDate?: string,
  timeZone?: string
): string {
  if (!startDate) return '';
  const start = parseSitecoreDate(startDate);
  const end = endDate ? parseSitecoreDate(endDate) : undefined;
  if (!start) return '';

  const fmt = (d: Date) =>
    new Intl.DateTimeFormat('en-US', {
      month: 'short',
      day: 'numeric',
      hour: 'numeric',
      minute: '2-digit',
      hour12: true,
      timeZone: timeZone || DEFAULT_EVENT_TIMEZONE,
    }).format(d);

  return end ? `${fmt(start)} - ${fmt(end)}` : fmt(start);
}

/**
 * Formats a single date for event listing display.
 * Output: "2027 - January 27 - 10:00 AM"
 */
export function formatEventDate(dateString: string, timeZone?: string): string {
  if (!dateString) {
    return '';
  }

  try {
    const date = parseSitecoreDate(dateString);

    if (!date || isNaN(date.getTime())) {
      return '';
    }

    const tz = timeZone || DEFAULT_EVENT_TIMEZONE;
    const year = date.toLocaleDateString('en-US', { year: 'numeric', timeZone: tz });
    const month = date.toLocaleDateString('en-US', { month: 'long', timeZone: tz });
    const day = date.toLocaleDateString('en-US', { day: 'numeric', timeZone: tz });
    const time = date.toLocaleTimeString('en-US', {
      hour: 'numeric',
      minute: '2-digit',
      hour12: true,
      timeZone: tz,
    });

    return `${year} - ${month} ${day} - ${time}`;
  } catch (error) {
    console.error('Error formatting date:', error);
    return '';
  }
}

Key implementation details:

  • Uses parseSitecoreDate helper to handle Sitecore's date format
  • Two functions for different display contexts (details vs listing)
  • Graceful handling of missing or invalid dates
  • Intl.DateTimeFormat for timezone-aware formatting

šŸŽ›ļø Making the Timezone Configurable

For flexibility, read the timezone from a Sitecore Dictionary entry:

// In your component
const timeZone = sitecoreContext.dictionary?.['Event_TimeZone'] || DEFAULT_EVENT_TIMEZONE;

const displayTime = formatEventDateRange(startDate, endDate, timeZone);

Configure this Dictionary entry in Sitecore:

Key Value
Event_TimeZone America/New_York

With this in place, content authors can change the display timezone without code changes.


āœ… Post-Deployment Checklist

After deploying the ServerTimeZone configuration:

1.Re-save affected events in Sitecore Content Editor (the stored UTC values need to be recalculated)

2.Verify GraphQL responses show correct UTC values:

  • 10:00 AM ET should store as T150000Z
  • 11:30 AM ET should store as T163000Z

3.Verify frontend display shows the expected times


šŸ”„ Windows vs IANA Timezone IDs

A common source of confusion:

System Format Example
Sitecore/Windows Windows ID Eastern Standard Time
JavaScript IANA ID America/New_York

Both handle daylight saving automatically. Use the correct format for each system.


🚫 Why Not Just Display UTC?

An earlier approach considered displaying raw UTC values with an "ET" label. This was rejected because:

  1. It misleads users (showing UTC labeled as ET)
  2. It breaks when ServerTimeZone is eventually configured
  3. It doesn't solve the root cause

Always fix the data layer first, then handle display consistently.


šŸŽÆ Conclusion

Timezone issues in SitecoreAI (XM Cloud) usually stem from the mismatch between:

  • Where the server runs (UTC in the cloud)
  • What timezone authors intend (often Eastern or local)
  • How the frontend displays dates

The fix requires both:

  1. Server-side: Configure ServerTimeZone to interpret inputs correctly
  2. Client-side: Use Intl.DateTimeFormat with explicit timezone for display

This ensures consistency across all environments and eliminates the "works locally, broken in production" problem.

Happy coding!


Share this post: