UNPKG

@ionic/core

Version:
132 lines (131 loc) 4.49 kB
/*! * (C) Ionic http://ionicframework.com - MIT License */ /** * Determines if given year is a * leap year. Returns `true` if year * is a leap year. Returns `false` * otherwise. */ export const isLeapYear = (year) => { return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; }; /** * Determines the hour cycle for a user. * If the hour cycle is explicitly defined, just use that. * Otherwise, we try to derive it from either the specified * locale extension tags or from Intl.DateTimeFormat directly. */ export const getHourCycle = (locale, hourCycle) => { /** * If developer has explicitly enabled 24-hour time * then return early and do not look at the system default. */ if (hourCycle !== undefined) { return hourCycle; } /** * If hourCycle was not specified, check the locale * that is set on the user's device. We first check the * Intl.DateTimeFormat hourCycle option as developers can encode this * 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: 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) => { 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. */ export const getNumDaysInMonth = (month, year) => { return month === 4 || month === 6 || month === 9 || month === 11 ? 30 : month === 2 ? isLeapYear(year) ? 29 : 28 : 31; }; /** * Certain locales display month then year while * others display year then month. * We can use Intl.DateTimeFormat to determine * the ordering for each locale. * The formatOptions param can be used to customize * which pieces of a date to compare against the month * with. For example, some locales render dd/mm/yyyy * while others render mm/dd/yyyy. This function can be * used for variations of the same "month first" check. */ export const isMonthFirstLocale = (locale, formatOptions = { month: 'numeric', year: 'numeric', }) => { /** * By setting month and year we guarantee that only * month, year, and literal (slashes '/', for example) * values are included in the formatToParts results. * * The ordering of the parts will be determined by * the locale. So if the month is the first value, * then we know month should be shown first. If the * year is the first value, then we know year should be shown first. * * This ordering can be controlled by customizing the locale property. */ const parts = new Intl.DateTimeFormat(locale, formatOptions).formatToParts(new Date()); return parts[0].type === 'month'; }; /** * Determines if the given locale formats the day period (am/pm) to the * left or right of the hour. * @param locale The locale to check. * @returns `true` if the locale formats the day period to the left of the hour. */ export const isLocaleDayPeriodRTL = (locale) => { const parts = new Intl.DateTimeFormat(locale, { hour: 'numeric' }).formatToParts(new Date()); return parts[0].type === 'dayPeriod'; };