-
Notifications
You must be signed in to change notification settings - Fork 595
DateTimeFormatter: Dynamically augment skeleton #604
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,3 +7,4 @@ before_install: | |
| install: | ||
| - npm install | ||
| - bower install | ||
| sudo: false | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,8 @@ | ||
| define([ | ||
| "../common/format-message", | ||
| "../common/create-error/invalid-parameter-value" | ||
| ], function( formatMessage, createErrorInvalidParameterValue ) { | ||
| "../common/create-error/invalid-parameter-value", | ||
| "./pattern-re" | ||
| ], function( formatMessage, createErrorInvalidParameterValue, datePatternRe ) { | ||
|
|
||
| /** | ||
| * expandPattern( options, cldr ) | ||
|
|
@@ -26,7 +27,7 @@ define([ | |
| */ | ||
|
|
||
| return function( options, cldr ) { | ||
| var dateSkeleton, result, skeleton, timeSkeleton, type; | ||
| var dateSkeleton, result, skeleton, timeSkeleton, type, dateTimeSkeleton; | ||
|
|
||
| function combineDateTime( type, datePattern, timePattern ) { | ||
| return formatMessage( | ||
|
|
@@ -38,6 +39,128 @@ return function( options, cldr ) { | |
| ); | ||
| } | ||
|
|
||
| function getBestMatchPattern( path, skeleton ) { | ||
| var availableFormats, ratedFormats, format, pattern; | ||
|
|
||
| pattern = cldr.main([ path, skeleton ]); | ||
|
|
||
| if ( skeleton && !pattern ) { | ||
| availableFormats = cldr.main([ path ]); | ||
| ratedFormats = []; | ||
|
|
||
| for ( format in availableFormats ) { | ||
| ratedFormats.push({ | ||
| format: format, | ||
| pattern: availableFormats[format], | ||
| rate: compareFormats( skeleton, format ) | ||
| }); | ||
| } | ||
|
|
||
| ratedFormats = ratedFormats | ||
| .filter( function( format ) { | ||
| return format.rate > -1; | ||
| } ) | ||
| .sort( function( formatA, formatB ) { | ||
| return formatA.rate - formatB.rate; | ||
| }); | ||
|
|
||
| if ( ratedFormats.length ) { | ||
| pattern = augmentFormat( skeleton, ratedFormats[0].pattern ); | ||
| } | ||
| } | ||
|
|
||
| return pattern; | ||
| } | ||
|
|
||
| function repeatStr( str, count ) { | ||
| var i, result = ""; | ||
| for ( i = 0; i < count; i++ ) { | ||
| result = result + str; | ||
| } | ||
| return result; | ||
| } | ||
|
|
||
| function normalizePatternType( char ) { | ||
| switch ( char ) { | ||
| case "e": | ||
| case "E": | ||
| case "c": | ||
| return "e"; | ||
|
|
||
| case "M": | ||
| case "L": | ||
| return "L"; | ||
|
|
||
| default: | ||
| return char; | ||
| } | ||
| } | ||
|
|
||
| function compareFormats( formatA, formatB ) { | ||
| var distance, | ||
| typeA, | ||
| typeB, | ||
| matchFound, | ||
| i, | ||
| j; | ||
|
|
||
| if ( formatA === formatB ) { | ||
| return 0; | ||
| } | ||
|
|
||
| formatA = formatA.match( datePatternRe ); | ||
| formatB = formatB.match( datePatternRe ); | ||
| if ( formatA.length === formatB.length ) { | ||
| distance = 1; | ||
| for ( i = 0; i < formatA.length; i++ ) { | ||
| typeA = normalizePatternType( formatA[i].charAt( 0 ) ); | ||
| typeB = null; | ||
| matchFound = false; | ||
| for ( j = 0; j < formatB.length; j++ ) { | ||
| typeB = normalizePatternType( formatB[j].charAt( 0 ) ); | ||
| if ( typeA === typeB ) { | ||
| break; | ||
| } else { | ||
| typeB = null; | ||
| } | ||
| } | ||
| if ( null === typeB ) { | ||
| return -1; | ||
| } | ||
| distance = distance + Math.abs( formatA[i].length - formatB[j].length ); | ||
| if ( formatA[i].charAt( 0 ) !== formatB[j].charAt( 0 ) ) { | ||
| distance = distance + 1; | ||
| } | ||
| } | ||
| return distance; | ||
| } | ||
| return -1; | ||
| } | ||
|
|
||
| function augmentFormat( requestedSkeleton, bestMatchFormat ) { | ||
| var i, j, matchedType, matchedLength, requestedType, requestedLength; | ||
|
|
||
| requestedSkeleton = requestedSkeleton.match( datePatternRe ); | ||
| bestMatchFormat = bestMatchFormat.match( datePatternRe ); | ||
|
|
||
| for ( i = 0; i < bestMatchFormat.length; i++ ) { | ||
| matchedType = bestMatchFormat[i].charAt( 0 ); | ||
| matchedLength = bestMatchFormat[i].length; | ||
| for ( j = 0; j < requestedSkeleton.length; j++ ) { | ||
| requestedType = requestedSkeleton[j].charAt( 0 ); | ||
| requestedLength = requestedSkeleton[j].length; | ||
| if ( | ||
| normalizePatternType( matchedType ) === normalizePatternType( requestedType ) && | ||
| matchedLength < requestedLength | ||
| ) { | ||
| bestMatchFormat[i] = repeatStr( matchedType, requestedLength ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return bestMatchFormat.join( "" ); | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In general about the functions above, can
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mean some sort of caching? But this could be a memory issue... |
||
|
|
||
| switch ( true ) { | ||
| case "skeleton" in options: | ||
| skeleton = options.skeleton; | ||
|
|
@@ -48,25 +171,38 @@ return function( options, cldr ) { | |
| if ( !result ) { | ||
| timeSkeleton = skeleton.split( /[^hHKkmsSAzZOvVXx]/ ).slice( -1 )[ 0 ]; | ||
| dateSkeleton = skeleton.split( /[^GyYuUrQqMLlwWdDFgEec]/ )[ 0 ]; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's defer this initialization by moving them both inside the |
||
| if ( /(MMMM|LLLL).*[Ec]/.test( dateSkeleton ) ) { | ||
| type = "full"; | ||
| } else if ( /MMMM/g.test( dateSkeleton ) ) { | ||
| type = "long"; | ||
| } else if ( /MMM/g.test( dateSkeleton ) || /LLL/g.test( dateSkeleton ) ) { | ||
| type = "medium"; | ||
| dateTimeSkeleton = getBestMatchPattern( | ||
| "dates/calendars/gregorian/dateTimeFormats/availableFormats", | ||
| skeleton | ||
| ); | ||
| if ( dateTimeSkeleton ) { | ||
| result = dateTimeSkeleton; | ||
| } else { | ||
| type = "short"; | ||
| } | ||
| result = combineDateTime( type, | ||
| cldr.main([ | ||
| dateSkeleton = getBestMatchPattern( | ||
| "dates/calendars/gregorian/dateTimeFormats/availableFormats", | ||
| dateSkeleton | ||
| ]), | ||
| cldr.main([ | ||
| ); | ||
| timeSkeleton = getBestMatchPattern( | ||
| "dates/calendars/gregorian/dateTimeFormats/availableFormats", | ||
| timeSkeleton | ||
| ]) | ||
| ); | ||
| ); | ||
|
|
||
| if ( /(MMMM|LLLL).*[Ec]/.test( dateSkeleton ) ) { | ||
| type = "full"; | ||
| } else if ( /MMMM/g.test( dateSkeleton ) ) { | ||
| type = "long"; | ||
| } else if ( /MMM/g.test( dateSkeleton ) || /LLL/g.test( dateSkeleton ) ) { | ||
| type = "medium"; | ||
| } else { | ||
| type = "short"; | ||
| } | ||
|
|
||
| if ( dateSkeleton && timeSkeleton ) { | ||
| result = combineDateTime( type, dateSkeleton, timeSkeleton ); | ||
| } else { | ||
| result = dateSkeleton || timeSkeleton; | ||
| } | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In general, the whole block above is getting too indented. Let's change it. Currently, we have something like this: tryDirectMap()
if (!directMap) {
tryToMatchIt()
if (!match) {
tryToMatchItsIndividualParts()
}
}Let's re-arrange it so we have: tryDirectMap()
if (directMap) {
break;
}
tryToMatchIt()
if (match) {
break;
}
tryToMatchItsIndividualParts()
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. About the |
||
| } | ||
| break; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's move this function into
./src/util/string/repeat-str.js. Maybe./src/util/string/pad.jscould reuse it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could use
String.prototype.repeatwith some of es6-shim?