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..86af2d68b98 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 @@ -3,6 +3,7 @@ import { DatePart, DatePartInfo } from '../../directives/date-time-editor/date-t import { DataType } from '../../data-operations/data-util'; import { registerLocaleData } from '@angular/common'; import localeBg from "@angular/common/locales/bg"; +import { BaseFormatter } from '../../core/i18n/formatters/formatter-base'; const reduceToDictionary = (parts: DatePartInfo[]) => parts.reduce((obj, x) => { obj[x.type] = x; @@ -239,7 +240,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 +251,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'); @@ -658,6 +659,7 @@ describe(`DateTimeUtil Unit tests`, () => { it('should correctly identify formats that would resolve to only numeric parts (and period) for the date/time parts', () => { // test with locale covering non-ASCII characters as well const locale = 'bg'; + const angularFormatter = new BaseFormatter; const numericFormats = ['y', 'yy', 'yyy', 'yyyy', 'M', 'MM', 'd', 'dd', 'h', 'hh', 'H', 'HH', 'm', 'mm', 's', 'ss', 'S', 'SS', 'SSS', @@ -666,47 +668,48 @@ describe(`DateTimeUtil Unit tests`, () => { 'dd/MM/yyyy test hh:mm' ]; numericFormats.forEach(format => { - expect(DateTimeUtil.isFormatNumeric(locale, format)).withContext(`Format: ${format}`).toBeTrue(); + expect(DateTimeUtil.isFormatNumeric(locale, format, angularFormatter)).withContext(`Format: ${format}`).toBeTrue(); }); const nonNumericFormats = ['MMM', 'MMMM', 'MMMMM', 'medium', 'long', 'full', 'mediumDate', 'longDate', 'fullDate', 'longTime', 'fullTime', 'dd-MMM-yyyy', 'E', 'EE']; nonNumericFormats.forEach(format => { - expect(DateTimeUtil.isFormatNumeric(locale, format)).withContext(`Format: ${format}`).toBeFalse(); + expect(DateTimeUtil.isFormatNumeric(locale, format, angularFormatter)).withContext(`Format: ${format}`).toBeFalse(); }); }); it('getNumericInputFormat should return formats with date parts that the date-time editors can handle', () => { let locale = 'en-US'; + const angularFormatter = new BaseFormatter; // returns the equivalent of the predefined numeric formats as date parts // should be transformed as inputFormats for editing (numeric year, 2-digit parts for the rest) - expect(DateTimeUtil.getNumericInputFormat(locale, 'short')).toBe('MM/dd/yyyy, hh:mm tt'); - expect(DateTimeUtil.getNumericInputFormat(locale, 'shortDate')).toBe('MM/dd/yyyy'); - expect(DateTimeUtil.getNumericInputFormat(locale, 'shortTime').normalize('NFKD')).toBe('hh:mm tt'); - expect(DateTimeUtil.getNumericInputFormat(locale, 'mediumTime').normalize('NFKD')).toBe('hh:mm:ss tt'); + expect(DateTimeUtil.getNumericInputFormat(locale, 'short', angularFormatter)).toBe('MM/dd/yyyy, hh:mm tt'); + expect(DateTimeUtil.getNumericInputFormat(locale, 'shortDate', angularFormatter)).toBe('MM/dd/yyyy'); + expect(DateTimeUtil.getNumericInputFormat(locale, 'shortTime', angularFormatter).normalize('NFKD')).toBe('hh:mm tt'); + expect(DateTimeUtil.getNumericInputFormat(locale, 'mediumTime', angularFormatter).normalize('NFKD')).toBe('hh:mm:ss tt'); // handle the predefined formats for different locales locale = 'bg-BG'; - expect(DateTimeUtil.getNumericInputFormat(locale, 'short').normalize('NFKD')).toBe('dd.MM.yyyy г., HH:mm'); - expect(DateTimeUtil.getNumericInputFormat(locale, 'shortDate').normalize('NFKD')).toBe('dd.MM.yyyy г.'); - expect(DateTimeUtil.getNumericInputFormat(locale, 'shortTime').normalize('NFKD')).toBe('HH:mm'); - expect(DateTimeUtil.getNumericInputFormat(locale, 'mediumTime').normalize('NFKD')).toBe('HH:mm:ss'); + expect(DateTimeUtil.getNumericInputFormat(locale, 'short', angularFormatter).normalize('NFKD')).toBe('dd.MM.yyyy г., HH:mm'); + expect(DateTimeUtil.getNumericInputFormat(locale, 'shortDate', angularFormatter).normalize('NFKD')).toBe('dd.MM.yyyy г.'); + expect(DateTimeUtil.getNumericInputFormat(locale, 'shortTime', angularFormatter).normalize('NFKD')).toBe('HH:mm'); + expect(DateTimeUtil.getNumericInputFormat(locale, 'mediumTime', angularFormatter).normalize('NFKD')).toBe('HH:mm:ss'); locale = 'ja-JP'; - expect(DateTimeUtil.getNumericInputFormat(locale, 'short')).toBe('yyyy/MM/dd HH:mm'); - expect(DateTimeUtil.getNumericInputFormat(locale, 'shortDate')).toBe('yyyy/MM/dd'); - expect(DateTimeUtil.getNumericInputFormat(locale, 'shortTime').normalize('NFKD')).toBe('HH:mm'); - expect(DateTimeUtil.getNumericInputFormat(locale, 'mediumTime').normalize('NFKD')).toBe('HH:mm:ss'); + expect(DateTimeUtil.getNumericInputFormat(locale, 'short', angularFormatter)).toBe('yyyy/MM/dd HH:mm'); + expect(DateTimeUtil.getNumericInputFormat(locale, 'shortDate', angularFormatter)).toBe('yyyy/MM/dd'); + expect(DateTimeUtil.getNumericInputFormat(locale, 'shortTime', angularFormatter).normalize('NFKD')).toBe('HH:mm'); + expect(DateTimeUtil.getNumericInputFormat(locale, 'mediumTime', angularFormatter).normalize('NFKD')).toBe('HH:mm:ss'); // returns the same format if it is custom and numeric - expect(DateTimeUtil.getNumericInputFormat(locale, 'dd-MM-yyyy')).toBe('dd-MM-yyyy'); - expect(DateTimeUtil.getNumericInputFormat(locale, 'dd/M/yyyy hh:mm:ss:SS aa')).toBe('dd/M/yyyy hh:mm:ss:SS aa'); + expect(DateTimeUtil.getNumericInputFormat(locale, 'dd-MM-yyyy', angularFormatter)).toBe('dd-MM-yyyy'); + expect(DateTimeUtil.getNumericInputFormat(locale, 'dd/M/yyyy hh:mm:ss:SS aa', angularFormatter)).toBe('dd/M/yyyy hh:mm:ss:SS aa'); // returns empty string if predefined and not among the numeric ones - expect(DateTimeUtil.getNumericInputFormat(locale, 'medium')).toBe(''); - expect(DateTimeUtil.getNumericInputFormat(locale, 'mediumDate')).toBe(''); - expect(DateTimeUtil.getNumericInputFormat(locale, 'longTime')).toBe(''); + expect(DateTimeUtil.getNumericInputFormat(locale, 'medium', angularFormatter)).toBe(''); + expect(DateTimeUtil.getNumericInputFormat(locale, 'mediumDate', angularFormatter)).toBe(''); + expect(DateTimeUtil.getNumericInputFormat(locale, 'longTime', angularFormatter)).toBe(''); }); }); 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..d07200b8793 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,9 @@ 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 { DataType } from '../../data-operations/data-util'; +import { getDateFormatter } from 'igniteui-i18n-core'; +import { BaseFormatter } from '../../core/i18n/formatters/formatter-base'; /** @hidden */ const enum FormatDesc { @@ -250,55 +251,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 (!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); - } - - /** 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 getDateFormatter().getLocaleDateTimeFormat(locale, true, DateTimeUtil.getFormatOptions(dataType)); } /** Determines if a given character is `d/M/y` or `h/m/s`. */ @@ -529,7 +482,7 @@ export abstract class DateTimeUtil { return false; } - public static isFormatNumeric(locale: string, inputFormat: string): boolean { + public static isFormatNumeric(locale: string, inputFormat: string, formatter: BaseFormatter): boolean { const dateParts = DateTimeUtil.parseDateTimeFormat(inputFormat); if (predefinedNonNumericFormats.has(inputFormat) || dateParts.every(p => p.type === DatePart.Literal)) { return false; @@ -538,7 +491,7 @@ export abstract class DateTimeUtil { if (dateParts[i].type === DatePart.AmPm || dateParts[i].type === DatePart.Literal) { continue; } - const transformedValue = formatDate(new Date(), dateParts[i].format, locale); + const transformedValue = formatter.formatDate(new Date(), dateParts[i].format, locale); // check if the transformed date/time part contains any kind of letter from any language if (/\p{L}+/gu.test(transformedValue)) { return false; @@ -554,7 +507,7 @@ export abstract class DateTimeUtil { * for the corresponding numeric date parts * - otherwise, return an empty string */ - public static getNumericInputFormat(locale: string, format: string): string { + public static getNumericInputFormat(locale: string, format: string, formatter: BaseFormatter): string { let resultFormat = ''; if (!format) { return resultFormat; @@ -562,7 +515,7 @@ export abstract class DateTimeUtil { if (predefinedNumericFormats.has(format)) { resultFormat = DateTimeUtil.getLocaleInputFormatFromParts(locale, predefinedNumericFormats.get(format)); - } else if (DateTimeUtil.isFormatNumeric(locale, format)) { + } else if (DateTimeUtil.isFormatNumeric(locale, format, formatter)) { resultFormat = format; } return resultFormat; @@ -578,10 +531,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 +550,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 +639,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..bc89fbefdde 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 @@ -1,4 +1,4 @@ -import { Component, ContentChild, Pipe, PipeTransform, Directive } from '@angular/core'; +import { Component, ContentChild, Pipe, PipeTransform, Directive, Inject, inject } from '@angular/core'; import { NgControl } from '@angular/forms'; import { IgxInputDirective, IgxInputState } from '../input-group/public_api'; import { IgxInputGroupComponent } from '../input-group/input-group.component'; @@ -11,6 +11,7 @@ import { IgxSuffixDirective } from '../directives/suffix/suffix.directive'; import { IgxButtonDirective } from '../directives/button/button.directive'; import { IgxPrefixDirective } from '../directives/prefix/prefix.directive'; import { NgTemplateOutlet } from '@angular/common'; +import { BaseFormatter, I18N_FORMATTER } from '../core/i18n/formatters/formatter-base'; /** Represents a range between two dates. */ export interface DateRange { @@ -29,6 +30,8 @@ export interface CustomDateRange { standalone: true }) export class DateRangePickerFormatPipe implements PipeTransform { + private i18nFormatter = inject(I18N_FORMATTER); + public transform(values: DateRange, appliedFormat?: string, locale?: string, formatter?: (_: DateRange) => string): string { if (!values || !values.start && !values.end) { @@ -44,8 +47,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 ? this.i18nFormatter.formatDate(start, appliedFormat, locale || 'en') : start?.toLocaleDateString(); + const endDate = appliedFormat ? this.i18nFormatter.formatDate(end, appliedFormat, locale || 'en') : end?.toLocaleDateString(); let formatted; if (start) { formatted = `${startDate} - `; diff --git a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts index 5027775638d..0ca10b12cf4 100644 --- a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts +++ b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts @@ -436,7 +436,7 @@ export class IgxDateRangePickerComponent extends PickerBaseDirective /** @hidden @internal */ public get appliedFormat(): string { - return DateTimeUtil.getLocaleDateFormat(this.locale, this.displayFormat) + return this.i18nFormatter.getLocaleDateFormat(this.locale, this.displayFormat) || DateTimeUtil.DEFAULT_INPUT_FORMAT; } 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..5c0df14f1b7 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 @@ -14,6 +14,7 @@ import { IgxDateTimeEditorEventArgs, DatePartInfo, DatePart } from './date-time- import { noop } from 'rxjs'; import { DatePartDeltas } from './date-time-editor.common'; import { DateTimeUtil } from '../../date-common/util/date-time.util'; +import { BaseFormatter, I18N_FORMATTER } from '../../core/i18n/formatters/formatter-base'; /** * Date Time Editor provides a functionality to input, edit and format date and time. @@ -139,7 +140,7 @@ export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnCh } public get displayFormat(): string { - return this._displayFormat || this.inputFormat; + return this._displayFormat || this._inputFormat || this._i18nFormatter.getLocaleDateFormat(this.locale, 'short'); } /** @@ -303,7 +304,8 @@ export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnCh maskParser: MaskParsingService, platform: PlatformUtil, @Inject(DOCUMENT) private _document: any, - @Inject(LOCALE_ID) private _locale: any) { + @Inject(LOCALE_ID) private _locale: any, + @Inject(I18N_FORMATTER) private _i18nFormatter: BaseFormatter,) { super(elementRef, maskParser, renderer, platform); this.document = this._document as Document; this.locale = this.locale || this._locale; @@ -526,7 +528,7 @@ export class IgxDateTimeEditorDirective extends IgxMaskDirective implements OnCh protected override setPlaceholder(_value: string): void { } private updateDefaultFormat(): void { - this._defaultInputFormat = DateTimeUtil.getNumericInputFormat(this.locale, this._displayFormat) + this._defaultInputFormat = DateTimeUtil.getNumericInputFormat(this.locale, this._displayFormat, this._i18nFormatter) || DateTimeUtil.getDefaultInputFormat(this.locale, this.defaultFormatType); this.setMask(this.inputFormat); } @@ -549,7 +551,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 = this._i18nFormatter.formatDate(this.dateValue, format.replace('tt', 'aa'), this.locale); } else { this.inputValue = this.dateValue.toLocaleString(); }