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
- 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.
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
- 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.
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
- Invalid hour cycle "${hourCycle}"
- Invalid hour cycle "${hourCycle}"
- Invalid hour cycle "${hourCycle}"
- No day of week provided
- No day provided
AI-assisted analysis of ionic-team/ionic-framework@625f9c38ad (2026-08-12).
Data as JSON: /api/errors/3d80c77a973e073b.
Report an issue: GitHub.