Skip to content

Commit

Permalink
Date: Assert options.skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
rxaviers committed May 22, 2017
1 parent 9389955 commit 49a4eb1
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 10 deletions.
48 changes: 48 additions & 0 deletions src/common/validate/skeleton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
define([
"../create-error",
"./skeleton/fields-pos-map"
], function( createError, validateSkeletonFieldsPosMap ) {

/**
* validateSkeleton( skeleton )
*
* skeleton: Assume `j` has already been converted into a localized hour field.
*/
return function validateSkeleton( skeleton ) {
var last,

// Using easier to read variable.
fieldsPosMap = validateSkeletonFieldsPosMap;

// "The fields are from the Date Field Symbol Table in Date Format Patterns"
// Ref: http://www.unicode.org/reports/tr35/tr35-dates.html#availableFormats_appendItems
// I.e., check for invalid characters.
skeleton.replace( /[^GyYuUrQqMLlwWEecdDFghHKkmsSAzZOvVXx]/, function( field ) {
throw createError(
"E_INVALID_OPTIONS", "Invalid field `{field}` of skeleton `{skeleton}`",
{
field: field,
skeleton: skeleton
}
);
});

// "The canonical order is from top to bottom in that table; that is, yM not My".
// http://www.unicode.org/reports/tr35/tr35-dates.html#availableFormats_appendItems
// I.e., check for invalid order.
skeleton.split( "" ).every(function( field ) {
if ( fieldsPosMap[ field ] < last ) {
throw createError(
"E_INVALID_OPTIONS", "Invalid order `{field}` of skeleton `{skeleton}`",
{
field: field,
skeleton: skeleton
}
);
}
last = fieldsPosMap[ field ];
return true;
});
};

});
16 changes: 16 additions & 0 deletions src/common/validate/skeleton/fields-pos-map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
define(function() {

/**
* Create a map between the skeleton fields and their positions, e.g.,
* {
* G: 0
* y: 1
* ...
* }
*/
return "GyYuUrQqMLlwWEecdDFghHKkmsSAzZOvVXx".split( "" ).reduce(function( memo, item, i ) {
memo[ item ] = i;
return memo;
}, {});

});
7 changes: 5 additions & 2 deletions src/date/expand-pattern.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
define([
"../common/format-message",
"../common/create-error/invalid-parameter-value",
"../common/format-message",
"../common/validate/skeleton",
"./expand-pattern/get-best-match-pattern"
], function( formatMessage, createErrorInvalidParameterValue,
], function( createErrorInvalidParameterValue, formatMessage, validateSkeleton,
dateExpandPatternGetBestMatchPattern ) {

/**
Expand Down Expand Up @@ -51,6 +52,8 @@ return function( options, cldr ) {
return cldr.supplemental.timeData.preferred();
});

validateSkeleton( skeleton );

// Try direct map (note that getBestMatchPattern handles it).
// ... or, try to "best match" the whole skeleton.
result = getBestMatchPattern(
Expand Down
35 changes: 27 additions & 8 deletions test/unit/date/expand-pattern.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,43 +43,62 @@ QUnit.test( "should expand {skeleton: \"<skeleton>\"}", function( assert ) {
assert.expandPattern( de, { skeleton: "jmm" }, "HH:mm" );
assert.expandPattern( ru, { skeleton: "jmm" }, "H:mm" );

// Best match the whole skeleton.
// Best matches the whole skeleton.
assert.expandPattern( en, { skeleton: "hhmm" }, "hh:mm a" );
assert.expandPattern( en, { skeleton: "HHmm" }, "HH:mm" );
assert.expandPattern( en, { skeleton: "EHmss" }, "E HH:mm:ss" );
assert.expandPattern( en, { skeleton: "yy" }, "yy" );
assert.expandPattern( de, { skeleton: "yMMMMd" }, "d. MMMM y" );
assert.expandPattern( de, { skeleton: "MMMM" }, "LLLL" );
assert.expandPattern( de, { skeleton: "MMMMy" }, "MMMM y" );
assert.expandPattern( de, { skeleton: "yMMMM" }, "MMMM y" );
assert.expandPattern( de, { skeleton: "EEEE" }, "cccc" );
assert.expandPattern( de, { skeleton: "cccc" }, "cccc" );
assert.expandPattern( de, { skeleton: "EEEEMMMMd" }, "EEEE, d. MMMM" );
assert.expandPattern( de, { skeleton: "ccccMMMMd" }, "EEEE, d. MMMM" );
assert.expandPattern( de, { skeleton: "MMMMEEEEd" }, "EEEE, d. MMMM" );
assert.expandPattern( de, { skeleton: "MMMMccccd" }, "EEEE, d. MMMM" );
assert.expandPattern( de, { skeleton: "HHmm" }, "HH:mm" );
assert.expandPattern( de, { skeleton: "EEEEHHmm" }, "EEEE, HH:mm" );
assert.expandPattern( de, { skeleton: "EEEEHmm" }, "EEEE, HH:mm" );
assert.expandPattern( de, { skeleton: "ccccHmm" }, "EEEE, HH:mm" );
assert.expandPattern( ru, { skeleton: "yMMMMd" }, "d MMMM y 'г'." );
assert.expandPattern( ru, { skeleton: "MMMM" }, "LLLL" );
assert.expandPattern( ru, { skeleton: "MMMMy" }, "LLLL y 'г'." );
assert.expandPattern( ru, { skeleton: "yMMMM" }, "LLLL y 'г'." );
assert.expandPattern( ru, { skeleton: "EEEE" }, "cccc" );
assert.expandPattern( ru, { skeleton: "cccc" }, "cccc" );
assert.expandPattern( ru, { skeleton: "EEEEMMMMd" }, "cccc, d MMMM" );
assert.expandPattern( ru, { skeleton: "ccccMMMMd" }, "cccc, d MMMM" );
assert.expandPattern( ru, { skeleton: "MMMMEEEEd" }, "cccc, d MMMM" );
assert.expandPattern( ru, { skeleton: "MMMMccccd" }, "cccc, d MMMM" );
assert.expandPattern( ru, { skeleton: "HHmm" }, "HH:mm" );
assert.expandPattern( ru, { skeleton: "EEEEHHmm" }, "EEEE HH:mm" );
assert.expandPattern( ru, { skeleton: "EEEEHmm" }, "EEEE HH:mm" );
assert.expandPattern( ru, { skeleton: "ccccHHmm" }, "EEEE HH:mm" );
assert.expandPattern( ru, { skeleton: "ccccHmm" }, "EEEE HH:mm" );

// Best match the date and time parts individually then combine together.
// Best matches the date and time parts individually then combine them together.
assert.expandPattern( en, { skeleton: "GyMMMEdhms" }, "E, MMM d, y G, h:mm:ss a" );
assert.expandPattern( en, { skeleton: "MMMMEdhm" }, "E, MMMM d 'at' h:mm a" );
assert.expandPattern( en, { skeleton: "MMMMh" }, "LLLL 'at' h a" );
assert.expandPattern( de, { skeleton: "MMMMEdhm" }, "E, d. MMMM 'um' h:mm a" );
assert.expandPattern( ru, { skeleton: "MMMMEdhm" }, "ccc, d MMMM, h:mm a" );
});

QUnit.test( "should throw exception on invalid skeletons", function( assert ) {
// Invalid characters.
assert.throws(function() {
expandPattern({ skeleton: "MMM d" }, en );
});
assert.throws(function() {
expandPattern({ skeleton: "MM/dd" }, en );
});

// Invalid order.
assert.throws(function() {
expandPattern({ skeleton: "dM" }, en );
});
assert.throws(function() {
expandPattern({ skeleton: "My" }, en );
expandPattern({ skeleton: "MMMy" }, en );
});
});

QUnit.test( "should expand {date: \"(full, ...)\"}", function( assert ) {
assert.expandPattern( en, { date: "full" }, "EEEE, MMMM d, y" );
});
Expand Down

0 comments on commit 49a4eb1

Please sign in to comment.