ionic-team/ionic-framework · error · Error

Hour value not found from DateTimeFormat

Error message

Hour value not found from DateTimeFormat

What it means

Thrown by getHourCycle() in helpers.ts on its slow fallback path. When neither an explicit hourCycle nor Intl.DateTimeFormat(...).resolvedOptions().hourCycle is available, ion-datetime formats a known date and reads the 'hour' part back. If Intl produces no hour part at all, this throws. It is fundamentally an environment capability problem, not a logic error in app code.

Source

Thrown at core/src/components/datetime/utils/helpers.ts:50

   * option into the locale string. Example: `en-US-u-hc-h23`
   */
  const formatted = new Intl.DateTimeFormat(locale, { hour: 'numeric' });
  const options = formatted.resolvedOptions();
  if (options.hourCycle !== undefined) {
    return options.hourCycle;
  }

  /**
   * If hourCycle is not specified (either through lack
   * of browser support or locale information) then fall
   * back to this slower hourCycle check.
   */
  const date = new Date('5/18/2021 00:00');
  const parts = formatted.formatToParts(date);
  const hour = parts.find((p) => p.type === 'hour');

  if (!hour) {
    throw new Error('Hour value not found from DateTimeFormat');
  }

  /**
   * Midnight for h11 starts at 0:00am
   * Midnight for h12 starts at 12:00am
   * Midnight for h23 starts at 00:00
   * Midnight for h24 starts at 24:00
   */
  switch (hour.value) {
    case '0':
      return 'h11';
    case '12':
      return 'h12';
    case '00':
      return 'h23';
    case '24':
      return 'h24';
    default:

View on GitHub (pinned to 625f9c38ad)

Solutions

  1. Pass an explicit hourCycle (or preferredHours) prop so ion-datetime never enters the detection fallback.
  2. Run Node with full ICU data: rebuild/install full-icu, or set NODE_ICU_DATA, or use a Node build with --with-intl=full-icu.
  3. In jsdom tests, polyfill/stub Intl.DateTimeFormat.formatToParts to return an hour part, or upgrade jsdom.
  4. Validate the locale string (well-formed BCP-47) before assigning it to the locale prop.

Example fix

// before (tests/SSR hit the detection fallback and throw)
<ion-datetime locale={userLocale}></ion-datetime>

// after (skip detection entirely)
<ion-datetime locale={userLocale} hour-cycle="h12"></ion-datetime>
Defensive patterns

Strategy: fallback

Validate before calling

// Before relying on Intl detection, probe it:
function intlCanDetectHour(locale: string): boolean {
  try {
    const parts = new Intl.DateTimeFormat(locale, { hour: 'numeric' }).formatToParts(new Date('5/18/2021 00:00'));
    return parts.some((p) => p.type === 'hour');
  } catch {
    return false;
  }
}
// if false, pass an explicit hourCycle prop

Type guard

function hasIntlHourPart(locale: string): boolean {
  try {
    const f = new Intl.DateTimeFormat(locale, { hour: 'numeric' });
    return f.formatToParts(new Date(2021, 4, 18, 0, 0)).some((p) => p.type === 'hour');
  } catch {
    return false;
  }
}

Try / catch

try {
  cycle = getHourCycle(locale);
} catch (e) {
  if (e instanceof Error && /Hour value not found/.test(e.message)) {
    cycle = 'h12'; // explicit fallback
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling ion-datetime (or getHourCycle directly) in an environment whose Intl.DateTimeFormat does not emit an hour token for the given locale and options. Seen in minimal jsdom/Node builds, very old engines, or non-standard locales where the 'numeric' hour formatter yields no hour field.

Common situations: Jest/jsdom tests that use a fake or limited Intl; SSR on a Node build compiled without full-icu; exotic or malformed locale strings passed to locale prop; headless browsers with stripped Intl data.

Related errors


AI-assisted analysis of ionic-team/ionic-framework@625f9c38ad (2026-08-12). Data as JSON: /api/errors/3d80c77a973e073b. Report an issue: GitHub.