From 8590a10d859df2609e3646a4f1a63e272be74fe8 Mon Sep 17 00:00:00 2001 From: MKirova Date: Tue, 23 Sep 2025 16:30:35 +0300 Subject: [PATCH 1/7] fix(date-editor): Use default display format based on locale. --- .../lib/date-common/util/date-time.util.ts | 21 +++---------------- .../date-time-editor.directive.ts | 2 +- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts b/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts index 18b3bc6b8a4..0b37597f9b4 100644 --- a/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts +++ b/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts @@ -1,7 +1,7 @@ import { DatePart, DatePartInfo } from '../../directives/date-time-editor/date-time-editor.common'; -import { formatDate, FormatWidth, getLocaleDateFormat } from '@angular/common'; +import { formatDate } from '@angular/common'; import { ValidationErrors } from '@angular/forms'; -import { isDate } from '../../core/utils'; +import { getLocaleDateFormat, isDate } from '../../core/utils'; import { DataType } from '../../data-operations/data-util'; /** @hidden */ @@ -283,22 +283,7 @@ export abstract class DateTimeUtil { * Supports Angular's DatePipe format options such as `shortDate`, `longDate`. */ public static getLocaleDateFormat(locale: string, displayFormat?: string): string { - const formatKeys = Object.keys(FormatWidth) as (keyof FormatWidth)[]; - const targetKey = formatKeys.find(k => k.toLowerCase() === displayFormat?.toLowerCase().replace('date', '')); - if (!targetKey) { - // if displayFormat is not shortDate, longDate, etc. - // or if it is not set by the user - return displayFormat; - } - let format: string; - try { - format = getLocaleDateFormat(locale, FormatWidth[targetKey]); - } catch { - DateTimeUtil.logMissingLocaleSettings(locale); - format = DateTimeUtil.getDefaultInputFormat(locale); - } - - return format; + return getLocaleDateFormat(locale, displayFormat); } /** Determines if a given character is `d/M/y` or `h/m/s`. */ diff --git a/projects/igniteui-angular/src/lib/directives/date-time-editor/date-time-editor.directive.ts b/projects/igniteui-angular/src/lib/directives/date-time-editor/date-time-editor.directive.ts index d758e0d3c64..7254b3296da 100644 --- a/projects/igniteui-angular/src/lib/directives/date-time-editor/date-time-editor.directive.ts +++ b/projects/igniteui-angular/src/lib/directives/date-time-editor/date-time-editor.directive.ts @@ -139,7 +139,7 @@ export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnCh } public get displayFormat(): string { - return this._displayFormat || this.inputFormat; + return this._displayFormat || this._inputFormat || DateTimeUtil.getLocaleDateFormat(this.locale, 'short'); } /** From 823d44fff9df121584dca4c9692e9a399b24dd38 Mon Sep 17 00:00:00 2001 From: MKirova Date: Wed, 24 Sep 2025 11:19:32 +0300 Subject: [PATCH 2/7] chore(*): Replace angular's format date with the new core lib one. --- .../src/lib/date-common/util/date-time.util.ts | 16 +--------------- .../date-range-picker-inputs.common.ts | 6 +++--- .../date-time-editor.directive.ts | 4 ++-- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts b/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts index 0b37597f9b4..71de5871c35 100644 --- a/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts +++ b/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts @@ -1,7 +1,6 @@ import { DatePart, DatePartInfo } from '../../directives/date-time-editor/date-time-editor.common'; -import { formatDate } from '@angular/common'; import { ValidationErrors } from '@angular/forms'; -import { getLocaleDateFormat, isDate } from '../../core/utils'; +import { formatDate, getLocaleDateFormat, isDate } from '../../core/utils'; import { DataType } from '../../data-operations/data-util'; /** @hidden */ @@ -264,19 +263,6 @@ export abstract class DateTimeUtil { return DateTimeUtil.getMask(parts); } - /** Tries to format a date using Angular's DatePipe. Fallbacks to `Intl` if no locale settings have been loaded. */ - public static formatDate(value: number | Date, format: string, locale: string, timezone?: string): string { - let formattedDate: string; - try { - formattedDate = formatDate(value, format, locale, timezone); - } catch { - DateTimeUtil.logMissingLocaleSettings(locale); - const formatter = new Intl.DateTimeFormat(locale); - formattedDate = formatter.format(value); - } - - return formattedDate; - } /** * Returns the date format based on a provided locale. diff --git a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker-inputs.common.ts b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker-inputs.common.ts index 6fb9732e4ce..970b95cec64 100644 --- a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker-inputs.common.ts +++ b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker-inputs.common.ts @@ -5,7 +5,7 @@ import { IgxInputGroupComponent } from '../input-group/input-group.component'; import { IgxInputGroupBase } from '../input-group/input-group.common'; import { DateTimeUtil } from '../date-common/util/date-time.util'; import { IgxDateTimeEditorDirective } from '../directives/date-time-editor/public_api'; -import { isDate } from '../core/utils'; +import { formatDate, isDate } from '../core/utils'; import { IgxIconComponent } from '../icon/icon.component'; import { IgxSuffixDirective } from '../directives/suffix/suffix.directive'; import { IgxButtonDirective } from '../directives/button/button.directive'; @@ -44,8 +44,8 @@ export class DateRangePickerFormatPipe implements PipeTransform { if (!isDate(end)) { end = DateTimeUtil.parseIsoDate(end); } - const startDate = appliedFormat ? DateTimeUtil.formatDate(start, appliedFormat, locale || 'en') : start?.toLocaleDateString(); - const endDate = appliedFormat ? DateTimeUtil.formatDate(end, appliedFormat, locale || 'en') : end?.toLocaleDateString(); + const startDate = appliedFormat ? formatDate(start, appliedFormat, locale || 'en') : start?.toLocaleDateString(); + const endDate = appliedFormat ? formatDate(end, appliedFormat, locale || 'en') : end?.toLocaleDateString(); let formatted; if (start) { formatted = `${startDate} - `; diff --git a/projects/igniteui-angular/src/lib/directives/date-time-editor/date-time-editor.directive.ts b/projects/igniteui-angular/src/lib/directives/date-time-editor/date-time-editor.directive.ts index 7254b3296da..e990cad8e24 100644 --- a/projects/igniteui-angular/src/lib/directives/date-time-editor/date-time-editor.directive.ts +++ b/projects/igniteui-angular/src/lib/directives/date-time-editor/date-time-editor.directive.ts @@ -9,7 +9,7 @@ import { } from '@angular/forms'; import { IgxMaskDirective } from '../mask/mask.directive'; import { MaskParsingService } from '../mask/mask-parsing.service'; -import { isDate, PlatformUtil } from '../../core/utils'; +import { formatDate, isDate, PlatformUtil } from '../../core/utils'; import { IgxDateTimeEditorEventArgs, DatePartInfo, DatePart } from './date-time-editor.common'; import { noop } from 'rxjs'; import { DatePartDeltas } from './date-time-editor.common'; @@ -549,7 +549,7 @@ export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnCh } const format = this.displayFormat || this.inputFormat; if (format) { - this.inputValue = DateTimeUtil.formatDate(this.dateValue, format.replace('tt', 'aa'), this.locale); + this.inputValue = formatDate(this.dateValue, format.replace('tt', 'aa'), this.locale); } else { this.inputValue = this.dateValue.toLocaleString(); } From ea41d72d4e86851383b8c37a0df50b20c8fa97ca Mon Sep 17 00:00:00 2001 From: MKirova Date: Wed, 24 Sep 2025 14:33:56 +0300 Subject: [PATCH 3/7] chore(*): Use default locale from core when resolving default input format. --- .../src/lib/date-common/util/date-time.util.ts | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts b/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts index 71de5871c35..572ff26dbfa 100644 --- a/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts +++ b/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts @@ -2,6 +2,7 @@ import { DatePart, DatePartInfo } from '../../directives/date-time-editor/date-t import { ValidationErrors } from '@angular/forms'; import { formatDate, getLocaleDateFormat, isDate } from '../../core/utils'; import { DataType } from '../../data-operations/data-util'; +import { getDateFormatter } from 'igniteui-i18n-core'; /** @hidden */ const enum FormatDesc { @@ -249,18 +250,12 @@ export abstract class DateTimeUtil { /** Builds a date-time editor's default input format based on provided locale settings and data type. */ public static getDefaultInputFormat(locale: string, dataType: DataType = DataType.Date): string { locale = locale || DateTimeUtil.DEFAULT_LOCALE; - if (!Intl || !Intl.DateTimeFormat || !Intl.DateTimeFormat.prototype.formatToParts) { - // TODO: fallback with Intl.format for IE? - return DateTimeUtil.DEFAULT_INPUT_FORMAT; - } - const parts = DateTimeUtil.getDefaultLocaleMask(locale, dataType); - parts.forEach(p => { - if (p.type !== DatePart.Year && p.type !== DateTimeUtil.SEPARATOR && p.type !== DatePart.AmPm) { - p.formatType = FormatDesc.TwoDigits; - } - }); - return DateTimeUtil.getMask(parts); + if (dataType === DataType.Date) { + return getDateFormatter().getLocaleDateTimeFormat(locale, true); + } else if(dataType === DataType.DateTime) { + return getDateFormatter().getLocaleDateTimeFormat(locale, true); + } } From 2961c922bf880918333afdfec863ceec8d9f279f Mon Sep 17 00:00:00 2001 From: MKirova Date: Wed, 24 Sep 2025 14:41:27 +0300 Subject: [PATCH 4/7] chore(*): Pass specific input options to intl formatter in core. --- .../src/lib/date-common/util/date-time.util.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts b/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts index 572ff26dbfa..eab5b0131e8 100644 --- a/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts +++ b/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts @@ -544,10 +544,8 @@ export abstract class DateTimeUtil { options[p] = FormatDesc.TwoDigits; } }); - const formatter = new Intl.DateTimeFormat(locale, options); - const dateStruct = DateTimeUtil.getDateStructFromParts(formatter.formatToParts(new Date()), formatter); - DateTimeUtil.fillDatePartsPositions(dateStruct); - return DateTimeUtil.getMask(dateStruct); + + return getDateFormatter().getLocaleDateTimeFormat(locale, true, options); } private static addCurrentPart(currentPart: DatePartInfo, dateTimeParts: DatePartInfo[]): void { From f3fb8ec49149430f3088212f00d3e1bb4f5d28e9 Mon Sep 17 00:00:00 2001 From: MKirova Date: Wed, 24 Sep 2025 14:44:02 +0300 Subject: [PATCH 5/7] chore(*): Remove unused functions in util. --- .../lib/date-common/util/date-time.util.ts | 162 ------------------ 1 file changed, 162 deletions(-) diff --git a/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts b/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts index eab5b0131e8..85cca56668c 100644 --- a/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts +++ b/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts @@ -563,70 +563,6 @@ export abstract class DateTimeUtil { return result; } - private static getMask(dateStruct: any[]): string { - const mask = []; - for (const part of dateStruct) { - if (part.formatType === FormatDesc.Numeric) { - switch (part.type) { - case DateParts.Day: - mask.push('d'); - break; - case DateParts.Month: - mask.push('M'); - break; - case DateParts.Year: - mask.push('yyyy'); - break; - case DateParts.Hour: - mask.push(part.hour12 ? 'h' : 'H'); - break; - case DateParts.Minute: - mask.push('m'); - break; - case DateParts.Second: - mask.push('s'); - break; - } - } else if (part.formatType === FormatDesc.TwoDigits) { - switch (part.type) { - case DateParts.Day: - mask.push('dd'); - break; - case DateParts.Month: - mask.push('MM'); - break; - case DateParts.Year: - mask.push('yy'); - break; - case DateParts.Hour: - mask.push(part.hour12 ? 'hh' : 'HH'); - break; - case DateParts.Minute: - mask.push('mm'); - break; - case DateParts.Second: - mask.push('ss'); - break; - } - } - - if (part.type === DateParts.AmPm) { - mask.push('tt'); - } - - if (part.type === DateTimeUtil.SEPARATOR) { - mask.push(part.value); - } - } - - return mask.join(''); - } - - private static logMissingLocaleSettings(locale: string): void { - console.warn(`Missing locale data for the locale ${locale}. Please refer to https://angular.io/guide/i18n#i18n-pipes`); - console.warn('Using default browser locale settings.'); - } - private static prependValue(value: number, partLength: number, prependChar: string): string { return (prependChar + value.toString()).slice(-partLength); } @@ -716,102 +652,4 @@ export abstract class DateTimeUtil { return { }; } } - - private static getDefaultLocaleMask(locale: string, dataType: DataType = DataType.Date) { - const options = DateTimeUtil.getFormatOptions(dataType); - const formatter = new Intl.DateTimeFormat(locale, options); - const formatToParts = formatter.formatToParts(new Date()); - const dateStruct = DateTimeUtil.getDateStructFromParts(formatToParts, formatter); - DateTimeUtil.fillDatePartsPositions(dateStruct); - return dateStruct; - } - - private static getDateStructFromParts(parts: Intl.DateTimeFormatPart[], formatter: Intl.DateTimeFormat): any[] { - const dateStruct = []; - for (const part of parts) { - if (part.type === DateTimeUtil.SEPARATOR) { - dateStruct.push({ - type: DateTimeUtil.SEPARATOR, - value: part.value - }); - } else { - dateStruct.push({ - type: part.type - }); - } - } - const formatterOptions = formatter.resolvedOptions(); - for (const part of dateStruct) { - switch (part.type) { - case DateParts.Day: { - part.formatType = formatterOptions.day; - break; - } - case DateParts.Month: { - part.formatType = formatterOptions.month; - break; - } - case DateParts.Year: { - part.formatType = formatterOptions.year; - break; - } - case DateParts.Hour: { - part.formatType = formatterOptions.hour; - if (formatterOptions.hour12) { - part.hour12 = true; - } - break; - } - case DateParts.Minute: { - part.formatType = formatterOptions.minute; - break; - } - case DateParts.Second: { - part.formatType = formatterOptions.second; - break; - } - case DateParts.AmPm: { - part.formatType = formatterOptions.dayPeriod; - break; - } - } - } - return dateStruct; - } - - private static fillDatePartsPositions(dateArray: any[]): void { - let currentPos = 0; - - for (const part of dateArray) { - // Day|Month|Hour|Minute|Second|AmPm part positions - if (part.type === DateParts.Day || part.type === DateParts.Month || - part.type === DateParts.Hour || part.type === DateParts.Minute || part.type === DateParts.Second || - part.type === DateParts.AmPm - ) { - // Offset 2 positions for number - part.position = [currentPos, currentPos + 2]; - currentPos += 2; - } else if (part.type === DateParts.Year) { - // Year part positions - switch (part.formatType) { - case FormatDesc.Numeric: { - // Offset 4 positions for full year - part.position = [currentPos, currentPos + 4]; - currentPos += 4; - break; - } - case FormatDesc.TwoDigits: { - // Offset 2 positions for short year - part.position = [currentPos, currentPos + 2]; - currentPos += 2; - break; - } - } - } else if (part.type === DateTimeUtil.SEPARATOR) { - // Separator positions - part.position = [currentPos, currentPos + 1]; - currentPos++; - } - } - } } From 8a5c1f6815ad5c4277758ba5b96ca6b43bd7599a Mon Sep 17 00:00:00 2001 From: MKirova Date: Wed, 24 Sep 2025 17:49:51 +0300 Subject: [PATCH 6/7] chore(*): Pass format options based on dataType. --- .../src/lib/date-common/util/date-time.util.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts b/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts index 85cca56668c..2ac1745b1d8 100644 --- a/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts +++ b/projects/igniteui-angular/src/lib/date-common/util/date-time.util.ts @@ -250,12 +250,7 @@ export abstract class DateTimeUtil { /** Builds a date-time editor's default input format based on provided locale settings and data type. */ public static getDefaultInputFormat(locale: string, dataType: DataType = DataType.Date): string { locale = locale || DateTimeUtil.DEFAULT_LOCALE; - - if (dataType === DataType.Date) { - return getDateFormatter().getLocaleDateTimeFormat(locale, true); - } else if(dataType === DataType.DateTime) { - return getDateFormatter().getLocaleDateTimeFormat(locale, true); - } + return getDateFormatter().getLocaleDateTimeFormat(locale, true, DateTimeUtil.getFormatOptions(dataType)); } From bb218ffb9df5183f5e9eee3db22669344ab1c599 Mon Sep 17 00:00:00 2001 From: MKirova Date: Thu, 25 Sep 2025 15:45:52 +0300 Subject: [PATCH 7/7] chore(*): Update formats in tests to match Intl. --- .../src/lib/date-common/util/date-time.util.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/igniteui-angular/src/lib/date-common/util/date-time.util.spec.ts b/projects/igniteui-angular/src/lib/date-common/util/date-time.util.spec.ts index 4777e412448..65033acd12f 100644 --- a/projects/igniteui-angular/src/lib/date-common/util/date-time.util.spec.ts +++ b/projects/igniteui-angular/src/lib/date-common/util/date-time.util.spec.ts @@ -239,7 +239,7 @@ describe(`DateTimeUtil Unit tests`, () => { it('should properly build input formats based on locale for dateTime data type ', () => { let result = DateTimeUtil.getDefaultInputFormat('en-US', DataType.DateTime); - expect(result.normalize('NFKC')).toEqual('MM/dd/yyyy, hh:mm:ss tt'); + expect(result.normalize('NFKC')).toEqual('MM/dd/yyyy, hh:mm:ss a'); result = DateTimeUtil.getDefaultInputFormat('bg-BG', DataType.DateTime); expect(result.normalize('NFKC')).toEqual('dd.MM.yyyy г., HH:mm:ss'); @@ -250,7 +250,7 @@ describe(`DateTimeUtil Unit tests`, () => { it('should properly build input formats based on locale for time data type ', () => { let result = DateTimeUtil.getDefaultInputFormat('en-US', DataType.Time); - expect(result.normalize('NFKC')).toEqual('hh:mm tt'); + expect(result.normalize('NFKC')).toEqual('hh:mm a'); result = DateTimeUtil.getDefaultInputFormat('bg-BG', DataType.Time); expect(result.normalize('NFKC')).toEqual('HH:mm');