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'); 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..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 @@ -1,8 +1,8 @@ import { DatePart, DatePartInfo } from '../../directives/date-time-editor/date-time-editor.common'; -import { formatDate, FormatWidth, getLocaleDateFormat } from '@angular/common'; import { ValidationErrors } from '@angular/forms'; -import { isDate } from '../../core/utils'; +import { formatDate, getLocaleDateFormat, isDate } from '../../core/utils'; import { DataType } from '../../data-operations/data-util'; +import { getDateFormatter } from 'igniteui-i18n-core'; /** @hidden */ const enum FormatDesc { @@ -250,55 +250,16 @@ 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); + return getDateFormatter().getLocaleDateTimeFormat(locale, true, DateTimeUtil.getFormatOptions(dataType)); } - /** 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. * 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`. */ @@ -578,10 +539,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 { @@ -599,70 +558,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); } @@ -752,102 +647,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++; - } - } - } } 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 d758e0d3c64..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'; @@ -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'); } /** @@ -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(); }