{"record":{"id":"3d80c77a973e073b","repo":"ionic-team/ionic-framework","slug":"hour-value-not-found-from-datetimeformat","errorCode":null,"errorMessage":"Hour value not found from DateTimeFormat","messagePattern":"Hour value not found from DateTimeFormat","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"core/src/components/datetime/utils/helpers.ts","lineNumber":50,"sourceCode":"   * option into the locale string. Example: `en-US-u-hc-h23`\n   */\n  const formatted = new Intl.DateTimeFormat(locale, { hour: 'numeric' });\n  const options = formatted.resolvedOptions();\n  if (options.hourCycle !== undefined) {\n    return options.hourCycle;\n  }\n\n  /**\n   * If hourCycle is not specified (either through lack\n   * of browser support or locale information) then fall\n   * back to this slower hourCycle check.\n   */\n  const date = new Date('5/18/2021 00:00');\n  const parts = formatted.formatToParts(date);\n  const hour = parts.find((p) => p.type === 'hour');\n\n  if (!hour) {\n    throw new Error('Hour value not found from DateTimeFormat');\n  }\n\n  /**\n   * Midnight for h11 starts at 0:00am\n   * Midnight for h12 starts at 12:00am\n   * Midnight for h23 starts at 00:00\n   * Midnight for h24 starts at 24:00\n   */\n  switch (hour.value) {\n    case '0':\n      return 'h11';\n    case '12':\n      return 'h12';\n    case '00':\n      return 'h23';\n    case '24':\n      return 'h24';\n    default:","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/ionic-team/ionic-framework/blob/625f9c38ad8c5db8a6c12df5c1622a36da90f9e3/core/src/components/datetime/utils/helpers.ts#L32-L68","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass an explicit hourCycle (or preferredHours) prop so ion-datetime never enters the detection fallback.","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.","In jsdom tests, polyfill/stub Intl.DateTimeFormat.formatToParts to return an hour part, or upgrade jsdom.","Validate the locale string (well-formed BCP-47) before assigning it to the locale prop."],"exampleFix":"// before (tests/SSR hit the detection fallback and throw)\n<ion-datetime locale={userLocale}></ion-datetime>\n\n// after (skip detection entirely)\n<ion-datetime locale={userLocale} hour-cycle=\"h12\"></ion-datetime>","handlingStrategy":"fallback","validationCode":"// Before relying on Intl detection, probe it:\nfunction intlCanDetectHour(locale: string): boolean {\n  try {\n    const parts = new Intl.DateTimeFormat(locale, { hour: 'numeric' }).formatToParts(new Date('5/18/2021 00:00'));\n    return parts.some((p) => p.type === 'hour');\n  } catch {\n    return false;\n  }\n}\n// if false, pass an explicit hourCycle prop","typeGuard":"function hasIntlHourPart(locale: string): boolean {\n  try {\n    const f = new Intl.DateTimeFormat(locale, { hour: 'numeric' });\n    return f.formatToParts(new Date(2021, 4, 18, 0, 0)).some((p) => p.type === 'hour');\n  } catch {\n    return false;\n  }\n}","tryCatchPattern":"try {\n  cycle = getHourCycle(locale);\n} catch (e) {\n  if (e instanceof Error && /Hour value not found/.test(e.message)) {\n    cycle = 'h12'; // explicit fallback\n  } else { throw e; }\n}","preventionTips":["Run Node/SSR with full ICU (--with-intl=full-icu or full-icu package).","In jsdom tests, pass an explicit hourCycle prop or stub Intl.formatToParts.","Always pass an explicit hourCycle when locale data is uncertain."],"tags":["datetime","hour-cycle","intl","locale","ssr","test-environment","runtime"],"backgroundTag":null,"analyzedSha":"625f9c38ad8c5db8a6c12df5c1622a36da90f9e3","analyzedAt":"2026-08-12T16:00:25.413Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}