11import { DatePart , DatePartInfo } from '../../directives/date-time-editor/date-time-editor.common' ;
2- import { formatDate , FormatWidth , getLocaleDateFormat } from '@angular/common' ;
32import { ValidationErrors } from '@angular/forms' ;
43import { isDate } from '../../core/utils' ;
54import { DataType } from '../../data-operations/data-util' ;
5+ import { getDateFormatter } from 'igniteui-i18n-core' ;
6+ import { BaseFormatter } from '../../core/i18n/formatters/formatter-base' ;
67
78/** @hidden */
89const enum FormatDesc {
@@ -250,55 +251,7 @@ export abstract class DateTimeUtil {
250251 /** Builds a date-time editor's default input format based on provided locale settings and data type. */
251252 public static getDefaultInputFormat ( locale : string , dataType : DataType = DataType . Date ) : string {
252253 locale = locale || DateTimeUtil . DEFAULT_LOCALE ;
253- if ( ! Intl || ! Intl . DateTimeFormat || ! Intl . DateTimeFormat . prototype . formatToParts ) {
254- // TODO: fallback with Intl.format for IE?
255- return DateTimeUtil . DEFAULT_INPUT_FORMAT ;
256- }
257- const parts = DateTimeUtil . getDefaultLocaleMask ( locale , dataType ) ;
258- parts . forEach ( p => {
259- if ( p . type !== DatePart . Year && p . type !== DateTimeUtil . SEPARATOR && p . type !== DatePart . AmPm ) {
260- p . formatType = FormatDesc . TwoDigits ;
261- }
262- } ) ;
263-
264- return DateTimeUtil . getMask ( parts ) ;
265- }
266-
267- /** Tries to format a date using Angular's DatePipe. Fallbacks to `Intl` if no locale settings have been loaded. */
268- public static formatDate ( value : number | Date , format : string , locale : string , timezone ?: string ) : string {
269- let formattedDate : string ;
270- try {
271- formattedDate = formatDate ( value , format , locale , timezone ) ;
272- } catch {
273- DateTimeUtil . logMissingLocaleSettings ( locale ) ;
274- const formatter = new Intl . DateTimeFormat ( locale ) ;
275- formattedDate = formatter . format ( value ) ;
276- }
277-
278- return formattedDate ;
279- }
280-
281- /**
282- * Returns the date format based on a provided locale.
283- * Supports Angular's DatePipe format options such as `shortDate`, `longDate`.
284- */
285- public static getLocaleDateFormat ( locale : string , displayFormat ?: string ) : string {
286- const formatKeys = Object . keys ( FormatWidth ) as ( keyof FormatWidth ) [ ] ;
287- const targetKey = formatKeys . find ( k => k . toLowerCase ( ) === displayFormat ?. toLowerCase ( ) . replace ( 'date' , '' ) ) ;
288- if ( ! targetKey ) {
289- // if displayFormat is not shortDate, longDate, etc.
290- // or if it is not set by the user
291- return displayFormat ;
292- }
293- let format : string ;
294- try {
295- format = getLocaleDateFormat ( locale , FormatWidth [ targetKey ] ) ;
296- } catch {
297- DateTimeUtil . logMissingLocaleSettings ( locale ) ;
298- format = DateTimeUtil . getDefaultInputFormat ( locale ) ;
299- }
300-
301- return format ;
254+ return getDateFormatter ( ) . getLocaleDateTimeFormat ( locale , true , DateTimeUtil . getFormatOptions ( dataType ) ) ;
302255 }
303256
304257 /** Determines if a given character is `d/M/y` or `h/m/s`. */
@@ -529,7 +482,7 @@ export abstract class DateTimeUtil {
529482 return false ;
530483 }
531484
532- public static isFormatNumeric ( locale : string , inputFormat : string ) : boolean {
485+ public static isFormatNumeric ( locale : string , inputFormat : string , formatter : BaseFormatter ) : boolean {
533486 const dateParts = DateTimeUtil . parseDateTimeFormat ( inputFormat ) ;
534487 if ( predefinedNonNumericFormats . has ( inputFormat ) || dateParts . every ( p => p . type === DatePart . Literal ) ) {
535488 return false ;
@@ -538,7 +491,7 @@ export abstract class DateTimeUtil {
538491 if ( dateParts [ i ] . type === DatePart . AmPm || dateParts [ i ] . type === DatePart . Literal ) {
539492 continue ;
540493 }
541- const transformedValue = formatDate ( new Date ( ) , dateParts [ i ] . format , locale ) ;
494+ const transformedValue = formatter . formatDate ( new Date ( ) , dateParts [ i ] . format , locale ) ;
542495 // check if the transformed date/time part contains any kind of letter from any language
543496 if ( / \p{ L} + / gu. test ( transformedValue ) ) {
544497 return false ;
@@ -554,15 +507,15 @@ export abstract class DateTimeUtil {
554507 * for the corresponding numeric date parts
555508 * - otherwise, return an empty string
556509 */
557- public static getNumericInputFormat ( locale : string , format : string ) : string {
510+ public static getNumericInputFormat ( locale : string , format : string , formatter : BaseFormatter ) : string {
558511 let resultFormat = '' ;
559512 if ( ! format ) {
560513 return resultFormat ;
561514 }
562515 if ( predefinedNumericFormats . has ( format ) ) {
563516 resultFormat = DateTimeUtil . getLocaleInputFormatFromParts ( locale , predefinedNumericFormats . get ( format ) ) ;
564517
565- } else if ( DateTimeUtil . isFormatNumeric ( locale , format ) ) {
518+ } else if ( DateTimeUtil . isFormatNumeric ( locale , format , formatter ) ) {
566519 resultFormat = format ;
567520 }
568521 return resultFormat ;
@@ -578,10 +531,8 @@ export abstract class DateTimeUtil {
578531 options [ p ] = FormatDesc . TwoDigits ;
579532 }
580533 } ) ;
581- const formatter = new Intl . DateTimeFormat ( locale , options ) ;
582- const dateStruct = DateTimeUtil . getDateStructFromParts ( formatter . formatToParts ( new Date ( ) ) , formatter ) ;
583- DateTimeUtil . fillDatePartsPositions ( dateStruct ) ;
584- return DateTimeUtil . getMask ( dateStruct ) ;
534+
535+ return getDateFormatter ( ) . getLocaleDateTimeFormat ( locale , true , options ) ;
585536 }
586537
587538 private static addCurrentPart ( currentPart : DatePartInfo , dateTimeParts : DatePartInfo [ ] ) : void {
@@ -599,70 +550,6 @@ export abstract class DateTimeUtil {
599550 return result ;
600551 }
601552
602- private static getMask ( dateStruct : any [ ] ) : string {
603- const mask = [ ] ;
604- for ( const part of dateStruct ) {
605- if ( part . formatType === FormatDesc . Numeric ) {
606- switch ( part . type ) {
607- case DateParts . Day :
608- mask . push ( 'd' ) ;
609- break ;
610- case DateParts . Month :
611- mask . push ( 'M' ) ;
612- break ;
613- case DateParts . Year :
614- mask . push ( 'yyyy' ) ;
615- break ;
616- case DateParts . Hour :
617- mask . push ( part . hour12 ? 'h' : 'H' ) ;
618- break ;
619- case DateParts . Minute :
620- mask . push ( 'm' ) ;
621- break ;
622- case DateParts . Second :
623- mask . push ( 's' ) ;
624- break ;
625- }
626- } else if ( part . formatType === FormatDesc . TwoDigits ) {
627- switch ( part . type ) {
628- case DateParts . Day :
629- mask . push ( 'dd' ) ;
630- break ;
631- case DateParts . Month :
632- mask . push ( 'MM' ) ;
633- break ;
634- case DateParts . Year :
635- mask . push ( 'yy' ) ;
636- break ;
637- case DateParts . Hour :
638- mask . push ( part . hour12 ? 'hh' : 'HH' ) ;
639- break ;
640- case DateParts . Minute :
641- mask . push ( 'mm' ) ;
642- break ;
643- case DateParts . Second :
644- mask . push ( 'ss' ) ;
645- break ;
646- }
647- }
648-
649- if ( part . type === DateParts . AmPm ) {
650- mask . push ( 'tt' ) ;
651- }
652-
653- if ( part . type === DateTimeUtil . SEPARATOR ) {
654- mask . push ( part . value ) ;
655- }
656- }
657-
658- return mask . join ( '' ) ;
659- }
660-
661- private static logMissingLocaleSettings ( locale : string ) : void {
662- console . warn ( `Missing locale data for the locale ${ locale } . Please refer to https://angular.io/guide/i18n#i18n-pipes` ) ;
663- console . warn ( 'Using default browser locale settings.' ) ;
664- }
665-
666553 private static prependValue ( value : number , partLength : number , prependChar : string ) : string {
667554 return ( prependChar + value . toString ( ) ) . slice ( - partLength ) ;
668555 }
@@ -752,102 +639,4 @@ export abstract class DateTimeUtil {
752639 return { } ;
753640 }
754641 }
755-
756- private static getDefaultLocaleMask ( locale : string , dataType : DataType = DataType . Date ) {
757- const options = DateTimeUtil . getFormatOptions ( dataType ) ;
758- const formatter = new Intl . DateTimeFormat ( locale , options ) ;
759- const formatToParts = formatter . formatToParts ( new Date ( ) ) ;
760- const dateStruct = DateTimeUtil . getDateStructFromParts ( formatToParts , formatter ) ;
761- DateTimeUtil . fillDatePartsPositions ( dateStruct ) ;
762- return dateStruct ;
763- }
764-
765- private static getDateStructFromParts ( parts : Intl . DateTimeFormatPart [ ] , formatter : Intl . DateTimeFormat ) : any [ ] {
766- const dateStruct = [ ] ;
767- for ( const part of parts ) {
768- if ( part . type === DateTimeUtil . SEPARATOR ) {
769- dateStruct . push ( {
770- type : DateTimeUtil . SEPARATOR ,
771- value : part . value
772- } ) ;
773- } else {
774- dateStruct . push ( {
775- type : part . type
776- } ) ;
777- }
778- }
779- const formatterOptions = formatter . resolvedOptions ( ) ;
780- for ( const part of dateStruct ) {
781- switch ( part . type ) {
782- case DateParts . Day : {
783- part . formatType = formatterOptions . day ;
784- break ;
785- }
786- case DateParts . Month : {
787- part . formatType = formatterOptions . month ;
788- break ;
789- }
790- case DateParts . Year : {
791- part . formatType = formatterOptions . year ;
792- break ;
793- }
794- case DateParts . Hour : {
795- part . formatType = formatterOptions . hour ;
796- if ( formatterOptions . hour12 ) {
797- part . hour12 = true ;
798- }
799- break ;
800- }
801- case DateParts . Minute : {
802- part . formatType = formatterOptions . minute ;
803- break ;
804- }
805- case DateParts . Second : {
806- part . formatType = formatterOptions . second ;
807- break ;
808- }
809- case DateParts . AmPm : {
810- part . formatType = formatterOptions . dayPeriod ;
811- break ;
812- }
813- }
814- }
815- return dateStruct ;
816- }
817-
818- private static fillDatePartsPositions ( dateArray : any [ ] ) : void {
819- let currentPos = 0 ;
820-
821- for ( const part of dateArray ) {
822- // Day|Month|Hour|Minute|Second|AmPm part positions
823- if ( part . type === DateParts . Day || part . type === DateParts . Month ||
824- part . type === DateParts . Hour || part . type === DateParts . Minute || part . type === DateParts . Second ||
825- part . type === DateParts . AmPm
826- ) {
827- // Offset 2 positions for number
828- part . position = [ currentPos , currentPos + 2 ] ;
829- currentPos += 2 ;
830- } else if ( part . type === DateParts . Year ) {
831- // Year part positions
832- switch ( part . formatType ) {
833- case FormatDesc . Numeric : {
834- // Offset 4 positions for full year
835- part . position = [ currentPos , currentPos + 4 ] ;
836- currentPos += 4 ;
837- break ;
838- }
839- case FormatDesc . TwoDigits : {
840- // Offset 2 positions for short year
841- part . position = [ currentPos , currentPos + 2 ] ;
842- currentPos += 2 ;
843- break ;
844- }
845- }
846- } else if ( part . type === DateTimeUtil . SEPARATOR ) {
847- // Separator positions
848- part . position = [ currentPos , currentPos + 1 ] ;
849- currentPos ++ ;
850- }
851- }
852- }
853642}
0 commit comments