diff --git a/src/date-runtime.js b/src/date-runtime.js index db908de12..ba6fe0782 100644 --- a/src/date-runtime.js +++ b/src/date-runtime.js @@ -5,17 +5,15 @@ define([ "./common/validate/parameter-type/string", "./core-runtime", "./date/format", - "./date/formatter-fn", "./date/parse", "./date/parser-fn", "./date/tokenizer", "./number-runtime" ], function( runtimeKey, validateParameterPresence, validateParameterTypeDate, - validateParameterTypeString, Globalize, dateFormat, dateFormatterFn, dateParse, dateParserFn, + validateParameterTypeString, Globalize, dateFormat, dateParse, dateParserFn, dateTokenizer ) { -Globalize._dateFormatterFn = dateFormatterFn; Globalize._dateParserFn = dateParserFn; Globalize._dateFormat = dateFormat; Globalize._dateParser = dateParse; @@ -24,8 +22,19 @@ Globalize._validateParameterTypeDate = validateParameterTypeDate; Globalize.dateFormatter = Globalize.prototype.dateFormatter = function( options ) { + var formatterFn = this.dateToPartsFormatter( options ); + return function() { + var parts = formatterFn.apply( this, arguments ); + return parts.map( function( part ) { + return part.value; + }).join( "" ); + }; +}; + +Globalize.dateToPartsFormatter = +Globalize.prototype.dateToPartsFormatter = function( options ) { options = options || { skeleton: "yMd" }; - return Globalize[ runtimeKey( "dateFormatter", this._locale, [ options ] ) ]; + return Globalize[ runtimeKey( "dateToPartsFormatter", this._locale, [ options ] ) ]; }; Globalize.dateParser = @@ -42,6 +51,14 @@ Globalize.prototype.formatDate = function( value, options ) { return this.dateFormatter( options )( value ); }; +Globalize.formatDateToParts = +Globalize.prototype.formatDateToParts = function( value, options ) { + validateParameterPresence( value, "value" ); + validateParameterTypeDate( value, "value" ); + + return this.dateToPartsFormatter( options )( value ); +}; + Globalize.parseDate = Globalize.prototype.parseDate = function( value, options ) { validateParameterPresence( value, "value" ); diff --git a/src/date.js b/src/date.js index 354e9c5a0..df9aaf85e 100644 --- a/src/date.js +++ b/src/date.js @@ -10,7 +10,7 @@ define([ "./common/validate/parameter-type/string", "./core", "./date/expand-pattern", - "./date/formatter-fn", + "./date/to-parts-formatter-fn", "./date/format-properties", "./date/parser-fn", "./date/parse-properties", @@ -21,7 +21,7 @@ define([ "./number" ], function( Cldr, runtimeBind, validate, validateCldr, validateDefaultLocale, validateParameterPresence, validateParameterTypeDate, validateParameterTypePlainObject, - validateParameterTypeString, Globalize, dateExpandPattern, dateFormatterFn, + validateParameterTypeString, Globalize, dateExpandPattern, dateToPartsFormatterFn, dateFormatProperties, dateParserFn, dateParseProperties, dateTokenizerProperties ) { function validateRequiredCldr( path, value ) { @@ -77,6 +77,33 @@ function validateOptionsSkeleton( pattern, skeleton ) { */ Globalize.dateFormatter = Globalize.prototype.dateFormatter = function( options ) { + var formatterFn = this.dateToPartsFormatter( options ); + return function() { + var parts = formatterFn.apply( this, arguments ); + return parts.map( function( part ) { + return part.value; + }).join( "" ); + }; +}; + +/** + * .dateToPartsFormatter( options ) + * + * @options [Object] see date/expand_pattern for more info. + * + * Return a date formatter function (of the form below) according to the given options and the + * default/instance locale. + * + * fn( value ) + * + * @value [Date] + * + * Return a function that formats a date to parts according to the given `format` + * and the default/instance + * locale. + */ +Globalize.dateToPartsFormatter = +Globalize.prototype.dateToPartsFormatter = function( options ) { var args, cldr, numberFormatters, pad, pattern, properties, returnFn; validateParameterTypePlainObject( options, "options" ); @@ -104,7 +131,7 @@ Globalize.prototype.dateFormatter = function( options ) { }); } - returnFn = dateFormatterFn( numberFormatters, properties ); + returnFn = dateToPartsFormatterFn( numberFormatters, properties ); runtimeBind( args, cldr, returnFn, [ numberFormatters, properties ] ); @@ -166,6 +193,23 @@ Globalize.prototype.formatDate = function( value, options ) { return this.dateFormatter( options )( value ); }; +/** + * .formatDateToParts( value, options ) + * + * @value [Date] + * + * @options [Object] see date/expand_pattern for more info. + * + * Formats a date or number to parts according to the given options and the default/instance locale. + */ +Globalize.formatDateToParts = +Globalize.prototype.formatDateToParts = function( value, options ) { + validateParameterPresence( value, "value" ); + validateParameterTypeDate( value, "value" ); + + return this.dateToPartsFormatter( options )( value ); +}; + /** * .parseDate( value, options ) * diff --git a/src/date/fields-map.js b/src/date/fields-map.js new file mode 100644 index 000000000..c29476dc1 --- /dev/null +++ b/src/date/fields-map.js @@ -0,0 +1,14 @@ +define([ + "./inverse-fields-map" +], function( dateInverseFieldsMap ) { + +// Invert key and values, e.g., {"year": "yY"} ==> {"y": "year", "Y": "year"} +return Object.keys( dateInverseFieldsMap ).reduce( function( map, key ) { + var value = dateInverseFieldsMap[ key ]; + value.split( "" ).forEach(function( symbol ) { + map[ symbol ] = key; + }); + return map; +}, {}); + +}); diff --git a/src/date/format.js b/src/date/format.js index 0bb4834d3..234603d11 100644 --- a/src/date/format.js +++ b/src/date/format.js @@ -1,14 +1,15 @@ define([ "./day-of-week", "./day-of-year", + "./fields-map", "./milliseconds-in-day", "./pattern-re", "./start-of", "./timezone-hour-format", "./week-days", "../util/remove-literal-quotes" -], function( dateDayOfWeek, dateDayOfYear, dateMillisecondsInDay, datePatternRe, dateStartOf, - dateTimezoneHourFormat, dateWeekDays, removeLiteralQuotes ) { +], function( dateDayOfWeek, dateDayOfYear, dateFieldsMap, dateMillisecondsInDay, datePatternRe, + dateStartOf, dateTimezoneHourFormat, dateWeekDays, removeLiteralQuotes ) { /** * format( date, properties ) @@ -22,10 +23,12 @@ define([ * Disclosure: this function borrows excerpts of dojo/date/locale. */ return function( date, numberFormatters, properties ) { + var parts = []; + var timeSeparator = properties.timeSeparator; - return properties.pattern.replace( datePatternRe, function( current ) { - var ret, + properties.pattern.replace( datePatternRe, function( current ) { + var dateField, type, value, chr = current.charAt( 0 ), length = current.length; @@ -59,7 +62,7 @@ return function( date, numberFormatters, properties ) { // Era case "G": - ret = properties.eras[ date.getFullYear() < 0 ? 0 : 1 ]; + value = properties.eras[ date.getFullYear() < 0 ? 0 : 1 ]; break; // Year @@ -68,10 +71,10 @@ return function( date, numberFormatters, properties ) { // Plain year. // The length specifies the padding, but for two letters it also specifies the // maximum length. - ret = date.getFullYear(); + value = date.getFullYear(); if ( length === 2 ) { - ret = String( ret ); - ret = +ret.substr( ret.length - 2 ); + value = String( value ); + value = +value.substr( value.length - 2 ); } break; @@ -81,35 +84,35 @@ return function( date, numberFormatters, properties ) { // The length specifies the padding, but for two letters it also specifies the // maximum length. // yearInWeekofYear = date + DaysInAWeek - (dayOfWeek - firstDay) - minDays - ret = new Date( date.getTime() ); - ret.setDate( - ret.getDate() + 7 - + value = new Date( date.getTime() ); + value.setDate( + value.getDate() + 7 - dateDayOfWeek( date, properties.firstDay ) - properties.firstDay - properties.minDays ); - ret = ret.getFullYear(); + value = value.getFullYear(); if ( length === 2 ) { - ret = String( ret ); - ret = +ret.substr( ret.length - 2 ); + value = String( value ); + value = +value.substr( value.length - 2 ); } break; // Quarter case "Q": case "q": - ret = Math.ceil( ( date.getMonth() + 1 ) / 3 ); + value = Math.ceil( ( date.getMonth() + 1 ) / 3 ); if ( length > 2 ) { - ret = properties.quarters[ chr ][ length ][ ret ]; + value = properties.quarters[ chr ][ length ][ value ]; } break; // Month case "M": case "L": - ret = date.getMonth() + 1; + value = date.getMonth() + 1; if ( length > 2 ) { - ret = properties.months[ chr ][ length ][ ret ]; + value = properties.months[ chr ][ length ][ value ]; } break; @@ -119,33 +122,33 @@ return function( date, numberFormatters, properties ) { // Week of Year. // woy = ceil( ( doy + dow of 1/1 ) / 7 ) - minDaysStuff ? 1 : 0. // TODO should pad on ww? Not documented, but I guess so. - ret = dateDayOfWeek( dateStartOf( date, "year" ), properties.firstDay ); - ret = Math.ceil( ( dateDayOfYear( date ) + ret ) / 7 ) - - ( 7 - ret >= properties.minDays ? 0 : 1 ); + value = dateDayOfWeek( dateStartOf( date, "year" ), properties.firstDay ); + value = Math.ceil( ( dateDayOfYear( date ) + value ) / 7 ) - + ( 7 - value >= properties.minDays ? 0 : 1 ); break; case "W": // Week of Month. // wom = ceil( ( dom + dow of `1/month` ) / 7 ) - minDaysStuff ? 1 : 0. - ret = dateDayOfWeek( dateStartOf( date, "month" ), properties.firstDay ); - ret = Math.ceil( ( date.getDate() + ret ) / 7 ) - - ( 7 - ret >= properties.minDays ? 0 : 1 ); + value = dateDayOfWeek( dateStartOf( date, "month" ), properties.firstDay ); + value = Math.ceil( ( date.getDate() + value ) / 7 ) - + ( 7 - value >= properties.minDays ? 0 : 1 ); break; // Day case "d": - ret = date.getDate(); + value = date.getDate(); break; case "D": - ret = dateDayOfYear( date ) + 1; + value = dateDayOfYear( date ) + 1; break; case "F": // Day of Week in month. eg. 2nd Wed in July. - ret = Math.floor( date.getDate() / 7 ) + 1; + value = Math.floor( date.getDate() / 7 ) + 1; break; // Week day @@ -155,54 +158,54 @@ return function( date, numberFormatters, properties ) { // Range is [1-7] (deduced by example provided on documentation) // TODO Should pad with zeros (not specified in the docs)? - ret = dateDayOfWeek( date, properties.firstDay ) + 1; + value = dateDayOfWeek( date, properties.firstDay ) + 1; break; } /* falls through */ case "E": - ret = dateWeekDays[ date.getDay() ]; - ret = properties.days[ chr ][ length ][ ret ]; + value = dateWeekDays[ date.getDay() ]; + value = properties.days[ chr ][ length ][ value ]; break; // Period (AM or PM) case "a": - ret = properties.dayPeriods[ date.getHours() < 12 ? "am" : "pm" ]; + value = properties.dayPeriods[ date.getHours() < 12 ? "am" : "pm" ]; break; // Hour case "h": // 1-12 - ret = ( date.getHours() % 12 ) || 12; + value = ( date.getHours() % 12 ) || 12; break; case "H": // 0-23 - ret = date.getHours(); + value = date.getHours(); break; case "K": // 0-11 - ret = date.getHours() % 12; + value = date.getHours() % 12; break; case "k": // 1-24 - ret = date.getHours() || 24; + value = date.getHours() || 24; break; // Minute case "m": - ret = date.getMinutes(); + value = date.getMinutes(); break; // Second case "s": - ret = date.getSeconds(); + value = date.getSeconds(); break; case "S": - ret = Math.round( date.getMilliseconds() * Math.pow( 10, length - 3 ) ); + value = Math.round( date.getMilliseconds() * Math.pow( 10, length - 3 ) ); break; case "A": - ret = Math.round( dateMillisecondsInDay( date ) * Math.pow( 10, length - 3 ) ); + value = Math.round( dateMillisecondsInDay( date ) * Math.pow( 10, length - 3 ) ); break; // Zone @@ -212,15 +215,15 @@ return function( date, numberFormatters, properties ) { // O: "{gmtFormat}+H;{gmtFormat}-H" or "{gmtZeroFormat}", eg. "GMT-8" or "GMT". // OOOO: "{gmtFormat}{hourFormat}" or "{gmtZeroFormat}", eg. "GMT-08:00" or "GMT". if ( date.getTimezoneOffset() === 0 ) { - ret = properties.gmtZeroFormat; + value = properties.gmtZeroFormat; } else { - ret = dateTimezoneHourFormat( + value = dateTimezoneHourFormat( date, length < 4 ? "+H;-H" : properties.tzLongHourFormat, timeSeparator, numberFormatters ); - ret = properties.gmtFormat.replace( /\{0\}/, ret ); + value = properties.gmtFormat.replace( /\{0\}/, value ); } break; @@ -228,7 +231,7 @@ return function( date, numberFormatters, properties ) { // Same as x*, except it uses "Z" for zero offset. if ( date.getTimezoneOffset() === 0 ) { - ret = "Z"; + value = "Z"; break; } @@ -238,30 +241,45 @@ return function( date, numberFormatters, properties ) { // x: hourFormat("+HH;-HH") // xx or xxxx: hourFormat("+HHmm;-HHmm") // xxx or xxxxx: hourFormat("+HH:mm;-HH:mm") - ret = length === 1 ? "+HH;-HH" : ( length % 2 ? "+HH:mm;-HH:mm" : "+HHmm;-HHmm" ); - ret = dateTimezoneHourFormat( date, ret, ":" ); + value = length === 1 ? "+HH;-HH" : ( length % 2 ? "+HH:mm;-HH:mm" : "+HHmm;-HHmm" ); + value = dateTimezoneHourFormat( date, value, ":" ); break; // timeSeparator case ":": - ret = timeSeparator; + value = timeSeparator; break; // ' literals. case "'": - ret = removeLiteralQuotes( current ); + value = removeLiteralQuotes( current ); break; // Anything else is considered a literal, including [ ,:/.@#], chinese, japonese, and // arabic characters. default: - ret = current; + value = current; + + } + if ( typeof value === "number" ) { + value = numberFormatters[ length ]( value ); } - if ( typeof ret === "number" ) { - ret = numberFormatters[ length ]( ret ); + + dateField = dateFieldsMap[ chr ]; + type = dateField ? dateField : "literal"; + + // Concat two consecutive literals + if ( type === "literal" && parts.length && parts[ parts.length - 1 ].type === "literal" ) { + parts[ parts.length - 1 ].value += value; + return; } - return ret; + + parts.push( { type: type, value: value } ); + }); + + return parts; + }; }); diff --git a/src/date/inverse-fields-map.js b/src/date/inverse-fields-map.js new file mode 100644 index 000000000..504e07c7b --- /dev/null +++ b/src/date/inverse-fields-map.js @@ -0,0 +1,18 @@ +define(function() { + +return { + "era": "G", + "year": "yY", + "quarter": "qQ", + "month": "ML", + "week": "wW", + "day": "dDF", + "weekday": "ecE", + "dayperiod": "a", + "hour": "hHkK", + "minute": "m", + "second": "sSA", + "zone": "zOxX" +}; + +}); diff --git a/src/date/formatter-fn.js b/src/date/to-parts-formatter-fn.js similarity index 89% rename from src/date/formatter-fn.js rename to src/date/to-parts-formatter-fn.js index 70764228b..54da67d4d 100644 --- a/src/date/formatter-fn.js +++ b/src/date/to-parts-formatter-fn.js @@ -5,7 +5,7 @@ define([ ], function( validateParameterPresence, validateParameterTypeDate, dateFormat ) { return function( numberFormatters, properties ) { - return function dateFormatter( value ) { + return function dateToPartsFormatter( value ) { validateParameterPresence( value, "value" ); validateParameterTypeDate( value, "value" ); diff --git a/test/functional.js b/test/functional.js index f84bf0616..fac2d3268 100644 --- a/test/functional.js +++ b/test/functional.js @@ -12,8 +12,10 @@ require([ // date "./functional/date/date-formatter", + "./functional/date/date-to-parts-formatter", "./functional/date/date-parser", "./functional/date/format-date", + "./functional/date/format-date-to-parts", "./functional/date/parse-date", // message diff --git a/test/functional/core/locale.js b/test/functional/core/locale.js index 95504d2fe..90382d6df 100644 --- a/test/functional/core/locale.js +++ b/test/functional/core/locale.js @@ -26,6 +26,10 @@ QUnit.test( "should validate whether default locale is defined on static calls", Globalize.formatDate( new Date() ); }); + util.assertDefaultLocalePresence( assert, function() { + Globalize.formatDateToParts( new Date() ); + }); + util.assertDefaultLocalePresence( assert, function() { Globalize.parseDate( "15" ); }); diff --git a/test/functional/date/date-formatter.js b/test/functional/date/date-formatter.js index b71c0fe68..2df367730 100644 --- a/test/functional/date/date-formatter.js +++ b/test/functional/date/date-formatter.js @@ -93,190 +93,4 @@ QUnit.test( "should return a formatter", function( assert ) { assert.equal( Globalize.dateFormatter({ skeleton: "yQQQhm" })( date ), "Q3 2010, 5:35 PM" ); }); -QUnit.test( "should augment a skeleton", function( assert ) { - extraSetup(); - - assert.equal( Globalize.dateFormatter({ skeleton: "yMMMMd" })( date ), "September 15, 2010" ); - assert.equal( Globalize.dateFormatter({ skeleton: "MMMMd" })( date ), "September 15" ); - assert.equal( Globalize.dateFormatter({ skeleton: "MMMM" })( date ), "September" ); - assert.equal( Globalize.dateFormatter({ skeleton: "EEEE" })( date ), "Wednesday" ); -}); - -QUnit.test( "should allow for runtime compilation", function( assert ) { - extraSetup(); - - function pad1NumberFormatter( formatter ) { - util.assertRuntimeBind( - assert, - formatter, - "a1378886668", - "Globalize(\"en\").numberFormatter({\"raw\":\"0\"})", - function() {} - ); - } - - function pad2NumberFormatter( formatter ) { - util.assertRuntimeBind( - assert, - formatter, - "b203855544", - "Globalize(\"en\").numberFormatter({\"raw\":\"00\"})", - function() {} - ); - } - - util.assertRuntimeBind( - assert, - Globalize.dateFormatter({ time: "medium" }), - "a127047021", - "Globalize(\"en\").dateFormatter({\"time\":\"medium\"})", - function( runtimeArgs ) { - pad1NumberFormatter( runtimeArgs[ 0 ][ 1 ] ); - pad2NumberFormatter( runtimeArgs[ 0 ][ 2 ] ); - assert.deepEqual( runtimeArgs[ 1 ], { - "dayPeriods": { - "am": "AM", - "pm": "PM" - }, - "pattern": "h:mm:ss a", - "timeSeparator": ":" - }); - } - ); - - util.assertRuntimeBind( - assert, - Globalize.dateFormatter({ date: "full" }), - "b641817676", - "Globalize(\"en\").dateFormatter({\"date\":\"full\"})", - function( runtimeArgs ) { - pad1NumberFormatter( runtimeArgs[ 0 ][ 1 ] ); - assert.deepEqual( runtimeArgs[ 1 ], { - "pattern": "EEEE, MMMM d, y", - "timeSeparator": ":", - "days": { - "E": { - "4": { - "sun": "Sunday", - "mon": "Monday", - "tue": "Tuesday", - "wed": "Wednesday", - "thu": "Thursday", - "fri": "Friday", - "sat": "Saturday" - } - } - }, - "months": { - "M": { - "4": { - "1": "January", - "2": "February", - "3": "March", - "4": "April", - "5": "May", - "6": "June", - "7": "July", - "8": "August", - "9": "September", - "10": "October", - "11": "November", - "12": "December" - } - } - } - }); - } - ); - - util.assertRuntimeBind( - assert, - Globalize.dateFormatter({ skeleton: "GyMMMEdhms" }), - "a385327118", - "Globalize(\"en\").dateFormatter({\"skeleton\":\"GyMMMEdhms\"})", - function( runtimeArgs ) { - pad1NumberFormatter( runtimeArgs[ 0 ][ 1 ] ); - pad2NumberFormatter( runtimeArgs[ 0 ][ 2 ] ); - assert.deepEqual( runtimeArgs[ 1 ], { - "dayPeriods": { - "am": "AM", - "pm": "PM" - }, - "days": { - "E": { - "1": { - "fri": "Fri", - "mon": "Mon", - "sat": "Sat", - "sun": "Sun", - "thu": "Thu", - "tue": "Tue", - "wed": "Wed" - } - } - }, - "eras": { - "0": "BC", - "0-alt-variant": "BCE", - "1": "AD", - "1-alt-variant": "CE" - }, - "months": { - "M": { - "3": { - "1": "Jan", - "10": "Oct", - "11": "Nov", - "12": "Dec", - "2": "Feb", - "3": "Mar", - "4": "Apr", - "5": "May", - "6": "Jun", - "7": "Jul", - "8": "Aug", - "9": "Sep" - } - } - }, - "pattern": "E, MMM d, y G, h:mm:ss a", - "timeSeparator": ":" - }); - } - ); - - util.assertRuntimeBind( - assert, - Globalize.dateFormatter({ skeleton: "MMM" }), - "b664461195", - "Globalize(\"en\").dateFormatter({\"skeleton\":\"MMM\"})", - function( runtimeArgs ) { - assert.deepEqual( runtimeArgs[ 0 ], {} ); - assert.deepEqual( runtimeArgs[ 1 ], { - "months": { - "L": { - "3": { - "1": "Jan", - "10": "Oct", - "11": "Nov", - "12": "Dec", - "2": "Feb", - "3": "Mar", - "4": "Apr", - "5": "May", - "6": "Jun", - "7": "Jul", - "8": "Aug", - "9": "Sep" - } - } - }, - "pattern": "LLL", - "timeSeparator": ":" - }); - } - ); - -}); - }); diff --git a/test/functional/date/date-to-parts-formatter.js b/test/functional/date/date-to-parts-formatter.js new file mode 100644 index 000000000..c79d1f918 --- /dev/null +++ b/test/functional/date/date-to-parts-formatter.js @@ -0,0 +1,447 @@ +define([ + "globalize", + "json!cldr-data/main/en/numbers.json", + "json!cldr-data/main/en/ca-gregorian.json", + "json!cldr-data/supplemental/likelySubtags.json", + "json!cldr-data/supplemental/numberingSystems.json", + "json!cldr-data/supplemental/timeData.json", + "json!cldr-data/supplemental/weekData.json", + "../../util", + + "globalize/date" +], function( Globalize, enNumbers, enCaGregorian, likelySubtags, numberingSystems, timeData, + weekData, util ) { + +var date = new Date( 2010, 8, 15, 17, 35, 7, 369 ); + +function extraSetup() { + Globalize.load( + enCaGregorian, + enNumbers, + numberingSystems, + timeData, + weekData + ); +} + +QUnit.module( ".dateToPartsFormatter( pattern )", { + setup: function() { + Globalize.load( likelySubtags, { + main: { + en: {} + } + }); + Globalize.locale( "en" ); + }, + teardown: util.resetCldrContent +}); + +QUnit.test( "should validate parameters", function( assert ) { + util.assertPlainObjectParameter( assert, "options", function( invalidPattern ) { + return function() { + Globalize.dateToPartsFormatter( invalidPattern ); + }; + }); +}); + +QUnit.test( "should validate CLDR content", function( assert ) { + util.assertCldrContent( assert, function() { + Globalize.dateToPartsFormatter(); + }); +}); + +QUnit.test( "should return a formatter", function( assert ) { + extraSetup(); + + assert.deepEqual( Globalize.dateToPartsFormatter({ skeleton: "GyMMMEd" })( date ), + [ + { + "type": "weekday", + "value": "Wed" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "month", + "value": "Sep" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "day", + "value": "15" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "year", + "value": "2010" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "era", + "value": "AD" + } + ]); + + assert.deepEqual( Globalize.dateToPartsFormatter({ skeleton: "dhms" })( date ), + [ + { + "type": "day", + "value": "15" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "hour", + "value": "5" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "minute", + "value": "35" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "second", + "value": "07" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "dayperiod", + "value": "PM" + } + ]); + + assert.deepEqual( Globalize.dateToPartsFormatter({ skeleton: "GyMMMEdhms" })( date ), [ + { + "type": "weekday", + "value": "Wed" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "month", + "value": "Sep" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "day", + "value": "15" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "year", + "value": "2010" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "era", + "value": "AD" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "hour", + "value": "5" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "minute", + "value": "35" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "second", + "value": "07" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "dayperiod", + "value": "PM" + } + ]); + assert.deepEqual( Globalize.dateToPartsFormatter({ skeleton: "Ems" })( date ), +[ + { + "type": "weekday", + "value": "Wed" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "minute", + "value": "35" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "second", + "value": "07" + } + ]); + assert.deepEqual( Globalize.dateToPartsFormatter({ skeleton: "yQQQhm" })( date ), [ + { + "type": "quarter", + "value": "Q3" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "year", + "value": "2010" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "hour", + "value": "5" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "minute", + "value": "35" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "dayperiod", + "value": "PM" + } + ]); +}); + + +QUnit.test( "should allow for runtime compilation", function( assert ) { + extraSetup(); + + function pad1NumberFormatter( formatter ) { + util.assertRuntimeBind( + assert, + formatter, + "a1378886668", + "Globalize(\"en\").numberFormatter({\"raw\":\"0\"})", + function() {} + ); + } + + function pad2NumberFormatter( formatter ) { + util.assertRuntimeBind( + assert, + formatter, + "b203855544", + "Globalize(\"en\").numberFormatter({\"raw\":\"00\"})", + function() {} + ); + } + + util.assertRuntimeBind( + assert, + Globalize.dateToPartsFormatter({ time: "medium" }), + "a963207574", + "Globalize(\"en\").dateToPartsFormatter({\"time\":\"medium\"})", + function( runtimeArgs ) { + pad1NumberFormatter( runtimeArgs[ 0 ][ 1 ] ); + pad2NumberFormatter( runtimeArgs[ 0 ][ 2 ] ); + assert.deepEqual( runtimeArgs[ 1 ], { + "dayPeriods": { + "am": "AM", + "pm": "PM" + }, + "pattern": "h:mm:ss a", + "timeSeparator": ":" + }); + } + ); + + util.assertRuntimeBind( + assert, + Globalize.dateToPartsFormatter({ date: "full" }), + "b1543739875", + "Globalize(\"en\").dateToPartsFormatter({\"date\":\"full\"})", + function( runtimeArgs ) { + pad1NumberFormatter( runtimeArgs[ 0 ][ 1 ] ); + assert.deepEqual( runtimeArgs[ 1 ], { + "pattern": "EEEE, MMMM d, y", + "timeSeparator": ":", + "days": { + "E": { + "4": { + "sun": "Sunday", + "mon": "Monday", + "tue": "Tuesday", + "wed": "Wednesday", + "thu": "Thursday", + "fri": "Friday", + "sat": "Saturday" + } + } + }, + "months": { + "M": { + "4": { + "1": "January", + "2": "February", + "3": "March", + "4": "April", + "5": "May", + "6": "June", + "7": "July", + "8": "August", + "9": "September", + "10": "October", + "11": "November", + "12": "December" + } + } + } + }); + } + ); + + util.assertRuntimeBind( + assert, + Globalize.dateToPartsFormatter({ skeleton: "GyMMMEdhms" }), + "a1513632567", + "Globalize(\"en\").dateToPartsFormatter({\"skeleton\":\"GyMMMEdhms\"})", + function( runtimeArgs ) { + pad1NumberFormatter( runtimeArgs[ 0 ][ 1 ] ); + pad2NumberFormatter( runtimeArgs[ 0 ][ 2 ] ); + assert.deepEqual( runtimeArgs[ 1 ], { + "dayPeriods": { + "am": "AM", + "pm": "PM" + }, + "days": { + "E": { + "1": { + "fri": "Fri", + "mon": "Mon", + "sat": "Sat", + "sun": "Sun", + "thu": "Thu", + "tue": "Tue", + "wed": "Wed" + } + } + }, + "eras": { + "0": "BC", + "0-alt-variant": "BCE", + "1": "AD", + "1-alt-variant": "CE" + }, + "months": { + "M": { + "3": { + "1": "Jan", + "10": "Oct", + "11": "Nov", + "12": "Dec", + "2": "Feb", + "3": "Mar", + "4": "Apr", + "5": "May", + "6": "Jun", + "7": "Jul", + "8": "Aug", + "9": "Sep" + } + } + }, + "pattern": "E, MMM d, y G, h:mm:ss a", + "timeSeparator": ":" + }); + } + ); + + util.assertRuntimeBind( + assert, + Globalize.dateToPartsFormatter({ skeleton: "MMM" }), + "b513287828", + "Globalize(\"en\").dateToPartsFormatter({\"skeleton\":\"MMM\"})", + function( runtimeArgs ) { + assert.deepEqual( runtimeArgs[ 0 ], {} ); + assert.deepEqual( runtimeArgs[ 1 ], { + "months": { + "L": { + "3": { + "1": "Jan", + "10": "Oct", + "11": "Nov", + "12": "Dec", + "2": "Feb", + "3": "Mar", + "4": "Apr", + "5": "May", + "6": "Jun", + "7": "Jul", + "8": "Aug", + "9": "Sep" + } + } + }, + "pattern": "LLL", + "timeSeparator": ":" + }); + } + ); + +}); + +}); diff --git a/test/functional/date/format-date-to-parts.js b/test/functional/date/format-date-to-parts.js new file mode 100644 index 000000000..f826f7359 --- /dev/null +++ b/test/functional/date/format-date-to-parts.js @@ -0,0 +1,651 @@ +define([ + "globalize", + "json!cldr-data/main/ar/ca-gregorian.json", + "json!cldr-data/main/ar/numbers.json", + "json!cldr-data/main/ar/timeZoneNames.json", + "json!cldr-data/main/en/ca-gregorian.json", + "json!cldr-data/main/en/numbers.json", + "json!cldr-data/main/en/timeZoneNames.json", + "json!cldr-data/main/pt/ca-gregorian.json", + "json!cldr-data/main/pt/numbers.json", + "json!cldr-data/supplemental/likelySubtags.json", + "json!cldr-data/supplemental/numberingSystems.json", + "json!cldr-data/supplemental/timeData.json", + "json!cldr-data/supplemental/weekData.json", + "../../util", + + "globalize/date" +], function( Globalize, arCaGregorian, arNumbers, arTimeZoneNames, enCaGregorian, enNumbers, + enTimeZoneNames, ptCaGregorian, ptNumbers, likelySubtags, numberingSystems, timeData, weekData, + util ) { + +var ar, + date = new Date( 2010, 8, 15, 17, 35, 7, 369 ); + +function extraSetup() { + Globalize.load( + arCaGregorian, + arNumbers, + arTimeZoneNames, + enCaGregorian, + enNumbers, + enTimeZoneNames, + numberingSystems, + ptCaGregorian, + ptNumbers, + timeData, + weekData + ); +} + +QUnit.module( ".formatDateToParts( value, options )", { + setup: function() { + Globalize.load( likelySubtags, { + main: { + en: {} + } + }); + Globalize.locale( "en" ); + }, + teardown: util.resetCldrContent +}); + +QUnit.test( "should validate parameters", function( assert ) { + util.assertParameterPresence( assert, "value", function() { + Globalize.formatDateToParts(); + }); + + util.assertDateParameter( assert, "value", function( invalidValue ) { + return function() { + Globalize.formatDateToParts( invalidValue, "GyMMMEd" ); + }; + }); + + util.assertPlainObjectParameter( assert, "options", function( invalidPattern ) { + return function() { + Globalize.formatDateToParts( date, invalidPattern ); + }; + }); +}); + +QUnit.test( "should validate CLDR content", function( assert ) { + util.assertCldrContent( assert, function() { + Globalize.formatDateToParts( date ); + }); +}); + +QUnit.test( "should format skeleton to parts", function( assert ) { + extraSetup(); + + ar = Globalize( "ar" ); + + assert.deepEqual( Globalize.formatDateToParts( date, { skeleton: "d" } ), [ + { + "type": "day", + "value": "15" + } + ]); + + assert.deepEqual( Globalize.formatDateToParts( date, { skeleton: "Ed" } ), [ + { + "type": "day", + "value": "15" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "weekday", + "value": "Wed" + } + ]); + + assert.deepEqual( Globalize.formatDateToParts( date, { skeleton: "Ehms" } ), [ + { + "type": "weekday", + "value": "Wed" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "hour", + "value": "5" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "minute", + "value": "35" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "second", + "value": "07" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "dayperiod", + "value": "PM" + } + ]); + + assert.deepEqual( Globalize.formatDateToParts( date, { skeleton: "GyMMMEd" } ), + [ + { + "type": "weekday", + "value": "Wed" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "month", + "value": "Sep" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "day", + "value": "15" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "year", + "value": "2010" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "era", + "value": "AD" + } + ]); + + assert.deepEqual( Globalize.formatDateToParts( date, { skeleton: "yMd" } ), + [ + { + "type": "month", + "value": "9" + }, + { + "type": "literal", + "value": "/" + }, + { + "type": "day", + "value": "15" + }, + { + "type": "literal", + "value": "/" + }, + { + "type": "year", + "value": "2010" + } + ]); + + assert.deepEqual( Globalize.formatDateToParts( date, { skeleton: "yQQQ" } ), + [ + { + "type": "quarter", + "value": "Q3" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "year", + "value": "2010" + } + ]); + + assert.deepEqual( ar.formatDateToParts( date, { skeleton: "yQQQ" } ), + [ + { + "type": "quarter", + "value": "الربع الثالث" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "year", + "value": "٢٠١٠" + } + ]); + + // Via instance .formatDateToParts(). + assert.deepEqual( Globalize( "pt" ).formatDateToParts( date, { skeleton: "Ehms" } ), + [ + { + "type": "weekday", + "value": "qua" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "hour", + "value": "5" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "minute", + "value": "35" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "second", + "value": "07" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "dayperiod", + "value": "PM" + } + ]); + + assert.deepEqual( Globalize( "pt" ).formatDateToParts( date, { skeleton: "GyMMMEd" } ), + [ + { + "type": "weekday", + "value": "qua" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "day", + "value": "15" + }, + { + "type": "literal", + "value": " de " + }, + { + "type": "month", + "value": "set" + }, + { + "type": "literal", + "value": " de " + }, + { + "type": "year", + "value": "2010" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "era", + "value": "d.C." + } + ]); +}); + +QUnit.test( "should format time presets", function( assert ) { + extraSetup(); + + ar = Globalize( "ar" ); + + assert.deepEqual( Globalize.formatDateToParts( date, { time: "medium" } ), + [ + { + "type": "hour", + "value": "5" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "minute", + "value": "35" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "second", + "value": "07" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "dayperiod", + "value": "PM" + } + ]); + + assert.deepEqual( ar.formatDateToParts( date, { time: "medium" } ), + [ + { + "type": "hour", + "value": "٥" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "minute", + "value": "٣٥" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "second", + "value": "٠٧" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "dayperiod", + "value": "م" + } + ]); + + assert.deepEqual( Globalize.formatDateToParts( date, { time: "short" } ), + [ + { + "type": "hour", + "value": "5" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "minute", + "value": "35" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "dayperiod", + "value": "PM" + } + ]); + + assert.deepEqual( ar.formatDateToParts( date, { time: "short" } ), + [ + { + "type": "hour", + "value": "٥" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "minute", + "value": "٣٥" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "dayperiod", + "value": "م" + } + ]); +}); + +QUnit.test( "should format date presets", function( assert ) { + extraSetup(); + + assert.deepEqual( Globalize.formatDateToParts( date, { date: "full" } ), + [ + { + "type": "weekday", + "value": "Wednesday" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "month", + "value": "September" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "day", + "value": "15" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "year", + "value": "2010" + } + ]); + + assert.deepEqual( Globalize.formatDateToParts( date, { date: "long" } ), + [ + { + "type": "month", + "value": "September" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "day", + "value": "15" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "year", + "value": "2010" + } + ]); + + assert.deepEqual( Globalize.formatDateToParts( date, { date: "medium" } ), + [ + { + "type": "month", + "value": "Sep" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "day", + "value": "15" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "year", + "value": "2010" + } + ]); + + assert.deepEqual( Globalize.formatDateToParts( date, { date: "short" } ), + [ + { + "type": "month", + "value": "9" + }, + { + "type": "literal", + "value": "/" + }, + { + "type": "day", + "value": "15" + }, + { + "type": "literal", + "value": "/" + }, + { + "type": "year", + "value": "10" + } + ]); +}); + +QUnit.test( "should format datetime presets", function( assert ) { + extraSetup(); + + assert.deepEqual( Globalize.formatDateToParts( date, { datetime: "medium" } ), + [ + { + "type": "month", + "value": "Sep" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "day", + "value": "15" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "year", + "value": "2010" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "hour", + "value": "5" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "minute", + "value": "35" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "second", + "value": "07" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "dayperiod", + "value": "PM" + } + ]); +}); + +QUnit.test( "should format raw patterns", function( assert ) { + extraSetup(); + + assert.deepEqual( Globalize.formatDateToParts( date, { raw: "E, MMM d, y G" } ), + [ + { + "type": "weekday", + "value": "Wed" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "month", + "value": "Sep" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "day", + "value": "15" + }, + { + "type": "literal", + "value": ", " + }, + { + "type": "year", + "value": "2010" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "era", + "value": "AD" + } + ]); +}); + +}); diff --git a/test/unit/date/format.js b/test/unit/date/format.js index 9c586a693..d9d99c15c 100644 --- a/test/unit/date/format.js +++ b/test/unit/date/format.js @@ -66,8 +66,8 @@ QUnit.assert.dateFormat = function( date, pattern, cldr, expected ) { for ( pad in properties.numberFormatters ) { numberFormatters[ pad ] = simpleFormatter( pad ); } - - this.equal( format( date, numberFormatters, properties ), expected ); + var result = format( date, numberFormatters, properties ); + this.deepEqual( result, expected ); }; QUnit.module( "Date Format" ); @@ -77,27 +77,80 @@ QUnit.module( "Date Format" ); */ QUnit.test( "should format era (G|GG|GGG)", function( assert ) { - assert.dateFormat( date1, "G", cldr, "AD" ); - assert.dateFormat( year0, "G", cldr, "AD" ); - assert.dateFormat( yearBc, "G", cldr, "BC" ); - assert.dateFormat( date1, "GG", cldr, "AD" ); - assert.dateFormat( year0, "GG", cldr, "AD" ); - assert.dateFormat( yearBc, "GG", cldr, "BC" ); - assert.dateFormat( date1, "GGG", cldr, "AD" ); - assert.dateFormat( year0, "GGG", cldr, "AD" ); - assert.dateFormat( yearBc, "GGG", cldr, "BC" ); + + assert.dateFormat( date1, "G", cldr, [{ + type: "era", + value: "AD" + }] ); + assert.dateFormat( year0, "G", cldr, [{ + type: "era", + value: "AD" + }] ); + + assert.dateFormat( yearBc, "G", cldr, [{ + type: "era", + value: "BC" + }] ); + + assert.dateFormat( date1, "GG", cldr, [{ + type: "era", + value: "AD" + }] ); + assert.dateFormat( year0, "GG", cldr, [{ + type: "era", + value: "AD" + }] ); + + assert.dateFormat( yearBc, "GG", cldr, [{ + type: "era", + value: "BC" + }] ); + + assert.dateFormat( date1, "GGG", cldr, [{ + type: "era", + value: "AD" + }] ); + + assert.dateFormat( year0, "GGG", cldr, [{ + type: "era", + value: "AD" + }] ); + + assert.dateFormat( yearBc, "GGG", cldr, [{ + type: "era", + value: "BC" + }] ); }); QUnit.test( "should format era (GGGG)", function( assert ) { - assert.dateFormat( date1, "GGGG", cldr, "Anno Domini" ); - assert.dateFormat( year0, "GGGG", cldr, "Anno Domini" ); - assert.dateFormat( yearBc, "GGGG", cldr, "Before Christ" ); + assert.dateFormat( date1, "GGGG", cldr, [{ + type: "era", + value: "Anno Domini" + }] ); + assert.dateFormat( year0, "GGGG", cldr, [{ + type: "era", + value: "Anno Domini" + }] ); + + assert.dateFormat( yearBc, "GGGG", cldr, [{ + type: "era", + value: "Before Christ" + }] ); }); QUnit.test( "should format era (GGGGG)", function( assert ) { - assert.dateFormat( date1, "GGGGG", cldr, "A" ); - assert.dateFormat( year0, "GGGGG", cldr, "A" ); - assert.dateFormat( yearBc, "GGGGG", cldr, "B" ); + assert.dateFormat( date1, "GGGGG", cldr, [{ + type: "era", + value: "A" + }] ); + assert.dateFormat( year0, "GGGGG", cldr,[{ + type: "era", + value: "A" + }] ); + assert.dateFormat( yearBc, "GGGGG", cldr, [{ + type: "era", + value: "B" + }] ); }); /** @@ -105,40 +158,97 @@ QUnit.test( "should format era (GGGGG)", function( assert ) { */ QUnit.test( "should format year (y) with no padding", function( assert ) { - assert.dateFormat( date2, "y", cldr, "2010" ); - assert.dateFormat( date1, "y", cldr, "1982" ); - assert.dateFormat( year0, "y", cldr, "0" ); + assert.dateFormat( date2, "y", cldr, [{ + type: "year", + value: "2010" + }] ); + assert.dateFormat( date1, "y", cldr, [{ + type: "year", + value: "1982" + }] ); + assert.dateFormat( year0, "y", cldr, [{ + type: "year", + value: "0" + }] ); }); QUnit.test( "should format year (yy) with padding, and limit 2 digits", function( assert ) { - assert.dateFormat( date2, "yy", cldr, "10" ); - assert.dateFormat( date1, "yy", cldr, "82" ); - assert.dateFormat( year0, "yy", cldr, "00" ); + assert.dateFormat( date2, "yy", cldr, [{ + type: "year", + value: "10" + }] ); + assert.dateFormat( date1, "yy", cldr, [{ + type: "year", + value: "82" + }] ); + assert.dateFormat( year0, "yy", cldr, [{ + type: "year", + value: "00" + }] ); }); QUnit.test( "should format year (yyy+) with padding", function( assert ) { - assert.dateFormat( date1, "yyy", cldr, "1982" ); - assert.dateFormat( date2, "yyy", cldr, "2010" ); - assert.dateFormat( year0, "yyyy", cldr, "0000" ); - assert.dateFormat( date1, "yyyyy", cldr, "01982" ); - assert.dateFormat( date2, "yyyyy", cldr, "02010" ); + assert.dateFormat( date1, "yyy", cldr, [{ + type: "year", + value: "1982" + }] ); + assert.dateFormat( date2, "yyy", cldr, [{ + type: "year", + value: "2010" + }] ); + assert.dateFormat( year0, "yyyy", cldr, [{ + type: "year", + value: "0000" + }] ); + assert.dateFormat( date1, "yyyyy", cldr, [{ + type: "year", + value: "01982" + }] ); + assert.dateFormat( date2, "yyyyy", cldr, [{ + type: "year", + value: "02010" + }] ); }); QUnit.test( "should format year in \"week of year\" (Y) with no padding", function( assert ) { - assert.dateFormat( date3, "Y", cldr, "1982" ); - assert.dateFormat( date4, "Y", cldr, "1994" ); + assert.dateFormat( date3, "Y", cldr, [{ + type: "year", + value: "1982" + }] ); + assert.dateFormat( date4, "Y", cldr, [{ + type: "year", + value: "1994" + }] ); }); QUnit.test( "should format year in \"week of year\" (YY) with padding, and limit 2 digits", function( assert ) { - assert.dateFormat( date3, "YY", cldr, "82" ); - assert.dateFormat( date4, "YY", cldr, "94" ); + assert.dateFormat( date3, "YY", cldr, [{ + type: "year", + value: "82" + }] ); + assert.dateFormat( date4, "YY", cldr, [{ + type: "year", + value: "94" + }] ); }); QUnit.test( "should format year in \"week of year\" (YYY+) with padding", function( assert ) { - assert.dateFormat( date3, "YYY", cldr, "1982" ); - assert.dateFormat( date4, "YYY", cldr, "1994" ); - assert.dateFormat( date3, "YYYYY", cldr, "01982" ); - assert.dateFormat( date4, "YYYYY", cldr, "01994" ); + assert.dateFormat( date3, "YYY", cldr, [{ + type: "year", + value: "1982" + }] ); + assert.dateFormat( date4, "YYY", cldr, [{ + type: "year", + value: "1994" + }] ); + assert.dateFormat( date3, "YYYYY", cldr, [{ + type: "year", + value: "01982" + }] ); + assert.dateFormat( date4, "YYYYY", cldr, [{ + type: "year", + value: "01994" + }] ); }); /** @@ -146,31 +256,79 @@ QUnit.test( "should format year in \"week of year\" (YYY+) with padding", functi */ QUnit.test( "should format quarter (Q|q) with no padding", function( assert ) { - assert.dateFormat( date1, "Q", cldr, "1" ); - assert.dateFormat( date2, "Q", cldr, "3" ); - assert.dateFormat( date1, "q", cldr, "1" ); - assert.dateFormat( date2, "q", cldr, "3" ); + assert.dateFormat( date1, "Q", cldr, [{ + type: "quarter", + value: "1" + }] ); + assert.dateFormat( date2, "Q", cldr, [{ + type: "quarter", + value: "3" + }] ); + assert.dateFormat( date1, "q", cldr, [{ + type: "quarter", + value: "1" + }] ); + assert.dateFormat( date2, "q", cldr, [{ + type: "quarter", + value: "3" + }] ); }); QUnit.test( "should format quarter (QQ|qq) with padding", function( assert ) { - assert.dateFormat( date1, "QQ", cldr, "01" ); - assert.dateFormat( date2, "QQ", cldr, "03" ); - assert.dateFormat( date1, "qq", cldr, "01" ); - assert.dateFormat( date2, "qq", cldr, "03" ); + assert.dateFormat( date1, "QQ", cldr, [{ + type: "quarter", + value: "01" + }] ); + assert.dateFormat( date2, "QQ", cldr, [{ + type: "quarter", + value: "03" + }] ); + assert.dateFormat( date1, "qq", cldr, [{ + type: "quarter", + value: "01" + }] ); + assert.dateFormat( date2, "qq", cldr, [{ + type: "quarter", + value: "03" + }] ); }); QUnit.test( "should format quarter (QQQ|qqq)", function( assert ) { - assert.dateFormat( date1, "QQQ", cldr, "Q1" ); - assert.dateFormat( date2, "QQQ", cldr, "Q3" ); - assert.dateFormat( date1, "qqq", cldr, "Q1" ); - assert.dateFormat( date2, "qqq", cldr, "Q3" ); + assert.dateFormat( date1, "QQQ", cldr, [{ + type: "quarter", + value: "Q1" + }] ); + assert.dateFormat( date2, "QQQ", cldr, [{ + type: "quarter", + value: "Q3" + }] ); + assert.dateFormat( date1, "qqq", cldr, [{ + type: "quarter", + value: "Q1" + }] ); + assert.dateFormat( date2, "qqq", cldr, [{ + type: "quarter", + value: "Q3" + }] ); }); QUnit.test( "should format quarter (QQQQ|qqqq) with padding", function( assert ) { - assert.dateFormat( date1, "QQQQ", cldr, "1st quarter" ); - assert.dateFormat( date2, "QQQQ", cldr, "3rd quarter" ); - assert.dateFormat( date1, "qqqq", cldr, "1st quarter" ); - assert.dateFormat( date2, "qqqq", cldr, "3rd quarter" ); + assert.dateFormat( date1, "QQQQ", cldr, [{ + type: "quarter", + value: "1st quarter" + }] ); + assert.dateFormat( date2, "QQQQ", cldr, [{ + type: "quarter", + value: "3rd quarter" + }] ); + assert.dateFormat( date1, "qqqq", cldr, [{ + type: "quarter", + value: "1st quarter" + }] ); + assert.dateFormat( date2, "qqqq", cldr, [{ + type: "quarter", + value: "3rd quarter" + }] ); }); /** @@ -178,38 +336,99 @@ QUnit.test( "should format quarter (QQQQ|qqqq) with padding", function( assert ) */ QUnit.test( "should format month (M|L) with no padding", function( assert ) { - assert.dateFormat( date1, "M", cldr, "1" ); - assert.dateFormat( date2, "M", cldr, "9" ); - assert.dateFormat( date1, "L", cldr, "1" ); - assert.dateFormat( date2, "L", cldr, "9" ); + assert.dateFormat( date1, "M", cldr, [{ + type: "month", + value: "1" + }] ); + assert.dateFormat( date2, "M", cldr, [{ + type: "month", + value: "9" + }] ); + assert.dateFormat( date1, "L", cldr, [{ + type: "month", + value: "1" + }] ); + assert.dateFormat( date2, "L", cldr, [{ + type: "month", + value: "9" + }] ); }); QUnit.test( "should format month (MM|LL) with padding", function( assert ) { - assert.dateFormat( date1, "MM", cldr, "01" ); - assert.dateFormat( date2, "MM", cldr, "09" ); - assert.dateFormat( date1, "LL", cldr, "01" ); - assert.dateFormat( date2, "LL", cldr, "09" ); + assert.dateFormat( date1, "MM", cldr, [{ + type: "month", + value: "01" + }] ); + assert.dateFormat( date2, "MM", cldr, [{ + type: "month", + value: "09" + }] ); + assert.dateFormat( date1, "LL", cldr, [{ + type: "month", + value: "01" + }] ); + assert.dateFormat( date2, "LL", cldr, [{ + type: "month", + value: "09" + }] ); }); QUnit.test( "should format month (MMM|LLL)", function( assert ) { - assert.dateFormat( date1, "MMM", cldr, "Jan" ); - assert.dateFormat( date2, "MMM", cldr, "Sep" ); - assert.dateFormat( date1, "LLL", cldr, "Jan" ); - assert.dateFormat( date2, "LLL", cldr, "Sep" ); + assert.dateFormat( date1, "MMM", cldr, [{ + type: "month", + value: "Jan" + }] ); + assert.dateFormat( date2, "MMM", cldr, [{ + type: "month", + value: "Sep" + }] ); + assert.dateFormat( date1, "LLL", cldr, [{ + type: "month", + value: "Jan" + }] ); + assert.dateFormat( date2, "LLL", cldr, [{ + type: "month", + value: "Sep" + }] ); }); + QUnit.test( "should format month (MMMM|LLLL)", function( assert ) { - assert.dateFormat( date1, "MMMM", cldr, "January" ); - assert.dateFormat( date2, "MMMM", cldr, "September" ); - assert.dateFormat( date1, "LLLL", cldr, "January" ); - assert.dateFormat( date2, "LLLL", cldr, "September" ); + assert.dateFormat( date1, "MMMM", cldr, [{ + type: "month", + value: "January" + }] ); + assert.dateFormat( date2, "MMMM", cldr, [{ + type: "month", + value: "September" + }] ); + assert.dateFormat( date1, "LLLL", cldr, [{ + type: "month", + value: "January" + }] ); + assert.dateFormat( date2, "LLLL", cldr, [{ + type: "month", + value: "September" + }] ); }); QUnit.test( "should format month (MMMMM|LLLLL)", function( assert ) { - assert.dateFormat( date1, "MMMMM", cldr, "J" ); - assert.dateFormat( date2, "MMMMM", cldr, "S" ); - assert.dateFormat( date1, "LLLLL", cldr, "J" ); - assert.dateFormat( date2, "LLLLL", cldr, "S" ); + assert.dateFormat( date1, "MMMMM", cldr, [{ + type: "month", + value: "J" + }] ); + assert.dateFormat( date2, "MMMMM", cldr, [{ + type: "month", + value: "S" + }] ); + assert.dateFormat( date1, "LLLLL", cldr, [{ + type: "month", + value: "J" + }] ); + assert.dateFormat( date2, "LLLLL", cldr, [{ + type: "month", + value: "S" + }] ); }); /** @@ -217,19 +436,40 @@ QUnit.test( "should format month (MMMMM|LLLLL)", function( assert ) { */ QUnit.test( "should format week of year (w) with no padding", function( assert ) { - assert.dateFormat( date1, "w", cldr, "1" ); - assert.dateFormat( date2, "w", cldr, "38" ); + assert.dateFormat( date1, "w", cldr, [{ + type: "week", + value: "1" + }] ); + assert.dateFormat( date2, "w", cldr, [{ + type: "week", + value: "38" + }] ); }); QUnit.test( "should format week of year (ww) with padding", function( assert ) { - assert.dateFormat( date1, "ww", cldr, "01" ); - assert.dateFormat( date2, "ww", cldr, "38" ); + assert.dateFormat( date1, "ww", cldr, [{ + type: "week", + value: "01" + }] ); + assert.dateFormat( date2, "ww", cldr, [{ + type: "week", + value: "38" + }] ); }); QUnit.test( "should format week of month (W)", function( assert ) { - assert.dateFormat( date1, "W", cldr, "1" ); - assert.dateFormat( date2, "W", cldr, "3" ); - assert.dateFormat( date3, "W", cldr, "5" ); + assert.dateFormat( date1, "W", cldr, [{ + type: "week", + value: "1" + }] ); + assert.dateFormat( date2, "W", cldr, [{ + type: "week", + value: "3" + }] ); + assert.dateFormat( date3, "W", cldr, [{ + type: "week", + value: "5" + }] ); }); /** @@ -237,284 +477,727 @@ QUnit.test( "should format week of month (W)", function( assert ) { */ QUnit.test( "should format day (d) with no padding", function( assert ) { - assert.dateFormat( date1, "d", cldr, "2" ); - assert.dateFormat( date2, "d", cldr, "15" ); + assert.dateFormat( date1, "d", cldr, [{ + type: "day", + value: "2" + }] ); + assert.dateFormat( date2, "d", cldr, [{ + type: "day", + value: "15" + }] ); }); QUnit.test( "should format day (dd) with padding", function( assert ) { - assert.dateFormat( date1, "dd", cldr, "02" ); - assert.dateFormat( date2, "dd", cldr, "15" ); + assert.dateFormat( date1, "dd", cldr, [{ + type: "day", + value: "02" + }] ); + assert.dateFormat( date2, "dd", cldr, [{ + type: "day", + value: "15" + }] ); }); QUnit.test( "should format day of year (D) with no padding", function( assert ) { - assert.dateFormat( date1, "D", cldr, "2" ); - assert.dateFormat( date2, "D", cldr, "258" ); + assert.dateFormat( date1, "D", cldr, [{ + type: "day", + value: "2" + }] ); + assert.dateFormat( date2, "D", cldr, [{ + type: "day", + value: "258" + }] ); }); QUnit.test( "should format day of year (DD|DDD) with padding", function( assert ) { - assert.dateFormat( date1, "DD", cldr, "02" ); - assert.dateFormat( date1, "DDD", cldr, "002" ); - assert.dateFormat( date2, "DD", cldr, "258" ); + assert.dateFormat( date1, "DD", cldr, [{ + type: "day", + value: "02" + }] ); + assert.dateFormat( date1, "DDD", cldr, [{ + type: "day", + value: "002" + }] ); + assert.dateFormat( date2, "DD", cldr, [{ + type: "day", + value: "258" + }] ); }); QUnit.test( "should format day of week in month (F)", function( assert ) { - assert.dateFormat( date1, "F", cldr, "1" ); - assert.dateFormat( date2, "F", cldr, "3" ); + assert.dateFormat( date1, "F", cldr, [{ // TODO is this correct? + type: "day", + value: "1" + }] ); + assert.dateFormat( date2, "F", cldr, [{ + type: "day", + value: "3" + }] ); }); /** * Week day */ - QUnit.test( "should format local day of week (e|c) with no padding", function( assert ) { - assert.dateFormat( date1, "e", cldr, "7" ); - assert.dateFormat( date2, "e", cldr, "4" ); - assert.dateFormat( date1, "c", cldr, "7" ); - assert.dateFormat( date2, "c", cldr, "4" ); + assert.dateFormat( date1, "e", cldr, [{ + type: "weekday", + value: "7" + }] ); + assert.dateFormat( date2, "e", cldr, [{ + type: "weekday", + value: "4" + }] ); + assert.dateFormat( date1, "c", cldr, [{ + type: "weekday", + value: "7" + }] ); + assert.dateFormat( date2, "c", cldr, [{ + type: "weekday", + value: "4" + }] ); }); QUnit.test( "should format local day of week (ee|cc) with padding", function( assert ) { - assert.dateFormat( date1, "ee", cldr, "07" ); - assert.dateFormat( date2, "ee", cldr, "04" ); - assert.dateFormat( date1, "cc", cldr, "07" ); - assert.dateFormat( date2, "cc", cldr, "04" ); + assert.dateFormat( date1, "ee", cldr, [{ + type: "weekday", + value: "07" + }] ); + assert.dateFormat( date2, "ee", cldr, [{ + type: "weekday", + value: "04" + }] ); + assert.dateFormat( date1, "cc", cldr, [{ + type: "weekday", + value: "07" + }] ); + assert.dateFormat( date2, "cc", cldr, [{ + type: "weekday", + value: "04" + }] ); }); QUnit.test( "should format local day of week (E|EE|EEE|eee|ccc)", function( assert ) { - assert.dateFormat( date1, "E", cldr, "Sat" ); - assert.dateFormat( date2, "E", cldr, "Wed" ); - assert.dateFormat( date1, "EE", cldr, "Sat" ); - assert.dateFormat( date2, "EE", cldr, "Wed" ); - assert.dateFormat( date1, "EEE", cldr, "Sat" ); - assert.dateFormat( date2, "EEE", cldr, "Wed" ); - assert.dateFormat( date1, "eee", cldr, "Sat" ); - assert.dateFormat( date2, "eee", cldr, "Wed" ); - assert.dateFormat( date1, "ccc", cldr, "Sat" ); - assert.dateFormat( date2, "ccc", cldr, "Wed" ); + assert.dateFormat( date1, "E", cldr, [{ + type: "weekday", + value: "Sat" + }] ); + assert.dateFormat( date2, "E", cldr, [{ + type: "weekday", + value: "Wed" + }] ); + assert.dateFormat( date1, "EE", cldr, [{ + type: "weekday", + value: "Sat" + }] ); + assert.dateFormat( date2, "EE", cldr, [{ + type: "weekday", + value: "Wed" + }] ); + assert.dateFormat( date1, "EEE", cldr, [{ + type: "weekday", + value: "Sat" + }] ); + assert.dateFormat( date2, "EEE", cldr, [{ + type: "weekday", + value: "Wed" + }] ); + assert.dateFormat( date1, "eee", cldr, [{ + type: "weekday", + value: "Sat" + }] ); + assert.dateFormat( date2, "eee", cldr, [{ + type: "weekday", + value: "Wed" + }] ); + assert.dateFormat( date1, "ccc", cldr, [{ + type: "weekday", + value: "Sat" + }] ); + assert.dateFormat( date2, "ccc", cldr, [{ + type: "weekday", + value: "Wed" + }] ); }); QUnit.test( "should format local day of week (EEEE|eeee|cccc)", function( assert ) { - assert.dateFormat( date1, "EEEE", cldr, "Saturday" ); - assert.dateFormat( date2, "EEEE", cldr, "Wednesday" ); - assert.dateFormat( date1, "eeee", cldr, "Saturday" ); - assert.dateFormat( date2, "eeee", cldr, "Wednesday" ); - assert.dateFormat( date1, "cccc", cldr, "Saturday" ); - assert.dateFormat( date2, "cccc", cldr, "Wednesday" ); + assert.dateFormat( date1, "EEEE", cldr, [{ + type: "weekday", + value: "Saturday" + }] ); + assert.dateFormat( date2, "EEEE", cldr, [{ + type: "weekday", + value: "Wednesday" + }] ); + assert.dateFormat( date1, "eeee", cldr, [{ + type: "weekday", + value: "Saturday" + }] ); + assert.dateFormat( date2, "eeee", cldr, [{ + type: "weekday", + value: "Wednesday" + }] ); + assert.dateFormat( date1, "cccc", cldr, [{ + type: "weekday", + value: "Saturday" + }] ); + assert.dateFormat( date2, "cccc", cldr, [{ + type: "weekday", + value: "Wednesday" + }] ); }); QUnit.test( "should format local day of week (EEEEE|eeeee|ccccc)", function( assert ) { - assert.dateFormat( date1, "EEEEE", cldr, "S" ); - assert.dateFormat( date2, "EEEEE", cldr, "W" ); - assert.dateFormat( date1, "eeeee", cldr, "S" ); - assert.dateFormat( date2, "eeeee", cldr, "W" ); - assert.dateFormat( date1, "ccccc", cldr, "S" ); - assert.dateFormat( date2, "ccccc", cldr, "W" ); + assert.dateFormat( date1, "EEEEE", cldr, [{ + type: "weekday", + value: "S" + }] ); + assert.dateFormat( date2, "EEEEE", cldr, [{ + type: "weekday", + value: "W" + }] ); + assert.dateFormat( date1, "eeeee", cldr, [{ + type: "weekday", + value: "S" + }] ); + assert.dateFormat( date2, "eeeee", cldr, [{ + type: "weekday", + value: "W" + }] ); + assert.dateFormat( date1, "ccccc", cldr, [{ + type: "weekday", + value: "S" + }] ); + assert.dateFormat( date2, "ccccc", cldr, [{ + type: "weekday", + value: "W" + }] ); }); QUnit.test( "should format local day of week (EEEEEE|eeeeee|cccccc)", function( assert ) { - assert.dateFormat( date1, "EEEEEE", cldr, "Sa" ); - assert.dateFormat( date2, "EEEEEE", cldr, "We" ); - assert.dateFormat( date1, "eeeeee", cldr, "Sa" ); - assert.dateFormat( date2, "eeeeee", cldr, "We" ); - assert.dateFormat( date1, "cccccc", cldr, "Sa" ); - assert.dateFormat( date2, "cccccc", cldr, "We" ); + assert.dateFormat( date1, "EEEEEE", cldr, [{ + type: "weekday", + value: "Sa" + }] ); + assert.dateFormat( date2, "EEEEEE", cldr, [{ + type: "weekday", + value: "We" + }] ); + assert.dateFormat( date1, "eeeeee", cldr, [{ + type: "weekday", + value: "Sa" + }] ); + assert.dateFormat( date2, "eeeeee", cldr, [{ + type: "weekday", + value: "We" + }] ); + assert.dateFormat( date1, "cccccc", cldr, [{ + type: "weekday", + value: "Sa" + }] ); + assert.dateFormat( date2, "cccccc", cldr, [{ + type: "weekday", + value: "We" + }] ); }); - /** * Period */ QUnit.test( "should format period (a)", function( assert ) { - assert.dateFormat( date1, "a", cldr, "AM" ); - assert.dateFormat( date2, "a", cldr, "PM" ); + assert.dateFormat( date1, "a", cldr, [{ + type: "dayperiod", + value: "AM" + }] ); + assert.dateFormat( date2, "a", cldr, [{ + type: "dayperiod", + value: "PM" + }] ); }); /** * Hour */ - QUnit.test( "should format hour (h) using 12-hour-cycle [1-12] with no padding", function( assert ) { - assert.dateFormat( date1, "h", cldr, "9" ); - assert.dateFormat( date2, "h", cldr, "5" ); - assert.dateFormat( new Date( 0, 0, 0, 0 ), "h", cldr, "12" ); + assert.dateFormat( date1, "h", cldr, [{ + type: "hour", + value: "9" + }] ); + assert.dateFormat( date2, "h", cldr, [{ + type: "hour", + value: "5" + }] ); + assert.dateFormat( new Date( 0, 0, 0, 0 ), "h", cldr, [{ + type: "hour", + value: "12" + }] ); }); QUnit.test( "should format hour (hh) using 12-hour-cycle [1-12] with padding", function( assert ) { - assert.dateFormat( date1, "hh", cldr, "09" ); - assert.dateFormat( date2, "hh", cldr, "05" ); - assert.dateFormat( new Date( 0, 0, 0, 0 ), "hh", cldr, "12" ); + assert.dateFormat( date1, "hh", cldr, [{ + type: "hour", + value: "09" + }] ); + assert.dateFormat( date2, "hh", cldr, [{ + type: "hour", + value: "05" + }] ); + assert.dateFormat( new Date( 0, 0, 0, 0 ), "hh", cldr,[{ + type: "hour", + value: "12" + }] ); }); QUnit.test( "should format hour (H) using 24-hour-cycle [0-23] with no padding", function( assert ) { - assert.dateFormat( date1, "H", cldr, "9" ); - assert.dateFormat( date2, "H", cldr, "17" ); - assert.dateFormat( new Date( 0, 0, 0, 0 ), "H", cldr, "0" ); + assert.dateFormat( date1, "H", cldr, [{ + type: "hour", + value: "9" + }] ); + assert.dateFormat( date2, "H", cldr, [{ + type: "hour", + value: "17" + }] ); + assert.dateFormat( new Date( 0, 0, 0, 0 ), "H", cldr, [{ + type: "hour", + value: "0" + }] ); }); QUnit.test( "should format hour (HH) using 24-hour-cycle [0-23] with padding", function( assert ) { - assert.dateFormat( date1, "HH", cldr, "09" ); - assert.dateFormat( date2, "HH", cldr, "17" ); - assert.dateFormat( new Date( 0, 0, 0, 0 ), "HH", cldr, "00" ); + assert.dateFormat( date1, "HH", cldr, [{ + type: "hour", + value: "09" + }] ); + assert.dateFormat( date2, "HH", cldr, [{ + type: "hour", + value: "17" + }] ); + assert.dateFormat( new Date( 0, 0, 0, 0 ), "HH", cldr, [{ + type: "hour", + value: "00" + }] ); }); QUnit.test( "should format hour (K) using 12-hour-cycle [0-11] with no padding", function( assert ) { - assert.dateFormat( date1, "K", cldr, "9" ); - assert.dateFormat( date2, "K", cldr, "5" ); - assert.dateFormat( new Date( 0, 0, 0, 0 ), "K", cldr, "0" ); + assert.dateFormat( date1, "K", cldr, [{ + type: "hour", + value: "9" + }] ); + assert.dateFormat( date2, "K", cldr, [{ + type: "hour", + value: "5" + }] ); + assert.dateFormat( new Date( 0, 0, 0, 0 ), "K", cldr, [{ + type: "hour", + value: "0" + }] ); }); QUnit.test( "should format hour (KK) using 12-hour-cycle [0-11] with padding", function( assert ) { - assert.dateFormat( date1, "KK", cldr, "09" ); - assert.dateFormat( date2, "KK", cldr, "05" ); - assert.dateFormat( new Date( 0, 0, 0, 0 ), "KK", cldr, "00" ); + assert.dateFormat( date1, "KK", cldr, [{ + type: "hour", + value: "09" + }] ); + assert.dateFormat( date2, "KK", cldr, [{ + type: "hour", + value: "05" + }] ); + assert.dateFormat( new Date( 0, 0, 0, 0 ), "KK", cldr, [{ + type: "hour", + value: "00" + }] ); }); QUnit.test( "should format hour (k) using 24-hour-cycle [1-24] with no padding", function( assert ) { - assert.dateFormat( date1, "k", cldr, "9" ); - assert.dateFormat( date2, "k", cldr, "17" ); - assert.dateFormat( new Date( 0, 0, 0, 0 ), "k", cldr, "24" ); + assert.dateFormat( date1, "k", cldr, [{ + type: "hour", + value: "9" + }] ); + assert.dateFormat( date2, "k", cldr, [{ + type: "hour", + value: "17" + }] ); + assert.dateFormat( new Date( 0, 0, 0, 0 ), "k", cldr, [{ + type: "hour", + value: "24" + }] ); }); QUnit.test( "should format hour (kk) using 24-hour-cycle [1-24] with padding", function( assert ) { - assert.dateFormat( date1, "kk", cldr, "09" ); - assert.dateFormat( date2, "kk", cldr, "17" ); - assert.dateFormat( new Date( 0, 0, 0, 0 ), "kk", cldr, "24" ); + assert.dateFormat( date1, "kk", cldr, [{ + type: "hour", + value: "09" + }] ); + assert.dateFormat( date2, "kk", cldr, [{ + type: "hour", + value: "17" + }] ); + assert.dateFormat( new Date( 0, 0, 0, 0 ), "kk", cldr, [{ + type: "hour", + value: "24" + }] ); }); QUnit.test( "should format hour (j) using preferred hour format for the locale (h, H, K, or k) with no padding", function( assert ) { - assert.dateFormat( date2, "j", cldr, "5" ); - assert.dateFormat( date2, "j", new Cldr( "pt-BR" ), "17" ); - assert.dateFormat( date2, "j", new Cldr( "de" ), "17" ); - assert.dateFormat( date2, "j", new Cldr( "en-IN" ), "5" ); - assert.dateFormat( date2, "j", new Cldr( "en-GB" ), "17" ); - assert.dateFormat( date2, "j", new Cldr( "ru" ), "17" ); + assert.dateFormat( date2, "j", cldr, [{ + type: "hour", + value: "5" + }] ); + assert.dateFormat( date2, "j", new Cldr( "pt-BR" ), [{ + type: "hour", + value: "17" + }] ); + assert.dateFormat( date2, "j", new Cldr( "de" ), [{ + type: "hour", + value: "17" + }] ); + assert.dateFormat( date2, "j", new Cldr( "en-IN" ), [{ + type: "hour", + value: "5" + }] ); + assert.dateFormat( date2, "j", new Cldr( "en-GB" ), [{ + type: "hour", + value: "17" + }] ); + assert.dateFormat( date2, "j", new Cldr( "ru" ), [{ + type: "hour", + value: "17" + }] ); }); QUnit.test( "should format hour (jj) using preferred hour format for the locale (h, H, K, or k) with padding", function( assert ) { - assert.dateFormat( date1, "jj", cldr, "09" ); - assert.dateFormat( date2, "jj", cldr, "05" ); - assert.dateFormat( new Date( 0, 0, 0, 0 ), "jj", cldr, "12" ); + assert.dateFormat( date1, "jj", cldr, [{ + type: "hour", + value: "09" + }] ); + assert.dateFormat( date2, "jj", cldr, [{ + type: "hour", + value: "05" + }] ); + assert.dateFormat( new Date( 0, 0, 0, 0 ), "jj", cldr, [{ + type: "hour", + value: "12" + }] ); }); /** * Minute */ - QUnit.test( "should format minute (m) with no padding", function( assert ) { - assert.dateFormat( date1, "m", cldr, "5" ); - assert.dateFormat( date2, "m", cldr, "35" ); + assert.dateFormat( date1, "m", cldr, [{ + type: "minute", + value: "5" + }] ); + assert.dateFormat( date2, "m", cldr, [{ + type: "minute", + value: "35" + }] ); }); QUnit.test( "should format minute (mm) with padding", function( assert ) { - assert.dateFormat( date1, "mm", cldr, "05" ); - assert.dateFormat( date2, "mm", cldr, "35" ); + assert.dateFormat( date1, "mm", cldr, [{ + type: "minute", + value: "05" + }] ); + assert.dateFormat( date2, "mm", cldr, [{ + type: "minute", + value: "35" + }] ); }); - /** * Second */ - QUnit.test( "should format second (s) with no padding", function( assert ) { - assert.dateFormat( date1, "s", cldr, "59" ); - assert.dateFormat( date2, "s", cldr, "7" ); + assert.dateFormat( date1, "s", cldr, [{ + type: "second", + value: "59" + }] ); + assert.dateFormat( date2, "s", cldr, [{ + type: "second", + value: "7" + }] ); }); QUnit.test( "should format second (ss) with padding", function( assert ) { - assert.dateFormat( date1, "ss", cldr, "59" ); - assert.dateFormat( date2, "ss", cldr, "07" ); + assert.dateFormat( date1, "ss", cldr, [{ + type: "second", + value: "59" + }] ); + assert.dateFormat( date2, "ss", cldr, [{ + type: "second", + value: "07" + }] ); }); QUnit.test( "should format various milliseconds (S+)", function( assert ) { - assert.dateFormat( date2, "S", cldr, "4" ); - assert.dateFormat( date2, "SS", cldr, "37" ); - assert.dateFormat( date2, "SSS", cldr, "369" ); - assert.dateFormat( date2, "SSSS", cldr, "3690" ); - assert.dateFormat( date2, "SSSSS", cldr, "36900" ); + assert.dateFormat( date2, "S", cldr, [{ + type: "second", + value: "4" + }] ); + assert.dateFormat( date2, "SS", cldr, [{ + type: "second", + value: "37" + }] ); + assert.dateFormat( date2, "SSS", cldr, [{ + type: "second", + value: "369" + }] ); + assert.dateFormat( date2, "SSSS", cldr, [{ + type: "second", + value: "3690" + }] ); + assert.dateFormat( date2, "SSSSS", cldr, [{ + type: "second", + value: "36900" + }] ); }); QUnit.test( "should format various milliseconds (A+)", function( assert ) { - assert.dateFormat( date2, "A", cldr, "633074" ); - assert.dateFormat( date2, "AA", cldr, "6330737" ); - assert.dateFormat( date2, "AAA", cldr, "63307369" ); - assert.dateFormat( date2, "AAAA", cldr, "633073690" ); - assert.dateFormat( date2, "AAAAA", cldr, "6330736900" ); + assert.dateFormat( date2, "A", cldr, [{ + type: "second", + value: "633074" + }] ); + + assert.dateFormat( date2, "AA", cldr, [{ + type: "second", + value: "6330737" + }] ); + + assert.dateFormat( date2, "AAA", cldr, [{ + type: "second", + value: "63307369" + }] ); + + assert.dateFormat( date2, "AAAA", cldr, [{ + type: "second", + value: "633073690" + }] ); + + assert.dateFormat( date2, "AAAAA", cldr, [{ + type: "second", + value: "6330736900" + }] ); }); /** * Zone */ - QUnit.test( "should format timezone (z)", function( assert ) { var date = new FakeDate( 0 ); - assert.dateFormat( date, "z", cldr, "GMT" ); - assert.dateFormat( date, "zz", cldr, "GMT" ); - assert.dateFormat( date, "zzz", cldr, "GMT" ); - assert.dateFormat( date, "zzzz", cldr, "GMT" ); + assert.dateFormat( date, "z", cldr, [{ + type: "zone", + value: "GMT" + }] ); + assert.dateFormat( date, "zz", cldr, [{ + type: "zone", + value: "GMT" + }] ); + assert.dateFormat( date, "zzz", cldr, [{ + type: "zone", + value: "GMT" + }] ); + assert.dateFormat( date, "zzzz", cldr, [{ + type: "zone", + value: "GMT" + }] ); date = new FakeDate( -3 ); - assert.dateFormat( date, "z", cldr, "GMT-3" ); - assert.dateFormat( date, "zz", cldr, "GMT-3" ); - assert.dateFormat( date, "zzz", cldr, "GMT-3" ); - assert.dateFormat( date, "zzzz", cldr, "GMT-03:00" ); + assert.dateFormat( date, "z", cldr,[{ + type: "zone", + value: "GMT-3" + }] ); + assert.dateFormat( date, "zz", cldr,[{ + type: "zone", + value: "GMT-3" + }] ); + assert.dateFormat( date, "zzz", cldr,[{ + type: "zone", + value: "GMT-3" + }] ); + assert.dateFormat( date, "zzzz", cldr, [{ + type: "zone", + value: "GMT-03:00" + }] ); date = new FakeDate( 11 ); - assert.dateFormat( date, "z", cldr, "GMT+11" ); - assert.dateFormat( date, "zz", cldr, "GMT+11" ); - assert.dateFormat( date, "zzz", cldr, "GMT+11" ); - assert.dateFormat( date, "zzzz", cldr, "GMT+11:00" ); + assert.dateFormat( date, "z", cldr, [{ + type: "zone", + value: "GMT+11" + }] ); + assert.dateFormat( date, "zz", cldr, [{ + type: "zone", + value: "GMT+11" + }] ); + assert.dateFormat( date, "zzz", cldr, [{ + type: "zone", + value: "GMT+11" + }] ); + assert.dateFormat( date, "zzzz", cldr, [{ + type: "zone", + value: "GMT+11:00" + }] ); }); QUnit.test( "should format timezone (Z)", function( assert ) { var date = new FakeDate( 0 ); - assert.dateFormat( date, "Z", cldr, "+0000" ); - assert.dateFormat( date, "ZZ", cldr, "+0000" ); - assert.dateFormat( date, "ZZZ", cldr, "+0000" ); - assert.dateFormat( date, "ZZZZ", cldr, "GMT" ); - assert.dateFormat( date, "ZZZZZ", cldr, "Z" ); + assert.dateFormat( date, "Z", cldr, [{ + type: "zone", + value: "+0000" + }] ); + + assert.dateFormat( date, "ZZ", cldr, [{ + type: "zone", + value: "+0000" + }] ); + + assert.dateFormat( date, "ZZZ", cldr, [{ + type: "zone", + value: "+0000" + }] ); + + assert.dateFormat( date, "ZZZZ", cldr,[{ + type: "zone", + value: "GMT" + }] ); + assert.dateFormat( date, "ZZZZZ", cldr, [{ + type: "zone", + value: "Z" + }] ); date = new FakeDate( -3 ); - assert.dateFormat( date, "Z", cldr, "-0300" ); - assert.dateFormat( date, "ZZ", cldr, "-0300" ); - assert.dateFormat( date, "ZZZ", cldr, "-0300" ); - assert.dateFormat( date, "ZZZZ", cldr, "GMT-03:00" ); - assert.dateFormat( date, "ZZZZZ", cldr, "-03:00" ); + assert.dateFormat( date, "Z", cldr, [{ + type: "zone", + value: "-0300" + }] ); + assert.dateFormat( date, "ZZ", cldr, [{ + type: "zone", + value: "-0300" + }] ); + + assert.dateFormat( date, "ZZZ", cldr, [{ + type: "zone", + value: "-0300" + }] ); + + assert.dateFormat( date, "ZZZZ", cldr, [{ + type: "zone", + value: "GMT-03:00" + }] ); + + assert.dateFormat( date, "ZZZZZ", cldr, [{ + type: "zone", + value: "-03:00" + }] ); date = new FakeDate( 11 ); - assert.dateFormat( date, "Z", cldr, "+1100" ); - assert.dateFormat( date, "ZZ", cldr, "+1100" ); - assert.dateFormat( date, "ZZZ", cldr, "+1100" ); - assert.dateFormat( date, "ZZZZ", cldr, "GMT+11:00" ); - assert.dateFormat( date, "ZZZZZ", cldr, "+11:00" ); + assert.dateFormat( date, "Z", cldr, [{ + type: "zone", + value: "+1100" + }] ); + assert.dateFormat( date, "ZZ", cldr, [{ + type: "zone", + value: "+1100" + }] ); + assert.dateFormat( date, "ZZZ", cldr, [{ + type: "zone", + value: "+1100" + }] ); + + assert.dateFormat( date, "ZZZZ", cldr, [{ + type: "zone", + value: "GMT+11:00" + }] ); + assert.dateFormat( date, "ZZZZZ", cldr, [{ + type: "zone", + value: "+11:00" + }] ); }); QUnit.test( "should format timezone (O)", function( assert ) { var date = new FakeDate( 0 ); - assert.dateFormat( date, "O", cldr, "GMT" ); - assert.dateFormat( date, "OOOO", cldr, "GMT" ); + assert.dateFormat( date, "O", cldr, [{ + type: "zone", + value: "GMT" + }] ); + assert.dateFormat( date, "OOOO", cldr, [{ + type: "zone", + value: "GMT" + }] ); date = new FakeDate( -3 ); - assert.dateFormat( date, "O", cldr, "GMT-3" ); - assert.dateFormat( date, "OOOO", cldr, "GMT-03:00" ); + assert.dateFormat( date, "O", cldr, [{ + type: "zone", + value: "GMT-3" + }] ); + + assert.dateFormat( date, "OOOO", cldr, [{ + type: "zone", + value: "GMT-03:00" + }] ); date = new FakeDate( 11 ); - assert.dateFormat( date, "O", cldr, "GMT+11" ); - assert.dateFormat( date, "OOOO", cldr, "GMT+11:00" ); + assert.dateFormat( date, "O", cldr, [{ + type: "zone", + value: "GMT+11" + }] ); + + assert.dateFormat( date, "OOOO", cldr, [{ + type: "zone", + value: "GMT+11:00" + }] ); }); QUnit.test( "should format timezone (X)", function( assert ) { var date = new FakeDate( 0 ); - assert.dateFormat( date, "X", cldr, "Z" ); - assert.dateFormat( date, "XX", cldr, "Z" ); - assert.dateFormat( date, "XXX", cldr, "Z" ); - assert.dateFormat( date, "XXXX", cldr, "Z" ); - assert.dateFormat( date, "XXXXX", cldr, "Z" ); + assert.dateFormat( date, "X", cldr, [{ + type: "zone", + value: "Z" + }] ); + + assert.dateFormat( date, "XX", cldr, [{ + type: "zone", + value: "Z" + }] ); + + assert.dateFormat( date, "XXX", cldr, [{ + type: "zone", + value: "Z" + }] ); + + assert.dateFormat( date, "XXXX", cldr, [{ + type: "zone", + value: "Z" + }] ); + + assert.dateFormat( date, "XXXXX", cldr, [{ + type: "zone", + value: "Z" + }] ); date = new FakeDate( -3 ); - assert.dateFormat( date, "X", cldr, "-03" ); - assert.dateFormat( date, "XX", cldr, "-0300" ); - assert.dateFormat( date, "XXX", cldr, "-03:00" ); - assert.dateFormat( date, "XXXX", cldr, "-0300" ); - assert.dateFormat( date, "XXXXX", cldr, "-03:00" ); + assert.dateFormat( date, "X", cldr, [{ + type: "zone", + value: "-03" + }] ); + + assert.dateFormat( date, "XX", cldr, [{ + type: "zone", + value: "-0300" + }] ); + + assert.dateFormat( date, "XXX", cldr, [{ + type: "zone", + value: "-03:00" + }] ); + + assert.dateFormat( date, "XXXX", cldr, [{ + type: "zone", + value: "-0300" + }] ); + + assert.dateFormat( date, "XXXXX", cldr, [{ + type: "zone", + value: "-03:00" + }] ); // TODO (see https://github.com/jquery/globalize/issues/339) // date = new FakeDate( -7.883 ); @@ -528,33 +1211,101 @@ QUnit.test( "should format timezone (X)", function( assert ) { // TODO (see https://github.com/jquery/globalize/issues/339) // assert.dateFormat( date, "X", cldr, "+0530" ); - assert.dateFormat( date, "XX", cldr, "+0530" ); - assert.dateFormat( date, "XXX", cldr, "+05:30" ); - assert.dateFormat( date, "XXXX", cldr, "+0530" ); - assert.dateFormat( date, "XXXXX", cldr, "+05:30" ); + assert.dateFormat( date, "XX", cldr, [{ + type: "zone", + value: "+0530" + }] ); + + assert.dateFormat( date, "XXX", cldr, [{ + type: "zone", + value: "+05:30" + }] ); + + assert.dateFormat( date, "XXXX", cldr, [{ + type: "zone", + value: "+0530" + }] ); + + assert.dateFormat( date, "XXXXX", cldr, [{ + type: "zone", + value: "+05:30" + }] ); date = new FakeDate( 11 ); - assert.dateFormat( date, "X", cldr, "+11" ); - assert.dateFormat( date, "XX", cldr, "+1100" ); - assert.dateFormat( date, "XXX", cldr, "+11:00" ); - assert.dateFormat( date, "XXXX", cldr, "+1100" ); - assert.dateFormat( date, "XXXXX", cldr, "+11:00" ); + assert.dateFormat( date, "X", cldr, [{ + type: "zone", + value: "+11" + }] ); + + assert.dateFormat( date, "XX", cldr, [{ + type: "zone", + value: "+1100" + }] ); + + assert.dateFormat( date, "XXX", cldr, [{ + type: "zone", + value: "+11:00" + }] ); + + assert.dateFormat( date, "XXXX", cldr, [{ + type: "zone", + value: "+1100" + }] ); + + assert.dateFormat( date, "XXXXX", cldr, [{ + type: "zone", + value: "+11:00" + }] ); }); QUnit.test( "should format timezone (x)", function( assert ) { var date = new FakeDate( 0 ); - assert.dateFormat( date, "x", cldr, "+00" ); - assert.dateFormat( date, "xx", cldr, "+0000" ); - assert.dateFormat( date, "xxx", cldr, "+00:00" ); - assert.dateFormat( date, "xxxx", cldr, "+0000" ); - assert.dateFormat( date, "xxxxx", cldr, "+00:00" ); + assert.dateFormat( date, "x", cldr, [{ + type: "zone", + value: "+00" + }] ); + assert.dateFormat( date, "xx", cldr, [{ + type: "zone", + value: "+0000" + }] ); + + assert.dateFormat( date, "xxx", cldr, [{ + type: "zone", + value: "+00:00" + }] ); + + assert.dateFormat( date, "xxxx", cldr, [{ + type: "zone", + value: "+0000" + }] ); + + assert.dateFormat( date, "xxxxx", cldr, [{ + type: "zone", + value: "+00:00" + }] ); + date = new FakeDate( -3 ); - assert.dateFormat( date, "x", cldr, "-03" ); - assert.dateFormat( date, "xx", cldr, "-0300" ); - assert.dateFormat( date, "xxx", cldr, "-03:00" ); - assert.dateFormat( date, "xxxx", cldr, "-0300" ); - assert.dateFormat( date, "xxxxx", cldr, "-03:00" ); + assert.dateFormat( date, "x", cldr, [{ + type: "zone", + value: "-03" + }] ); + assert.dateFormat( date, "xx", cldr, [{ + type: "zone", + value: "-0300" + }] ); + assert.dateFormat( date, "xxx", cldr, [{ + type: "zone", + value: "-03:00" + }] ); + assert.dateFormat( date, "xxxx", cldr, [{ + type: "zone", + value: "-0300" + }] ); + assert.dateFormat( date, "xxxxx", cldr, [{ + type: "zone", + value: "-03:00" + }] ); // TODO (see https://github.com/jquery/globalize/issues/339) // date = new FakeDate( -7.883 ); @@ -568,26 +1319,136 @@ QUnit.test( "should format timezone (x)", function( assert ) { // TODO (see https://github.com/jquery/globalize/issues/339) // assert.dateFormat( date, "x", cldr, "+0530" ); - assert.dateFormat( date, "xx", cldr, "+0530" ); - assert.dateFormat( date, "xxx", cldr, "+05:30" ); - assert.dateFormat( date, "xxxx", cldr, "+0530" ); - assert.dateFormat( date, "xxxxx", cldr, "+05:30" ); + assert.dateFormat( date, "xx", cldr, [{ + type: "zone", + value: "+0530" + }] ); + + assert.dateFormat( date, "xxx", cldr, [{ + type: "zone", + value: "+05:30" + }] ); + + assert.dateFormat( date, "xxxx", cldr, [{ + type: "zone", + value: "+0530" + }] ); + + assert.dateFormat( date, "xxxxx", cldr, [{ + type: "zone", + value: "+05:30" + }] ); date = new FakeDate( 11 ); - assert.dateFormat( date, "x", cldr, "+11" ); - assert.dateFormat( date, "xx", cldr, "+1100" ); - assert.dateFormat( date, "xxx", cldr, "+11:00" ); - assert.dateFormat( date, "xxxx", cldr, "+1100" ); - assert.dateFormat( date, "xxxxx", cldr, "+11:00" ); + assert.dateFormat( date, "x", cldr, [{ + type: "zone", + value: "+11" + }] ); + + assert.dateFormat( date, "xx", cldr, [{ + type: "zone", + value: "+1100" + }] ); + + assert.dateFormat( date, "xxx", cldr, [{ + type: "zone", + value: "+11:00" + }] ); + + assert.dateFormat( date, "xxxx", cldr, [{ + type: "zone", + value: "+1100" + }] ); + + assert.dateFormat( date, "xxxxx", cldr, [{ + type: "zone", + value: "+11:00" + }] ); }); /** * Literal */ - QUnit.test( "should format literal (')", function( assert ) { - assert.dateFormat( date1, "yyyy.MM.dd G 'at' HH:mm:ss", cldr, "1982.01.02 AD at 09:05:59" ); - assert.dateFormat( date1, "hh 'o''clock' a", cldr, "09 o'clock AM" ); + + var result = [ + { + "type": "year", + "value": "1982" + }, + { + "type": "literal", + "value": "." + }, + { + "type": "month", + "value": "01" + }, + { + "type": "literal", + "value": "." + }, + { + "type": "day", + "value": "02" + }, + { + "type": "literal", + "value": " " + }, + { + "type": "era", + "value": "AD" + }, + { + "type": "literal", + "value": " at " + }, + { + "type": "hour", + "value": "09" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "minute", + "value": "05" + }, + { + "type": "literal", + "value": ":" + }, + { + "type": "second", + "value": "59" + } + ]; + //assert.dateFormat( date1, "yyyy.MM.dd G 'at' HH:mm:ss", cldr, "1982.01.02 AD at 09:05:59" ); + assert.dateFormat( date1, "yyyy.MM.dd G 'at' HH:mm:ss", cldr, result ); + + result = [ + { + "type": "hour", + "value": "09" + }, + { + "type": "literal", + "value": " o'clock " + }, + { + "type": "dayperiod", + "value": "AM" + } + ]; + + //assert.dateFormat( date1, "hh 'o''clock' a", cldr, "09 o'clock AM" ); + assert.dateFormat( date1, "hh 'o''clock' a", cldr, result ); }); }); + + + +