ionic-team/ionic-framework · error · Error
Invalid hour cycle "${hourCycle}"
Error message
Invalid hour cycle "${hourCycle}" What it means
Thrown by getHourCycle() on the same Intl fallback path as error 2, but one step further: the hour part was found, yet its string value was not '0', '12', '00', or '24'. Note the message interpolates the optional hourCycle parameter (which is undefined on this path), so it renders as `Invalid hour cycle "undefined"` - a mildly misleading message, since the real offender is hour.value, not hourCycle.
Source
Thrown at core/src/components/datetime/utils/helpers.ts:69
}
/**
* 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:
throw new Error(`Invalid hour cycle "${hourCycle}"`);
}
};
/**
* Determine if the hour cycle uses a 24-hour format.
* Returns true for h23 and h24. Returns false otherwise.
* If you don't know the hourCycle, use getHourCycle above
* and pass the result into this function.
*/
export const is24Hour = (hourCycle: DatetimeHourCycle) => {
return hourCycle === 'h23' || hourCycle === 'h24';
};
/**
* Given a date object, returns the number
* of days in that month.
* Month value begin at 1, not 0.
* i.e. January = month 1.View on GitHub (pinned to 625f9c38ad)
Solutions
- Provide an explicit hourCycle prop to ion-datetime to avoid the heuristic detection entirely.
- Embed the cycle in the locale string using the Unicode extension, e.g. 'en-US-u-hc-h23', which resolvedOptions().hourCycle will then return and short-circuit the fallback.
- Ensure full ICU data is available so Intl hour output matches the expected Latin-digit snapshots.
- If you maintain a fork, normalize hour.value (trim, convert digits) before the switch.
Example fix
// before <ion-datetime locale="ar-EG"></ion-datetime> <!-- Intl may emit non-Latin digits --> // after <ion-datetime locale="ar-EG-u-hc-h23" hour-cycle="h23"></ion-datetime>
Defensive patterns
Strategy: fallback
Validate before calling
// Prefer embedding the cycle in the locale so resolvedOptions() short-circuits the fallback: const locale = baseLocale + '-u-hc-h23'; // then Intl.DateTimeFormat(locale).resolvedOptions().hourCycle === 'h23'
Type guard
function localeDeclaresHourCycle(locale: string): boolean {
try {
return new Intl.DateTimeFormat(locale, { hour: 'numeric' }).resolvedOptions().hourCycle !== undefined;
} catch {
return false;
}
} Try / catch
try {
cycle = getHourCycle(locale);
} catch (e) {
if (e instanceof Error && /Invalid hour cycle/.test(e.message)) {
cycle = 'h23'; // deterministic fallback
} else { throw e; }
} Prevention
- Use the Unicode -u-hc-* extension in locale strings to avoid the heuristic path.
- Provide explicit hourCycle on ion-datetime in non-Latin-digit locales.
- Ensure full ICU data is present so hour output matches expected snapshots.
When it happens
Trigger: Intl.DateTimeFormat(locale, {hour:'numeric'}).formatToParts(midnightDate) returns an hour part whose value is something other than the four expected midnight representations - for example leading-zero differences like ' 0', locale-specific numerals (Arabic-Indic digits), or a non-midnight value because the test date resolved to a different hour in that timezone/locale.
Common situations: Locales with non-Latin digit output; environments that normalize/trim hour strings differently; a locale whose default hour formatting does not match the four hardcoded midnight snapshots; ICU data variants between Node versions.
Related errors
- Hour value not found from DateTimeFormat
- 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/cae49205c35da3b6.
Report an issue: GitHub.