mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-08 23:58:13 +08:00
feat(datetime): formatOptions property for Datetime (#29065)
Issue number: Internal --------- <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? <!-- Please describe the current behavior that you are modifying. --> The Datetime header, Datetime time button, and Datetime Button have default date formatting that cannot be set by the developer. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - The developer can customize the date and time formatting for the Datetime header and time button - The developer can customize the date and time formatting for the Datetime Button - A warning will appear in the console if they try to provide a time zone (the time zone will not get used) - A warning will be logged if they do not include the date or time object for formatOptions as needed for the presentation of the Datetime ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change: 1. Describe the impact and migration path for existing applications below. 2. Update the BREAKING.md file with the breaking change. 3. Add "BREAKING CHANGE: [...]" to the commit description when merging. See https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#footer for more information. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> These changes have been reviewed in #29009 and #29059. This PR just adds them to the feature branch now that the separate tickets are complete. --------- Co-authored-by: ionitron <hi@ionicframework.com> Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>
This commit is contained in:
@ -36,3 +36,16 @@ export type DatetimeHighlight = { date: string } & DatetimeHighlightStyle;
|
||||
export type DatetimeHighlightCallback = (dateIsoString: string) => DatetimeHighlightStyle | undefined;
|
||||
|
||||
export type DatetimeHourCycle = 'h11' | 'h12' | 'h23' | 'h24';
|
||||
|
||||
/**
|
||||
* FormatOptions must include date and/or time; it cannot be an empty object
|
||||
*/
|
||||
export type FormatOptions =
|
||||
| {
|
||||
date: Intl.DateTimeFormatOptions;
|
||||
time?: Intl.DateTimeFormatOptions;
|
||||
}
|
||||
| {
|
||||
date?: Intl.DateTimeFormatOptions;
|
||||
time: Intl.DateTimeFormatOptions;
|
||||
};
|
||||
|
||||
@ -20,6 +20,7 @@ import type {
|
||||
DatetimeHighlightStyle,
|
||||
DatetimeHighlightCallback,
|
||||
DatetimeHourCycle,
|
||||
FormatOptions,
|
||||
} from './datetime-interface';
|
||||
import { isSameDay, warnIfValueOutOfBounds, isBefore, isAfter } from './utils/comparison';
|
||||
import {
|
||||
@ -33,7 +34,7 @@ import {
|
||||
getTimeColumnsData,
|
||||
getCombinedDateColumnData,
|
||||
} from './utils/data';
|
||||
import { formatValue, getLocalizedTime, getMonthAndDay, getMonthAndYear } from './utils/format';
|
||||
import { formatValue, getLocalizedDateTime, getLocalizedTime, getMonthAndYear } from './utils/format';
|
||||
import { isLocaleDayPeriodRTL, isMonthFirstLocale, getNumDaysInMonth, getHourCycle } from './utils/helpers';
|
||||
import {
|
||||
calculateHourFromAMPM,
|
||||
@ -68,6 +69,7 @@ import {
|
||||
isNextMonthDisabled,
|
||||
isPrevMonthDisabled,
|
||||
} from './utils/state';
|
||||
import { checkForPresentationFormatMismatch, warnIfTimeZoneProvided } from './utils/validate';
|
||||
|
||||
/**
|
||||
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
|
||||
@ -171,6 +173,20 @@ export class Datetime implements ComponentInterface {
|
||||
*/
|
||||
@Prop() disabled = false;
|
||||
|
||||
/**
|
||||
* Formatting options for dates and times.
|
||||
* Should include a 'date' and/or 'time' object, each of which is of type [Intl.DateTimeFormatOptions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options).
|
||||
*
|
||||
*/
|
||||
@Prop() formatOptions?: FormatOptions;
|
||||
|
||||
@Watch('formatOptions')
|
||||
protected formatOptionsChanged() {
|
||||
const { el, formatOptions, presentation } = this;
|
||||
checkForPresentationFormatMismatch(el, presentation, formatOptions);
|
||||
warnIfTimeZoneProvided(el, formatOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* If `true`, the datetime appears normal but the selected date cannot be changed.
|
||||
*/
|
||||
@ -235,6 +251,12 @@ export class Datetime implements ComponentInterface {
|
||||
*/
|
||||
@Prop() presentation: DatetimePresentation = 'date-time';
|
||||
|
||||
@Watch('presentation')
|
||||
protected presentationChanged() {
|
||||
const { el, formatOptions, presentation } = this;
|
||||
checkForPresentationFormatMismatch(el, presentation, formatOptions);
|
||||
}
|
||||
|
||||
private get isGridStyle() {
|
||||
const { presentation, preferWheel } = this;
|
||||
const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
|
||||
@ -1357,7 +1379,7 @@ export class Datetime implements ComponentInterface {
|
||||
};
|
||||
|
||||
componentWillLoad() {
|
||||
const { el, highlightedDates, multiple, presentation, preferWheel } = this;
|
||||
const { el, formatOptions, highlightedDates, multiple, presentation, preferWheel } = this;
|
||||
|
||||
if (multiple) {
|
||||
if (presentation !== 'date') {
|
||||
@ -1382,6 +1404,11 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
}
|
||||
|
||||
if (formatOptions) {
|
||||
checkForPresentationFormatMismatch(el, presentation, formatOptions);
|
||||
warnIfTimeZoneProvided(el, formatOptions);
|
||||
}
|
||||
|
||||
const hourValues = (this.parsedHourValues = convertToArrayOfNumbers(this.hourValues));
|
||||
const minuteValues = (this.parsedMinuteValues = convertToArrayOfNumbers(this.minuteValues));
|
||||
const monthValues = (this.parsedMonthValues = convertToArrayOfNumbers(this.monthValues));
|
||||
@ -2354,7 +2381,7 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
|
||||
private renderTimeOverlay() {
|
||||
const { disabled, hourCycle, isTimePopoverOpen, locale } = this;
|
||||
const { disabled, hourCycle, isTimePopoverOpen, locale, formatOptions } = this;
|
||||
const computedHourCycle = getHourCycle(locale, hourCycle);
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
@ -2389,7 +2416,7 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
}}
|
||||
>
|
||||
{getLocalizedTime(locale, activePart, computedHourCycle)}
|
||||
{getLocalizedTime(locale, activePart, computedHourCycle, formatOptions?.time)}
|
||||
</button>,
|
||||
<ion-popover
|
||||
alignment="center"
|
||||
@ -2424,7 +2451,7 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
|
||||
private getHeaderSelectedDateText() {
|
||||
const { activeParts, multiple, titleSelectedDatesFormatter } = this;
|
||||
const { activeParts, formatOptions, multiple, titleSelectedDatesFormatter } = this;
|
||||
const isArray = Array.isArray(activeParts);
|
||||
|
||||
let headerText: string;
|
||||
@ -2439,7 +2466,11 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
} else {
|
||||
// for exactly 1 day selected (multiple set or not), show a formatted version of that
|
||||
headerText = getMonthAndDay(this.locale, this.getActivePartsWithFallback());
|
||||
headerText = getLocalizedDateTime(
|
||||
this.locale,
|
||||
this.getActivePartsWithFallback(),
|
||||
formatOptions?.date ?? { weekday: 'short', month: 'short', day: 'numeric' }
|
||||
);
|
||||
}
|
||||
|
||||
return headerText;
|
||||
|
||||
@ -565,3 +565,107 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* This behavior does not differ across
|
||||
* directions.
|
||||
*/
|
||||
configs({ directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('datetime: formatOptions'), () => {
|
||||
test('should format header and time button', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-datetime value="2022-02-01T16:30:00">
|
||||
<span slot="title">Select Date</span>
|
||||
</ion-datetime>
|
||||
<script>
|
||||
const datetime = document.querySelector('ion-datetime');
|
||||
datetime.formatOptions = {
|
||||
time: { hour: '2-digit', minute: '2-digit' },
|
||||
date: { day: '2-digit', month: 'long', era: 'short' },
|
||||
}
|
||||
</script>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
const headerDate = page.locator('ion-datetime .datetime-selected-date');
|
||||
await expect(headerDate).toHaveText('February 01 AD');
|
||||
|
||||
const timeBody = page.locator('ion-datetime .time-body');
|
||||
await expect(timeBody).toHaveText('04:30 PM');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* This behavior does not differ across
|
||||
* modes/directions.
|
||||
*/
|
||||
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('datetime: formatOptions misconfiguration errors'), () => {
|
||||
test('should log a warning if time zone is provided', async ({ page }) => {
|
||||
const logs: string[] = [];
|
||||
|
||||
page.on('console', (msg) => {
|
||||
if (msg.type() === 'warning') {
|
||||
logs.push(msg.text());
|
||||
}
|
||||
});
|
||||
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-datetime value="2022-02-01T16:30:00" presentation="date">
|
||||
<span slot="title">Select Date</span>
|
||||
</ion-datetime>
|
||||
<script>
|
||||
const datetime = document.querySelector('ion-datetime');
|
||||
datetime.formatOptions = {
|
||||
date: { timeZone: 'UTC' },
|
||||
}
|
||||
</script>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
expect(logs.length).toBe(1);
|
||||
expect(logs[0]).toContain(
|
||||
'[Ionic Warning]: Datetime: "timeZone" and "timeZoneName" are not supported in "formatOptions".'
|
||||
);
|
||||
});
|
||||
|
||||
test('should log a warning if the required formatOptions are not provided for a presentation', async ({ page }) => {
|
||||
const logs: string[] = [];
|
||||
|
||||
page.on('console', (msg) => {
|
||||
if (msg.type() === 'warning') {
|
||||
logs.push(msg.text());
|
||||
}
|
||||
});
|
||||
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-datetime value="2022-02-01T16:30:00">
|
||||
<span slot="title">Select Date</span>
|
||||
</ion-datetime>
|
||||
<script>
|
||||
const datetime = document.querySelector('ion-datetime');
|
||||
datetime.formatOptions = {}
|
||||
</script>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
await page.locator('.datetime-ready').waitFor();
|
||||
|
||||
expect(logs.length).toBe(1);
|
||||
expect(logs[0]).toContain(
|
||||
"[Ionic Warning]: Datetime: The 'date-time' presentation requires either a date or time object (or both) in formatOptions."
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -308,6 +308,13 @@
|
||||
</ion-datetime>
|
||||
</ion-modal>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>formatOptions</h2>
|
||||
<ion-datetime value="2020-03-14T14:23:00.000Z" id="format-options-datetime">
|
||||
<span slot="title">Select Date</span>
|
||||
</ion-datetime>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
<script>
|
||||
@ -403,6 +410,12 @@
|
||||
app.appendChild(modalElement);
|
||||
return modalElement;
|
||||
};
|
||||
|
||||
const formatOptions = document.querySelector('#format-options-datetime');
|
||||
formatOptions.formatOptions = {
|
||||
time: { hour: '2-digit', minute: '2-digit' },
|
||||
date: { day: '2-digit', month: 'long', era: 'short' },
|
||||
};
|
||||
</script>
|
||||
</ion-app>
|
||||
</body>
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import type { DatetimeParts } from '../datetime-interface';
|
||||
import {
|
||||
generateDayAriaLabel,
|
||||
getMonthAndDay,
|
||||
getFormattedHour,
|
||||
addTimePadding,
|
||||
getMonthAndYear,
|
||||
getLocalizedDayPeriod,
|
||||
getLocalizedTime,
|
||||
stripTimeZone,
|
||||
} from '../utils/format';
|
||||
|
||||
describe('generateDayAriaLabel()', () => {
|
||||
@ -37,24 +37,6 @@ describe('generateDayAriaLabel()', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMonthAndDay()', () => {
|
||||
it('should return Tue, May 11', () => {
|
||||
expect(getMonthAndDay('en-US', { month: 5, day: 11, year: 2021 })).toEqual('Tue, May 11');
|
||||
});
|
||||
|
||||
it('should return mar, 11 may', () => {
|
||||
expect(getMonthAndDay('es-ES', { month: 5, day: 11, year: 2021 })).toEqual('mar, 11 may');
|
||||
});
|
||||
|
||||
it('should return Sat, Apr 1', () => {
|
||||
expect(getMonthAndDay('en-US', { month: 4, day: 1, year: 2006 })).toEqual('Sat, Apr 1');
|
||||
});
|
||||
|
||||
it('should return sáb, 1 abr', () => {
|
||||
expect(getMonthAndDay('es-ES', { month: 4, day: 1, year: 2006 })).toEqual('sáb, 1 abr');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFormattedHour()', () => {
|
||||
it('should only add padding if using 24 hour time', () => {
|
||||
expect(getFormattedHour(1, 'h11')).toEqual('1');
|
||||
@ -144,6 +126,7 @@ describe('getLocalizedTime', () => {
|
||||
|
||||
expect(getLocalizedTime('en-GB', datetimeParts, 'h12')).toEqual('12:00 am');
|
||||
});
|
||||
|
||||
it('should parse time-only values correctly', () => {
|
||||
const datetimeParts: Partial<DatetimeParts> = {
|
||||
hour: 22,
|
||||
@ -153,4 +136,79 @@ describe('getLocalizedTime', () => {
|
||||
expect(getLocalizedTime('en-US', datetimeParts as DatetimeParts, 'h12')).toEqual('10:40 PM');
|
||||
expect(getLocalizedTime('en-US', datetimeParts as DatetimeParts, 'h23')).toEqual('22:40');
|
||||
});
|
||||
|
||||
it('should use formatOptions', () => {
|
||||
const datetimeParts: DatetimeParts = {
|
||||
day: 1,
|
||||
month: 1,
|
||||
year: 2022,
|
||||
hour: 9,
|
||||
minute: 40,
|
||||
};
|
||||
|
||||
const formatOptions: Intl.DateTimeFormatOptions = {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
dayPeriod: 'short',
|
||||
day: '2-digit',
|
||||
};
|
||||
|
||||
// Even though this method is intended to be used for time, the date may be displayed as well when passing formatOptions
|
||||
expect(getLocalizedTime('en-US', datetimeParts, 'h12', formatOptions)).toEqual('01, 09:40 in the morning');
|
||||
});
|
||||
|
||||
it('should override provided time zone with UTC', () => {
|
||||
const datetimeParts: DatetimeParts = {
|
||||
day: 1,
|
||||
month: 1,
|
||||
year: 2022,
|
||||
hour: 9,
|
||||
minute: 40,
|
||||
};
|
||||
|
||||
const formatOptions: Intl.DateTimeFormatOptions = {
|
||||
timeZone: 'Australia/Sydney',
|
||||
timeZoneName: 'long',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
};
|
||||
|
||||
expect(getLocalizedTime('en-US', datetimeParts, 'h12', formatOptions)).toEqual('9:40 AM');
|
||||
});
|
||||
|
||||
it('should not include time zone name', () => {
|
||||
const datetimeParts: DatetimeParts = {
|
||||
day: 1,
|
||||
month: 1,
|
||||
year: 2022,
|
||||
hour: 9,
|
||||
minute: 40,
|
||||
};
|
||||
|
||||
const formatOptions: Intl.DateTimeFormatOptions = {
|
||||
timeZone: 'America/Los_Angeles',
|
||||
timeZoneName: 'long',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
};
|
||||
|
||||
expect(getLocalizedTime('en-US', datetimeParts, 'h12', formatOptions)).toEqual('9:40 AM');
|
||||
});
|
||||
});
|
||||
|
||||
describe('stripTimeZone', () => {
|
||||
it('should remove the time zone name from the options and set the time zone to UTC', () => {
|
||||
const formatOptions: Intl.DateTimeFormatOptions = {
|
||||
timeZone: 'America/Los_Angeles',
|
||||
timeZoneName: 'long',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
};
|
||||
|
||||
expect(stripTimeZone(formatOptions)).toEqual({
|
||||
timeZone: 'UTC',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -11,7 +11,33 @@ const getFormattedDayPeriod = (dayPeriod?: string) => {
|
||||
return dayPeriod.toUpperCase();
|
||||
};
|
||||
|
||||
export const getLocalizedTime = (locale: string, refParts: DatetimeParts, hourCycle: DatetimeHourCycle): string => {
|
||||
/**
|
||||
* Including time zone options may lead to the rendered text showing a
|
||||
* different time from what was selected in the Datetime, which could cause
|
||||
* confusion.
|
||||
*/
|
||||
export const stripTimeZone = (formatOptions: Intl.DateTimeFormatOptions): Intl.DateTimeFormatOptions => {
|
||||
return {
|
||||
...formatOptions,
|
||||
/**
|
||||
* Setting the time zone to UTC ensures that the value shown is always the
|
||||
* same as what was selected and safeguards against older Safari bugs with
|
||||
* Intl.DateTimeFormat.
|
||||
*/
|
||||
timeZone: 'UTC',
|
||||
/**
|
||||
* We do not want to display the time zone name
|
||||
*/
|
||||
timeZoneName: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
export const getLocalizedTime = (
|
||||
locale: string,
|
||||
refParts: DatetimeParts,
|
||||
hourCycle: DatetimeHourCycle,
|
||||
formatOptions: Intl.DateTimeFormatOptions = { hour: 'numeric', minute: 'numeric' }
|
||||
): string => {
|
||||
const timeParts: Pick<DatetimeParts, 'hour' | 'minute'> = {
|
||||
hour: refParts.hour,
|
||||
minute: refParts.minute,
|
||||
@ -22,15 +48,7 @@ export const getLocalizedTime = (locale: string, refParts: DatetimeParts, hourCy
|
||||
}
|
||||
|
||||
return new Intl.DateTimeFormat(locale, {
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
/**
|
||||
* Setting the timeZone to UTC prevents
|
||||
* new Intl.DatetimeFormat from subtracting
|
||||
* the user's current timezone offset
|
||||
* when formatting the time.
|
||||
*/
|
||||
timeZone: 'UTC',
|
||||
...stripTimeZone(formatOptions),
|
||||
/**
|
||||
* We use hourCycle here instead of hour12 due to:
|
||||
* https://bugs.chromium.org/p/chromium/issues/detail?id=1347316&q=hour12&can=2
|
||||
@ -146,17 +164,6 @@ export const generateDayAriaLabel = (locale: string, today: boolean, refParts: D
|
||||
return today ? `Today, ${labelString}` : labelString;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the day of the week, month, and day
|
||||
* Used for the header in MD mode.
|
||||
*/
|
||||
export const getMonthAndDay = (locale: string, refParts: DatetimeParts) => {
|
||||
const date = getNormalizedDate(refParts);
|
||||
return new Intl.DateTimeFormat(locale, { weekday: 'short', month: 'short', day: 'numeric', timeZone: 'UTC' }).format(
|
||||
date
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a locale and a date object,
|
||||
* return a formatted string that includes
|
||||
@ -168,16 +175,6 @@ export const getMonthAndYear = (locale: string, refParts: DatetimeParts) => {
|
||||
return new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric', timeZone: 'UTC' }).format(date);
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a locale and a date object,
|
||||
* return a formatted string that includes
|
||||
* the short month, numeric day, and full year.
|
||||
* Example: Apr 22, 2021
|
||||
*/
|
||||
export const getMonthDayAndYear = (locale: string, refParts: DatetimeParts) => {
|
||||
return getLocalizedDateTime(locale, refParts, { month: 'short', day: 'numeric', year: 'numeric' });
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a locale and a date object,
|
||||
* return a formatted string that includes
|
||||
@ -235,7 +232,7 @@ export const getLocalizedDateTime = (
|
||||
options: Intl.DateTimeFormatOptions
|
||||
): string => {
|
||||
const date = getNormalizedDate(refParts);
|
||||
return getDateTimeFormat(locale, options).format(date);
|
||||
return getDateTimeFormat(locale, stripTimeZone(options)).format(date);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
54
core/src/components/datetime/utils/validate.ts
Normal file
54
core/src/components/datetime/utils/validate.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import { printIonWarning } from '@utils/logging';
|
||||
|
||||
import type { DatetimePresentation, FormatOptions } from '../datetime-interface';
|
||||
|
||||
/**
|
||||
* If a time zone is provided in the format options, the rendered text could
|
||||
* differ from what was selected in the Datetime, which could cause
|
||||
* confusion.
|
||||
*/
|
||||
export const warnIfTimeZoneProvided = (el: HTMLElement, formatOptions?: FormatOptions) => {
|
||||
if (
|
||||
formatOptions?.date?.timeZone ||
|
||||
formatOptions?.date?.timeZoneName ||
|
||||
formatOptions?.time?.timeZone ||
|
||||
formatOptions?.time?.timeZoneName
|
||||
) {
|
||||
printIonWarning('Datetime: "timeZone" and "timeZoneName" are not supported in "formatOptions".', el);
|
||||
}
|
||||
};
|
||||
|
||||
export const checkForPresentationFormatMismatch = (
|
||||
el: HTMLElement,
|
||||
presentation: DatetimePresentation,
|
||||
formatOptions?: FormatOptions
|
||||
) => {
|
||||
// formatOptions is not required
|
||||
if (!formatOptions) return;
|
||||
|
||||
// If formatOptions is provided, the date and/or time objects are required, depending on the presentation
|
||||
switch (presentation) {
|
||||
case 'date':
|
||||
case 'month-year':
|
||||
case 'month':
|
||||
case 'year':
|
||||
if (formatOptions.date === undefined) {
|
||||
printIonWarning(`Datetime: The '${presentation}' presentation requires a date object in formatOptions.`, el);
|
||||
}
|
||||
break;
|
||||
case 'time':
|
||||
if (formatOptions.time === undefined) {
|
||||
printIonWarning(`Datetime: The 'time' presentation requires a time object in formatOptions.`, el);
|
||||
}
|
||||
break;
|
||||
case 'date-time':
|
||||
case 'time-date':
|
||||
if (formatOptions.date === undefined && formatOptions.time === undefined) {
|
||||
printIonWarning(
|
||||
`Datetime: The '${presentation}' presentation requires either a date or time object (or both) in formatOptions.`,
|
||||
el
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user