Skip to content

Commit

Permalink
fix(datetime): preferWheel respects column ordering by locale (#25726)
Browse files Browse the repository at this point in the history
resolves #25722
  • Loading branch information
liamdebeasi committed Aug 8, 2022
1 parent 8327889 commit dee0f51
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 23 deletions.
22 changes: 21 additions & 1 deletion core/src/components/datetime/datetime.tsx
Expand Up @@ -1522,7 +1522,27 @@ export class Datetime implements ComponentInterface {
? getYearColumnData(this.todayParts, this.minParts, this.maxParts, this.parsedYearValues)
: [];

return [this.renderMonthPickerColumn(months), this.renderDayPickerColumn(days), this.renderYearPickerColumn(years)];
/**
* Certain locales show the day before the month.
*/
const showMonthFirst = isMonthFirstLocale(this.locale, { month: 'numeric', day: 'numeric' });

let renderArray = [];
if (showMonthFirst) {
renderArray = [
this.renderMonthPickerColumn(months),
this.renderDayPickerColumn(days),
this.renderYearPickerColumn(years),
];
} else {
renderArray = [
this.renderDayPickerColumn(days),
this.renderMonthPickerColumn(months),
this.renderYearPickerColumn(years),
];
}

return renderArray;
}

private renderDayPickerColumn(days: PickerColumnItem[]) {
Expand Down
78 changes: 58 additions & 20 deletions core/src/components/datetime/test/prefer-wheel/datetime.e2e.ts
Expand Up @@ -89,26 +89,64 @@ test.describe('datetime: prefer wheel', () => {
expect(await yearValues.count()).toBe(3);
expect(await dayValues.count()).toBe(5);
});
test('should correctly localize the date data', async ({ page }) => {
await page.setContent(`
<ion-datetime
presentation="date"
prefer-wheel="true"
locale="ja-JP"
min="2022-01-01"
max="2022-03-01"
day-values="1,2,3"
value="2022-01-01"
></ion-datetime>
`);

await page.waitForSelector('.datetime-ready');

const monthValues = page.locator('.month-column .picker-item:not(.picker-item-empty)');
const dayValues = page.locator('.day-column .picker-item:not(.picker-item-empty)');

expect(monthValues).toHaveText(['1月', '2月', '3月']);
expect(dayValues).toHaveText(['1日', '2日', '3日']);
test.describe('datetime: date wheel localization', () => {
test('should correctly localize the date data', async ({ page }) => {
await page.setContent(`
<ion-datetime
presentation="date"
prefer-wheel="true"
locale="ja-JP"
min="2022-01-01"
max="2022-03-01"
day-values="1,2,3"
value="2022-01-01"
></ion-datetime>
`);

await page.waitForSelector('.datetime-ready');

const monthValues = page.locator('.month-column .picker-item:not(.picker-item-empty)');
const dayValues = page.locator('.day-column .picker-item:not(.picker-item-empty)');

expect(monthValues).toHaveText(['1月', '2月', '3月']);
expect(dayValues).toHaveText(['1日', '2日', '3日']);
});
test('should render the columns according to locale - en-US', async ({ page }) => {
await page.setContent(`
<ion-datetime
presentation="date"
prefer-wheel="true"
locale="en-US"
value="2022-01-01"
></ion-datetime>
`);

await page.waitForSelector('.datetime-ready');

const columns = page.locator('ion-picker-column-internal');

await expect(columns.nth(0)).toHaveClass(/month-column/);
await expect(columns.nth(1)).toHaveClass(/day-column/);
await expect(columns.nth(2)).toHaveClass(/year-column/);
});
test('should render the columns according to locale - en-GB', async ({ page }) => {
await page.setContent(`
<ion-datetime
presentation="date"
prefer-wheel="true"
locale="en-GB"
value="2022-01-01"
></ion-datetime>
`);

await page.waitForSelector('.datetime-ready');

const columns = page.locator('ion-picker-column-internal');

await expect(columns.nth(0)).toHaveClass(/day-column/);
await expect(columns.nth(1)).toHaveClass(/month-column/);
await expect(columns.nth(2)).toHaveClass(/year-column/);
});
});
});
test.describe('datetime: date-time wheel rendering', () => {
Expand Down
15 changes: 13 additions & 2 deletions core/src/components/datetime/utils/helpers.ts
Expand Up @@ -74,8 +74,19 @@ export const getNumDaysInMonth = (month: number, year: number) => {
* 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: string) => {
export const isMonthFirstLocale = (
locale: string,
formatOptions: Intl.DateTimeFormatOptions = {
month: 'numeric',
year: 'numeric',
}
) => {
/**
* By setting month and year we guarantee that only
* month, year, and literal (slashes '/', for example)
Expand All @@ -88,7 +99,7 @@ export const isMonthFirstLocale = (locale: string) => {
*
* This ordering can be controlled by customizing the locale property.
*/
const parts = new Intl.DateTimeFormat(locale, { month: 'numeric', year: 'numeric' }).formatToParts(new Date());
const parts = new Intl.DateTimeFormat(locale, formatOptions).formatToParts(new Date());

return parts[0].type === 'month';
};
Expand Down

0 comments on commit dee0f51

Please sign in to comment.