Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ describe('NaturalErrorMessagePipe', () => {
[{myValidator: {message: 123}}, ''],
[{myValidator: {message: (unit: string) => `my message${unit}`}}, `my message`],
[{myValidator: {message: (unit: string) => `my message${unit}`}}, '%', `my message %`],
[{matDatepickerParse: {text: '01.01.'}}, 'Date invalide'],
[
{
matDatepickerMin: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {formatIsoDate, formatSwissDate} from '../../../classes/utility';
* - `Validators.required`
* - `matDatepickerMin`
* - `matDatepickerMax`
* - `matDatepickerParse`
*
* **Generic**:
*
Expand Down Expand Up @@ -70,6 +71,8 @@ export class NaturalErrorMessagePipe implements PipeTransform {
return $localize`Doit être plus grand ou égal à ${errors.min.min}${unit}`;
} else if (errors.max) {
return $localize`Doit être plus petit ou égal à ${errors.max.max}${unit}`;
} else if (errors.matDatepickerParse) {
return $localize`Date invalide`;
} else if (errors.matDatepickerMin) {
const min = formatIsoDate(errors.matDatepickerMin.min as Date);
const date = new Date();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,9 @@ export class TypeDateRangeComponent<D = any> implements DropdownComponent {
};

if (condition.between) {
value.from = this.dateAdapter.parse(condition.between.from, null);
value.to = this.dateAdapter.parse(condition.between.to, null);
// A condition that cannot be read parses into an invalid date, which must not reach the form
value.from = this.dateAdapter.getValidDateOrNull(this.dateAdapter.parse(condition.between.from, null));
value.to = this.dateAdapter.getValidDateOrNull(this.dateAdapter.parse(condition.between.to, null));
}

this.form.setValue(value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,27 +49,48 @@ describe('NaturalSwissParsingDateAdapter', () => {
expect(formatIsoDate(adapter.parse(' 2018-01-02 '))).toBe('2018-01-02');
});

it('should return nothing at all for an empty field', () => {
expect(adapter.parse('')).toBeNull();
expect(adapter.parse(' ')).toBeNull();
expect(adapter.parse(null)).toBeNull();
expect(adapter.parse(undefined)).toBeNull();
});

it('should tell an empty field apart from a date still being typed', () => {
expect(adapter.parse('')).toBeNull();

const stillBeingTyped = adapter.parse('01.01.');
expect(stillBeingTyped).not.toBeNull();
expect(adapter.isValid(stillBeingTyped!)).toBeFalse();
});

it('should reject too much partial Swiss format', () => {
expect(formatIsoDate(adapter.parse('2.1.1'))).toBeNull();
expect(adapter.isValid(adapter.parse('2.1.1')!)).toBeFalse();
});

it('should reject mixed separators', () => {
expect(adapter.parse('22.11/2018')).toBeNull();
expect(adapter.isValid(adapter.parse('22.11/2018')!)).toBeFalse();
});

it('should reject no separator at all', () => {
expect(adapter.parse('220905')).toBeNull();
expect(adapter.isValid(adapter.parse('220905')!)).toBeFalse();
});

it('should reject invalid date', () => {
expect(adapter.parse('00.01.2000')).toBeNull();
expect(adapter.parse('01.00.2000')).toBeNull();
expect(adapter.parse('01.31.2000')).toBeNull();
expect(adapter.parse('50.01.2000')).toBeNull();
it('should parse the 29th of February of a leap year', () => {
expect(formatIsoDate(adapter.parse('29.02.2024'))).toBe('2024-02-29');
});

it('should not parse invalid format', () => {
expect(adapter.parse('')).toBeNull();
expect(adapter.parse(null)).toBeNull();
it('should reject a day that does not exist in that month', () => {
expect(adapter.isValid(adapter.parse('29.02.2026')!)).toBeFalse();
expect(adapter.isValid(adapter.parse('31.02.2026')!)).toBeFalse();
expect(adapter.isValid(adapter.parse('31.04.2026')!)).toBeFalse();
expect(formatIsoDate(adapter.parse('30.04.2026'))).toBe('2026-04-30');
});

it('should reject invalid date', () => {
expect(adapter.isValid(adapter.parse('00.01.2000')!)).toBeFalse();
expect(adapter.isValid(adapter.parse('01.00.2000')!)).toBeFalse();
expect(adapter.isValid(adapter.parse('01.31.2000')!)).toBeFalse();
expect(adapter.isValid(adapter.parse('50.01.2000')!)).toBeFalse();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -18,42 +18,54 @@ export class NaturalSwissParsingDateAdapter extends NativeDateAdapter {
* - 24.12.2018
* - 1.4.18
* - 2018-12-24
*
* An empty field is `null`, and text that cannot be read is an invalid date.
*/
public override parse(value: unknown): Date | null {
if (typeof value === 'number') {
return new Date(value);
}

if (typeof value === 'string') {
const trimmed = value.trim();
if (typeof value !== 'string') {
return null;
}

const trimmed = value.trim();
if (!trimmed) {
return null;
}

for (const pattern of patterns) {
const m = trimmed.match(pattern);
if (m?.groups) {
const year = +m.groups.year;
const month = +m.groups.month;
const day = +m.groups.day;
for (const pattern of patterns) {
const m = trimmed.match(pattern);
if (m?.groups) {
const year = +m.groups.year;
const month = +m.groups.month;
const day = +m.groups.day;

return this.createDateIfValid(year, month, day);
}
return this.createDateOrInvalid(year, month, day);
}
}

return null;
return this.invalid();
}

private createDateIfValid(year: number, month: number, date: number): Date | null {
private createDateOrInvalid(year: number, month: number, date: number): Date {
// Assume year 2000 if only two digits
if (year < 100) {
year += 2000;
}

month = month - 1;
if (month >= 0 && month <= 11 && date >= 1 && date <= 31) {
return this.createDate(year, month, date);
if (month < 0 || month > 11 || date < 1 || date > 31) {
return this.invalid();
}

// A day that does not exist overflows into the next month
if (new Date(year, month, date).getMonth() !== month) {
return this.invalid();
}

return null;
return this.createDate(year, month, date);
}

public override getFirstDayOfWeek(): number {
Expand Down