Skip to content

Commit 2927741

Browse files
feat(datetime-button): formatOptions for Datetime Button (#29059)
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 Button has 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 Button - 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. --> --------- Co-authored-by: Liam DeBeasi <[email protected]>
1 parent 7ac08bc commit 2927741

File tree

3 files changed

+105
-20
lines changed

3 files changed

+105
-20
lines changed

core/src/components/datetime-button/datetime-button.tsx

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { getIonMode } from '../../global/ionic-global';
88
import type { Color } from '../../interface';
99
import type { DatetimePresentation } from '../datetime/datetime-interface';
1010
import { getToday } from '../datetime/utils/data';
11-
import { getMonthAndYear, getMonthDayAndYear, getLocalizedDateTime, getLocalizedTime } from '../datetime/utils/format';
11+
import { getLocalizedDateTime, getLocalizedTime } from '../datetime/utils/format';
1212
import { getHourCycle } from '../datetime/utils/helpers';
1313
import { parseDate } from '../datetime/utils/parse';
1414
/**
@@ -196,7 +196,7 @@ export class DatetimeButton implements ComponentInterface {
196196
return;
197197
}
198198

199-
const { value, locale, hourCycle, preferWheel, multiple, titleSelectedDatesFormatter } = datetimeEl;
199+
const { value, locale, formatOptions, hourCycle, preferWheel, multiple, titleSelectedDatesFormatter } = datetimeEl;
200200

201201
const parsedValues = this.getParsedDateValues(value);
202202

@@ -225,8 +225,12 @@ export class DatetimeButton implements ComponentInterface {
225225
switch (datetimePresentation) {
226226
case 'date-time':
227227
case 'time-date':
228-
const dateText = getMonthDayAndYear(locale, firstParsedDatetime);
229-
const timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle);
228+
const dateText = getLocalizedDateTime(
229+
locale,
230+
firstParsedDatetime,
231+
formatOptions?.date ?? { month: 'short', day: 'numeric', year: 'numeric' }
232+
);
233+
const timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle, formatOptions?.time);
230234
if (preferWheel) {
231235
this.dateText = `${dateText} ${timeText}`;
232236
} else {
@@ -246,20 +250,28 @@ export class DatetimeButton implements ComponentInterface {
246250
}
247251
this.dateText = headerText;
248252
} else {
249-
this.dateText = getMonthDayAndYear(locale, firstParsedDatetime);
253+
this.dateText = getLocalizedDateTime(
254+
locale,
255+
firstParsedDatetime,
256+
formatOptions?.date ?? { month: 'short', day: 'numeric', year: 'numeric' }
257+
);
250258
}
251259
break;
252260
case 'time':
253-
this.timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle);
261+
this.timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle, formatOptions?.time);
254262
break;
255263
case 'month-year':
256-
this.dateText = getMonthAndYear(locale, firstParsedDatetime);
264+
this.dateText = getLocalizedDateTime(
265+
locale,
266+
firstParsedDatetime,
267+
formatOptions?.date ?? { month: 'long', year: 'numeric' }
268+
);
257269
break;
258270
case 'month':
259-
this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, { month: 'long' });
271+
this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, formatOptions?.time ?? { month: 'long' });
260272
break;
261273
case 'year':
262-
this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, { year: 'numeric' });
274+
this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, formatOptions?.time ?? { year: 'numeric' });
263275
break;
264276
}
265277
};

core/src/components/datetime-button/test/basic/datetime-button.e2e.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,4 +244,87 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
244244
await expect(page.locator('#time-button')).not.toBeVisible();
245245
});
246246
});
247+
248+
test.describe(title('datetime-button: formatOptions'), () => {
249+
test('should include date and time for presentation date-time', async ({ page }) => {
250+
await page.setContent(
251+
`
252+
<ion-datetime-button datetime="datetime"></ion-datetime-button>
253+
<ion-datetime id="datetime" presentation="date-time" value="2023-11-02T01:22:00" locale="en-US"></ion-datetime>
254+
<script>
255+
const datetime = document.querySelector('ion-datetime');
256+
datetime.formatOptions = {
257+
date: {
258+
weekday: "short",
259+
month: "long",
260+
day: "2-digit"
261+
},
262+
time: {
263+
hour: "2-digit",
264+
minute: "2-digit"
265+
}
266+
}
267+
</script>
268+
`,
269+
config
270+
);
271+
272+
await page.locator('.datetime-ready').waitFor();
273+
274+
await expect(page.locator('#date-button')).toContainText('Thu, November 02');
275+
await expect(page.locator('#time-button')).toContainText('01:22 AM');
276+
});
277+
278+
test('should include date for presentation date', async ({ page }) => {
279+
await page.setContent(
280+
`
281+
<ion-datetime-button datetime="datetime"></ion-datetime-button>
282+
<ion-datetime id="datetime" presentation="date" value="2023-11-02" locale="en-US"></ion-datetime>
283+
<script>
284+
const datetime = document.querySelector('ion-datetime');
285+
datetime.formatOptions = {
286+
date: {
287+
weekday: "short",
288+
month: "long",
289+
day: "2-digit"
290+
}
291+
}
292+
</script>
293+
`,
294+
config
295+
);
296+
297+
await page.locator('.datetime-ready').waitFor();
298+
299+
await expect(page.locator('#date-button')).toContainText('Thu, November 02');
300+
});
301+
302+
test('should include date and time in same button for preferWheel', async ({ page }) => {
303+
await page.setContent(
304+
`
305+
<ion-datetime-button datetime="datetime"></ion-datetime-button>
306+
<ion-datetime id="datetime" presentation="date-time" value="2023-11-02T01:22:00" locale="en-US" prefer-wheel="true"></ion-datetime>
307+
<script>
308+
const datetime = document.querySelector('ion-datetime');
309+
datetime.formatOptions = {
310+
date: {
311+
weekday: "short",
312+
month: "long",
313+
day: "2-digit"
314+
},
315+
time: {
316+
hour: "2-digit",
317+
minute: "2-digit"
318+
}
319+
}
320+
</script>
321+
`,
322+
config
323+
);
324+
325+
await page.locator('.datetime-ready').waitFor();
326+
327+
await expect(page.locator('ion-datetime-button')).toContainText('Thu, November 02 01:22 AM');
328+
});
329+
});
247330
});

core/src/components/datetime/utils/format.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -175,16 +175,6 @@ export const getMonthAndYear = (locale: string, refParts: DatetimeParts) => {
175175
return new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric', timeZone: 'UTC' }).format(date);
176176
};
177177

178-
/**
179-
* Given a locale and a date object,
180-
* return a formatted string that includes
181-
* the short month, numeric day, and full year.
182-
* Example: Apr 22, 2021
183-
*/
184-
export const getMonthDayAndYear = (locale: string, refParts: DatetimeParts) => {
185-
return getLocalizedDateTime(locale, refParts, { month: 'short', day: 'numeric', year: 'numeric' });
186-
};
187-
188178
/**
189179
* Given a locale and a date object,
190180
* return a formatted string that includes
@@ -242,7 +232,7 @@ export const getLocalizedDateTime = (
242232
options: Intl.DateTimeFormatOptions
243233
): string => {
244234
const date = getNormalizedDate(refParts);
245-
return getDateTimeFormat(locale, options).format(date);
235+
return getDateTimeFormat(locale, stripTimeZone(options)).format(date);
246236
};
247237

248238
/**

0 commit comments

Comments
 (0)