11define ( [
22 "../common/format-message" ,
33 "../common/create-error/invalid-parameter-value" ,
4- "./pattern-re"
5- ] , function ( formatMessage , createErrorInvalidParameterValue , datePatternRe ) {
4+ "./expand-pattern/get-best-match-pattern"
5+ ] , function ( formatMessage , createErrorInvalidParameterValue ,
6+ dateExpandPatternGetBestMatchPattern ) {
67
78/**
89 * expandPattern( options, cldr )
@@ -25,9 +26,11 @@ define([
2526 * - { datetime: "full" } returns "EEEE, MMMM d, y 'at' h:mm:ss a zzzz";
2627 * - { raw: "dd/mm" } returns "dd/mm";
2728 */
28-
2929return function ( options , cldr ) {
30- var dateSkeleton , result , skeleton , timeSkeleton , type , dateTimeSkeleton ;
30+ var dateSkeleton , result , skeleton , timeSkeleton , type ,
31+
32+ // Using easier to read variables.
33+ getBestMatchPattern = dateExpandPatternGetBestMatchPattern ;
3134
3235 function combineDateTime ( type , datePattern , timePattern ) {
3336 return formatMessage (
@@ -39,171 +42,54 @@ return function( options, cldr ) {
3942 ) ;
4043 }
4144
42- function getBestMatchPattern ( path , skeleton ) {
43- var availableFormats , ratedFormats , format , pattern ;
44-
45- pattern = cldr . main ( [ path , skeleton ] ) ;
46-
47- if ( skeleton && ! pattern ) {
48- availableFormats = cldr . main ( [ path ] ) ;
49- ratedFormats = [ ] ;
50-
51- for ( format in availableFormats ) {
52- ratedFormats . push ( {
53- format : format ,
54- pattern : availableFormats [ format ] ,
55- rate : compareFormats ( skeleton , format )
56- } ) ;
57- }
45+ switch ( true ) {
46+ case "skeleton" in options :
47+ skeleton = options . skeleton ;
5848
59- ratedFormats = ratedFormats
60- . filter ( function ( format ) {
61- return format . rate > - 1 ;
62- } )
63- . sort ( function ( formatA , formatB ) {
64- return formatA . rate - formatB . rate ;
65- } ) ;
49+ // Preferred hour (j).
50+ skeleton = skeleton . replace ( / j / g, cldr . supplemental . timeData . preferred ( ) ) ;
6651
67- if ( ratedFormats . length ) {
68- pattern = augmentFormat ( skeleton , ratedFormats [ 0 ] . pattern ) ;
52+ // Try direct map (note that getBestMatchPattern handles it).
53+ // ... or, try to "best match" the whole skeleton.
54+ result = getBestMatchPattern (
55+ cldr ,
56+ "dates/calendars/gregorian/dateTimeFormats/availableFormats" ,
57+ skeleton
58+ ) ;
59+ if ( result ) {
60+ break ;
6961 }
70- }
71-
72- return pattern ;
73- }
74-
75- function repeatStr ( str , count ) {
76- var i , result = "" ;
77- for ( i = 0 ; i < count ; i ++ ) {
78- result = result + str ;
79- }
80- return result ;
81- }
82-
83- function normalizePatternType ( char ) {
84- switch ( char ) {
85- case "e" :
86- case "E" :
87- case "c" :
88- return "e" ;
8962
90- case "M" :
91- case "L" :
92- return "L" ;
93-
94- default :
95- return char ;
96- }
97- }
63+ // ... or, try to "best match" the date and time parts individually.
64+ timeSkeleton = skeleton . split ( / [ ^ h H K k m s S A z Z O v V X x ] / ) . slice ( - 1 ) [ 0 ] ;
65+ dateSkeleton = skeleton . split ( / [ ^ G y Y u U r Q q M L l w W d D F g E e c ] / ) [ 0 ] ;
66+ dateSkeleton = getBestMatchPattern (
67+ cldr ,
68+ "dates/calendars/gregorian/dateTimeFormats/availableFormats" ,
69+ dateSkeleton
70+ ) ;
71+ timeSkeleton = getBestMatchPattern (
72+ cldr ,
73+ "dates/calendars/gregorian/dateTimeFormats/availableFormats" ,
74+ timeSkeleton
75+ ) ;
9876
99- function compareFormats ( formatA , formatB ) {
100- var distance ,
101- typeA ,
102- typeB ,
103- matchFound ,
104- i ,
105- j ;
106-
107- if ( formatA === formatB ) {
108- return 0 ;
109- }
110-
111- formatA = formatA . match ( datePatternRe ) ;
112- formatB = formatB . match ( datePatternRe ) ;
113- if ( formatA . length === formatB . length ) {
114- distance = 1 ;
115- for ( i = 0 ; i < formatA . length ; i ++ ) {
116- typeA = normalizePatternType ( formatA [ i ] . charAt ( 0 ) ) ;
117- typeB = null ;
118- matchFound = false ;
119- for ( j = 0 ; j < formatB . length ; j ++ ) {
120- typeB = normalizePatternType ( formatB [ j ] . charAt ( 0 ) ) ;
121- if ( typeA === typeB ) {
122- break ;
123- } else {
124- typeB = null ;
125- }
126- }
127- if ( null === typeB ) {
128- return - 1 ;
129- }
130- distance = distance + Math . abs ( formatA [ i ] . length - formatB [ j ] . length ) ;
131- if ( formatA [ i ] . charAt ( 0 ) !== formatB [ j ] . charAt ( 0 ) ) {
132- distance = distance + 1 ;
133- }
77+ if ( / ( M M M M | L L L L ) .* [ E c ] / . test ( dateSkeleton ) ) {
78+ type = "full" ;
79+ } else if ( / M M M M | L L L L / . test ( dateSkeleton ) ) {
80+ type = "long" ;
81+ } else if ( / M M M | L L L / . test ( dateSkeleton ) ) {
82+ type = "medium" ;
83+ } else {
84+ type = "short" ;
13485 }
135- return distance ;
136- }
137- return - 1 ;
138- }
13986
140- function augmentFormat ( requestedSkeleton , bestMatchFormat ) {
141- var i , j , matchedType , matchedLength , requestedType , requestedLength ;
142-
143- requestedSkeleton = requestedSkeleton . match ( datePatternRe ) ;
144- bestMatchFormat = bestMatchFormat . match ( datePatternRe ) ;
145-
146- for ( i = 0 ; i < bestMatchFormat . length ; i ++ ) {
147- matchedType = bestMatchFormat [ i ] . charAt ( 0 ) ;
148- matchedLength = bestMatchFormat [ i ] . length ;
149- for ( j = 0 ; j < requestedSkeleton . length ; j ++ ) {
150- requestedType = requestedSkeleton [ j ] . charAt ( 0 ) ;
151- requestedLength = requestedSkeleton [ j ] . length ;
152- if (
153- normalizePatternType ( matchedType ) === normalizePatternType ( requestedType ) &&
154- matchedLength < requestedLength
155- ) {
156- bestMatchFormat [ i ] = repeatStr ( matchedType , requestedLength ) ;
157- }
87+ if ( dateSkeleton && timeSkeleton ) {
88+ result = combineDateTime ( type , dateSkeleton , timeSkeleton ) ;
89+ } else {
90+ result = dateSkeleton || timeSkeleton ;
15891 }
159- }
160-
161- return bestMatchFormat . join ( "" ) ;
162- }
16392
164- switch ( true ) {
165- case "skeleton" in options :
166- skeleton = options . skeleton ;
167- result = cldr . main ( [
168- "dates/calendars/gregorian/dateTimeFormats/availableFormats" ,
169- skeleton
170- ] ) ;
171- if ( ! result ) {
172- timeSkeleton = skeleton . split ( / [ ^ h H K k m s S A z Z O v V X x ] / ) . slice ( - 1 ) [ 0 ] ;
173- dateSkeleton = skeleton . split ( / [ ^ G y Y u U r Q q M L l w W d D F g E e c ] / ) [ 0 ] ;
174- dateTimeSkeleton = getBestMatchPattern (
175- "dates/calendars/gregorian/dateTimeFormats/availableFormats" ,
176- skeleton
177- ) ;
178- if ( dateTimeSkeleton ) {
179- result = dateTimeSkeleton ;
180- } else {
181- dateSkeleton = getBestMatchPattern (
182- "dates/calendars/gregorian/dateTimeFormats/availableFormats" ,
183- dateSkeleton
184- ) ;
185- timeSkeleton = getBestMatchPattern (
186- "dates/calendars/gregorian/dateTimeFormats/availableFormats" ,
187- timeSkeleton
188- ) ;
189-
190- if ( / ( M M M M | L L L L ) .* [ E c ] / . test ( dateSkeleton ) ) {
191- type = "full" ;
192- } else if ( / M M M M / g. test ( dateSkeleton ) ) {
193- type = "long" ;
194- } else if ( / M M M / g. test ( dateSkeleton ) || / L L L / g. test ( dateSkeleton ) ) {
195- type = "medium" ;
196- } else {
197- type = "short" ;
198- }
199-
200- if ( dateSkeleton && timeSkeleton ) {
201- result = combineDateTime ( type , dateSkeleton , timeSkeleton ) ;
202- } else {
203- result = dateSkeleton || timeSkeleton ;
204- }
205- }
206- }
20793 break ;
20894
20995 case "date" in options :
0 commit comments