<|start_filename|>src/number/format-properties.js<|end_filename|>
define([
	"./compact",
	"./numbering-system-digits-map",
	"./pattern-properties",
	"./symbol",
	"./symbol/map",
	"../util/number/round"
], function( numberCompact, numberNumberingSystemDigitsMap, numberPatternProperties, numberSymbol,
	numberSymbolMap, numberRound ) {

/**
 * formatProperties( pattern, cldr [, options] )
 *
 * @pattern [String] raw pattern for numbers.
 *
 * @cldr [Cldr instance].
 *
 * @options [Object]:
 * - minimumIntegerDigits [Number]
 * - minimumFractionDigits, maximumFractionDigits [Number]
 * - minimumSignificantDigits, maximumSignificantDigits [Number]
 * - round [String] "ceil", "floor", "round" (default), or "truncate".
 * - useGrouping [Boolean] default true.
 *
 * Return the processed properties that will be used in number/format.
 * ref: http://www.unicode.org/reports/tr35/tr35-numbers.html
 */
return function( pattern, cldr, options ) {
	var negativePattern, negativePrefix, negativeProperties, negativeSuffix, positivePattern,
		roundFn, properties;

	function getOptions( attribute, propertyIndex ) {
		if ( attribute in options ) {
			properties[ propertyIndex ] = options[ attribute ];
		}
	}

	options = options || {};
	pattern = pattern.split( ";" );

	positivePattern = pattern[ 0 ];

	negativePattern = pattern[ 1 ] || "-" + positivePattern;
	negativeProperties = numberPatternProperties( negativePattern );
	negativePrefix = negativeProperties[ 0 ];
	negativeSuffix = negativeProperties[ 10 ];

	// Have runtime code to refer to numberRound() instead of including it explicitly.
	roundFn = numberRound( options.round );
	roundFn.generatorString = function() {
		return "numberRound(" + ( options.round ? "\"" + options.round + "\"" : "" ) + ")";
	};

	properties = numberPatternProperties( positivePattern ).concat([
		positivePattern,
		negativePrefix + positivePattern + negativeSuffix,
		negativePrefix,
		negativeSuffix,
		roundFn,
		numberSymbol( "infinity", cldr ),
		numberSymbol( "nan", cldr ),
		numberSymbolMap( cldr ),
		numberNumberingSystemDigitsMap( cldr )
	]);

	if ( options.compact ) {

		// The compact digits number pattern is always `0+`, so override the following properties.
		// Note: minimumIntegerDigits would actually range from `0` to `000` based on the scale of
		// the value to be formatted, though we're always using 1 as a simplification, because the
		// number won't be zero-padded since we chose the right format based on the scale, i.e.,
		// we'd never see something like `003M` anyway.
		properties[ 2 ] = 1; // minimumIntegerDigits
		properties[ 3 ] = 0; // minimumFractionDigits
		properties[ 4 ] = 0; // maximumFractionDigits
		properties[ 5 ] = // minimumSignificantDigits &
			properties[ 6 ] = undefined; // maximumSignificantDigits

		properties[ 20 ] = numberCompact( options.compact, cldr );
	}

	getOptions( "minimumIntegerDigits", 2 );
	getOptions( "minimumFractionDigits", 3 );
	getOptions( "maximumFractionDigits", 4 );
	getOptions( "minimumSignificantDigits", 5 );
	getOptions( "maximumSignificantDigits", 6 );

	// Grouping separators
	if ( options.useGrouping === false ) {
		properties[ 8 ] = null;
	}

	// Normalize number of digits if only one of either minimumFractionDigits or
	// maximumFractionDigits is passed in as an option
	if ( "minimumFractionDigits" in options && !( "maximumFractionDigits" in options ) ) {

		// maximumFractionDigits = Math.max( minimumFractionDigits, maximumFractionDigits );
		properties[ 4 ] = Math.max( properties[ 3 ], properties[ 4 ] );
	} else if ( !( "minimumFractionDigits" in options ) &&
			"maximumFractionDigits" in options ) {

		// minimumFractionDigits = Math.min( minimumFractionDigits, maximumFractionDigits );
		properties[ 3 ] = Math.min( properties[ 3 ], properties[ 4 ] );
	}

	// Return:
	// 0-10: see number/pattern-properties.
	// 11: @positivePattern [String] Positive pattern.
	// 12: @negativePattern [String] Negative pattern.
	// 13: @negativePrefix [String] Negative prefix.
	// 14: @negativeSuffix [String] Negative suffix.
	// 15: @round [Function] Round function.
	// 16: @infinitySymbol [String] Infinity symbol.
	// 17: @nanSymbol [String] NaN symbol.
	// 18: @symbolMap [Object] A bunch of other symbols.
	// 19: @nuDigitsMap [Array] Digits map if numbering system is different than `latn`.
	// 20: @compactMap [Object] Map of per-digit-count format patterns for specified compact mode.
	return properties;
};

});


<|start_filename|>test/compiler/test.js<|end_filename|>
var globalizeCompiler = require( "globalize-compiler" );
var fs = require( "fs" );
var path = require( "path" );
var childProcess = require( "child_process" );
var assert = require( "assert" );
var glob = require( "glob" );

describe( "compiled", function() {
	if ( !fs.existsSync( path.join( __dirname, "_compiled" ) ) ) {
		fs.mkdirSync( path.join( __dirname, "_compiled" ) );
	}
	var files = glob.sync( "cases/*.js", {
		cwd: __dirname
	} );
	files.forEach( function(file) {
		var name = path.basename( file, ".js" );
		describe( name, function() {
			it( "should return identical data", function( done ) {
				var test = require( "./" + file );
				var expectedOutput = "";
				var formatters = [];
				var testCases = test.cases( test.dependencies() );
				testCases.forEach( function( testCase ) {
					formatters.push( testCase.formatter );
					expectedOutput += testCase.formatter.apply( null, testCase.args ) + "\n";
				});
				var out = globalizeCompiler.compile( formatters, {
					template: function( data ) {
						var deps = "var Globalize = " +
							data.dependencies.map( function( dependency ) {
								return "require( \"../../../dist/" + dependency + "\" )";
							} ).join( ";\n" );
						return [
							deps,
							"",
							data.code,
							"",
							"module.exports = Globalize;"
						].join( "\n" );
					}
				} );
				fs.writeFileSync( path.join( __dirname, "_compiled/" + name + ".compiled.js" ), out );
				fs.writeFileSync( path.join( __dirname, "_compiled/" + name + ".test.js" ), [
					"var test = require( \"../" + file + "\" );",
					"var Globalize = require( \"../_compiled/" + name + ".compiled.js\" );",
					"testCases = test.cases( Globalize );",
					"testCases.forEach( function( testCase ) {",
						"console.log( testCase.formatter.apply( null, testCase.args ) );",
					"});"
				].join("\n") );
				var childOutput = "";
				var child = childProcess.fork(
					path.join( __dirname, "_compiled/" + name + ".test.js" ),
					{ silent: true }
				);
				child.on( "error", function( err ) {
					done( err );
				} );
				child.on( "exit", function( exit ) {
					if ( exit !== 0 ) {
						done( new Error( "exited with non-zero" ) );
					}
				} );
				child.stdout.on( "data", function( chunk ) {
					childOutput += chunk.toString();
				} );
				child.stdout.on( "end", function() {
					assert.equal( childOutput, expectedOutput );
					done();
				} );
			} );
		} );
	} );
} );


<|start_filename|>test/unit/util/regexp/not-s.js<|end_filename|>
define([
    "src/util/regexp/not-s",
], function( regexpNotS ) {

    QUnit.module( "Util regexp ^S" );

    [
        {
            symbol: "௹",
            category: "Sc"
        },
        {
            symbol: "꜏",
            category: "Sk"
        },
        {
            symbol: "∇",
            category: "Sm"
        },
        {
            symbol: "❤",
            category: "So"
        }
    ].forEach(function( c ) {
        QUnit.test("it should NOT match category " + c.category, function( assert ) {
            assert.notOk(regexpNotS.test(c.symbol));
        });
    });

    [
        {
            symbol: "𒐖",
            category: "Nl"
        },
        {
            symbol: "א",
            category: "Lo"
        },
        {
            symbol: "\u2028",
            category: "Zl"
        },
        {
            symbol: "\u2029",
            category: "Zp"
        },
        {
            symbol: "\u2003",
            category: "Zs"
        }
    ].forEach(function( c ) {
        QUnit.test("it should match category " + c.category, function( assert ) {
            assert.ok(regexpNotS.test(c.symbol));
        });
    });
});


<|start_filename|>test/unit/relative-time/properties.js<|end_filename|>
define([
	"cldr",
	"src/relative-time/properties",
	"json!cldr-data/main/en/dateFields.json",
	"json!cldr-data/main/de/dateFields.json",
	"json!cldr-data/supplemental/likelySubtags.json",

	"cldr/event",
	"cldr/supplemental"
], function( Cldr, properties, enDateFields, deDateFields, likelySubtags ) {

var cldr, de;

Cldr.load( enDateFields );
Cldr.load( deDateFields );
Cldr.load( likelySubtags );

cldr = new Cldr( "en" );
de = new Cldr( "de" );

QUnit.module( "Relative Time Properties" );

QUnit.test( "should return month info in english", function( assert ) {
	assert.deepEqual( properties( "month", cldr, {} ), {
		"relative-type--1": "last month",
		"relative-type-0": "this month",
		"relative-type-1": "next month",
		"relativeTime-type-future": {
			"relativeTimePattern-count-one": "in {0} month",
			"relativeTimePattern-count-other": "in {0} months"
		},
		"relativeTime-type-past": {
			"relativeTimePattern-count-one": "{0} month ago",
			"relativeTimePattern-count-other": "{0} months ago"
		}
	});
});

QUnit.test( "should return complete day info in german", function( assert ) {
	assert.deepEqual( properties( "day", de, {} ), {
		"relative-type--1": "gestern",
		"relative-type--2": "vorgestern",
		"relative-type-0": "heute",
		"relative-type-1": "morgen",
		"relative-type-2": "übermorgen",
		"relativeTime-type-future": {
			"relativeTimePattern-count-one": "in {0} Tag",
			"relativeTimePattern-count-other": "in {0} Tagen"
		},
		"relativeTime-type-past": {
			"relativeTimePattern-count-one": "vor {0} Tag",
			"relativeTimePattern-count-other": "vor {0} Tagen"
		}
	});
});

QUnit.test( "should return short info when requested", function( assert ) {
	assert.deepEqual( properties( "month", cldr, { form: "short" } ), {
		"relative-type--1": "last mo.",
		"relative-type-0": "this mo.",
		"relative-type-1": "next mo.",
		"relativeTime-type-future": {
			"relativeTimePattern-count-one": "in {0} mo.",
			"relativeTimePattern-count-other": "in {0} mo."
		},
		"relativeTime-type-past": {
			"relativeTimePattern-count-one": "{0} mo. ago",
			"relativeTimePattern-count-other": "{0} mo. ago"
		}
	});
});

QUnit.test( "should return narrow info when requested", function( assert ) {
	assert.deepEqual( properties( "month", cldr, { form: "narrow" } ), {
		"relative-type--1": "last mo.",
		"relative-type-0": "this mo.",
		"relative-type-1": "next mo.",
		"relativeTime-type-future": {
			"relativeTimePattern-count-one": "in {0} mo.",
			"relativeTimePattern-count-other": "in {0} mo."
		},
		"relativeTime-type-past": {
			"relativeTimePattern-count-one": "{0} mo. ago",
			"relativeTimePattern-count-other": "{0} mo. ago"
		}
	});
});

});


<|start_filename|>src/util/regexp/zs-g.js<|end_filename|>
define(function() {

/**
 * Generated by:
 *
 * var regenerate = require( "regenerate" );
 * var spaceSeparatorSymbols = require( "@unicode/unicode-13.0.0/General_Category/Space_Separator/symbols" );
 * regenerate().add( spaceSeparatorSymbols ).toString();
 *
 * https://github.com/mathiasbynens/regenerate
 * https://github.com/node-unicode/unicode-13.0.0
 */
return /[ \xA0\u1680\u2000-\u200A\u202F\u205F\u3000]/g;

});


<|start_filename|>test/unit/number/parse-properties.js<|end_filename|>
define([
	"cldr",
	"src/number/parse-properties",
	"json!cldr-data/main/ar/numbers.json",
	"json!cldr-data/main/en/numbers.json",
	"json!cldr-data/main/es/numbers.json",
	"json!cldr-data/main/fa/numbers.json",
	"json!cldr-data/main/sv/numbers.json",
	"json!cldr-data/supplemental/likelySubtags.json",

	"cldr/event",
	"cldr/supplemental"
], function( Cldr, properties, arNumbers, enNumbers, esNumbers, faNumbers, svNumbers,
	likelySubtags ) {

var ar, en, es, sv;

Cldr.load(
	arNumbers,
	enNumbers,
	esNumbers,
	faNumbers,
	svNumbers,
	likelySubtags
);

ar = new Cldr( "ar" );
en = new Cldr( "en" );
es = new Cldr( "es" );
sv = new Cldr( "sv" );

QUnit.module( "Number Parse Properties" );

QUnit.test( "should return invertedSymbolMap", function( assert ) {
	assert.deepEqual( properties( "0", es )[ 0 ], {
		"%": "%",
		"+": "+",
		",": ".",
		"-": "-",
		".": ",",
		"E": "E",
		"‰": "‰"
	});

	// Note grouping separator is using regular U+0020 SPACE due to loose matching.
	assert.deepEqual( properties( "0", sv )[ 0 ], {
		"%": "%",
		"+": "+",
		",": ".",
		" ": ",",
		"×10^": "E",
		"‰": "‰",
		"-": "-"
	});
});

QUnit.test( "should return invertedNuDigitsMap", function( assert ) {
	assert.deepEqual( properties( "0", ar )[ 1 ], {
		"٠": "0",
		"١": "1",
		"٢": "2",
		"٣": "3",
		"٤": "4",
		"٥": "5",
		"٦": "6",
		"٧": "7",
		"٨": "8",
		"٩": "9"
	});
});

QUnit.test( "should return infinity tokenizer", function( assert ) {
	assert.deepEqual( properties( "0", en )[ 2 ].infinity, /^∞/ );
});

QUnit.test( "should return NaN tokenizer", function( assert ) {
	assert.deepEqual( properties( "0", en )[ 2 ].nan, /^NaN/ );
	assert.deepEqual( properties( "0", ar )[ 2 ].nan, /^ليس رقم/ );
});

QUnit.test( "should return negativePrefix tokenizer", function( assert ) {
	assert.deepEqual( properties( "0", en )[ 2 ].negativePrefix, /^-/ );
	assert.deepEqual( properties( "0;(0)", en )[ 2 ].negativePrefix, /^\(/ );
	});

QUnit.test( "should return negativeSuffix tokenizer", function( assert ) {
	assert.deepEqual( properties( "0", en )[ 2 ].negativeSuffix, /^/ );
	assert.deepEqual( properties( "0;(0)", en )[ 2 ].negativeSuffix, /^\)/ );
});

QUnit.test( "should return number tokenizer", function( assert ) {
	assert.deepEqual( properties( "0", en )[ 2 ].number, /^\d+/ );
	assert.deepEqual( properties( "0.##", en )[ 2 ].number, /^(\d+(\.\d+|\.)?|(\d+)?\.\d+)/ );

	assert.deepEqual(
		properties( "#,##0.##", en )[ 2 ].number,
		/^((\d{1,3}(,\d{3})+|\d+)(\.\d+|\.)?|((\d{1,3}(,\d{3})+|\d+))?\.\d+)/
	);

	assert.deepEqual(
		properties( "#,##0.##", es )[ 2 ].number,
		/^((\d{1,3}(\.\d{3})+|\d+)(,\d+|,)?|((\d{1,3}(\.\d{3})+|\d+))?,\d+)/
	);

	assert.deepEqual(
		properties( "#,##,##0.##", en )[ 2 ].number,
		/^((\d{1,2}((,\d{2})*(,\d{3}))|\d+)(\.\d+|\.)?|((\d{1,2}((,\d{2})*(,\d{3}))|\d+))?\.\d+)/
	);

	assert.deepEqual(
		properties( "#,##0.##", sv )[ 2 ].number,
		/^((\d{1,3}( \d{3})+|\d+)(,\d+|,)?|((\d{1,3}( \d{3})+|\d+))?,\d+)/
	);
});

QUnit.test( "should return prefix tokenizer", function( assert ) {
	assert.deepEqual( properties( "%0", en )[ 2 ].prefix, /^%/ );
	assert.deepEqual( properties( "'$'0.##", en )[ 2 ].prefix, /^\$/ );
	assert.deepEqual( properties( "'$ '0.##", en )[ 2 ].prefix, /^\$ / );
	assert.deepEqual( properties( "'foo''bar'0.##", en )[ 2 ].prefix, /^foo'bar/ );
	assert.deepEqual( properties( "-'foo''bar'0.##", en )[ 2 ].prefix, /^-foo'bar/ );
});

QUnit.test( "should return suffix tokenizer", function( assert ) {
	assert.deepEqual( properties( "#,##0%", en )[ 2 ].suffix, /^%/ );
	assert.deepEqual( properties( "#,##0 %", ar )[ 2 ].suffix, /^ ٪/ );
});

});


<|start_filename|>test/unit/date/tokenizer-properties.js<|end_filename|>
define([
	"cldr",
	"src/date/tokenizer-properties",
	"json!cldr-data/main/en/ca-gregorian.json",
	"json!cldr-data/main/en/timeZoneNames.json",
	"json!cldr-data/main/en-GB/ca-gregorian.json",
	"json!cldr-data/main/en-GB/timeZoneNames.json",
	"json!cldr-data/supplemental/likelySubtags.json",
	"json!cldr-data/supplemental/metaZones.json",

	"cldr/event",
	"cldr/supplemental"
], function( Cldr, tokenizerProperties, enCaGregorian, enTimeZoneNames, enGbCaGregorian,
	enGbTimeZoneNames, likelySubtags, metaZones ) {

var cldr;

Cldr.load(
	enCaGregorian,
	enTimeZoneNames,
	enGbCaGregorian,
	enGbTimeZoneNames,
	likelySubtags,
	metaZones
);

Cldr.load({
	"main": {
		"en": {
			"dates": {
				"timeZoneNames": {
					"zone": {
						"Foo": {
							"Baz": {
								"exemplarCity": "Foo City"
							}
						}
					}
				}
			}
		}
	}
});

cldr = new Cldr( "en" );

QUnit.module( "Date Tokenizer Properties" );

/**
 *  Era
 */

QUnit.test( "should return properties for era (G..GGGGG)", function( assert ) {
	[ "G", "GG", "GGG" ].forEach(function( pattern ) {
		assert.ok( "gregorian/eras/eraAbbr" in tokenizerProperties( pattern, cldr ) );
	});
	assert.ok( "gregorian/eras/eraNames" in tokenizerProperties( "GGGG", cldr ) );
	assert.ok( "gregorian/eras/eraNarrow" in tokenizerProperties( "GGGGG", cldr ) );
});

/**
 *  Quarter
 */

QUnit.test( "should return properties for quarter (QQQ..QQQQQ)", function( assert ) {
	assert.ok( "gregorian/quarters/format/abbreviated" in tokenizerProperties( "QQQ", cldr ) );
	assert.ok( "gregorian/quarters/format/wide" in tokenizerProperties( "QQQQ", cldr ) );
	assert.ok( "gregorian/quarters/format/narrow" in tokenizerProperties( "QQQQQ", cldr ) );
});

QUnit.test( "should return properties for quarter (qqq..qqqqq)", function( assert ) {
	assert.ok( "gregorian/quarters/stand-alone/abbreviated" in tokenizerProperties( "qqq", cldr ) );
	assert.ok( "gregorian/quarters/stand-alone/wide" in tokenizerProperties( "qqqq", cldr ) );
	assert.ok( "gregorian/quarters/stand-alone/narrow" in tokenizerProperties( "qqqqq", cldr ) );
});

/**
 *  Month
 */

QUnit.test( "should return properties for month (MMM..MMMMM)", function( assert ) {
	assert.ok( "gregorian/months/format/abbreviated" in tokenizerProperties( "MMM", cldr ) );
	assert.ok( "gregorian/months/format/wide" in tokenizerProperties( "MMMM", cldr ) );
	assert.ok( "gregorian/months/format/narrow" in tokenizerProperties( "MMMMM", cldr ) );
});

QUnit.test( "should return properties for month (LL..LLLLL)", function( assert ) {
	assert.ok( "gregorian/months/stand-alone/abbreviated" in tokenizerProperties( "LLL", cldr ) );
	assert.ok( "gregorian/months/stand-alone/wide" in tokenizerProperties( "LLLL", cldr ) );
	assert.ok( "gregorian/months/stand-alone/narrow" in tokenizerProperties( "LLLLL", cldr ) );
});

/**
 *  Week day
 */

QUnit.test( "should return properties for day of week (eee..eeeeee)", function( assert ) {
	assert.ok( "gregorian/days/format/abbreviated" in tokenizerProperties( "eee", cldr ) );
	assert.ok( "gregorian/days/format/wide" in tokenizerProperties( "eeee", cldr ) );
	assert.ok( "gregorian/days/format/narrow" in tokenizerProperties( "eeeee", cldr ) );
	assert.ok( "gregorian/days/format/short" in tokenizerProperties( "eeeeee", cldr ) );
});

QUnit.test( "should return properties for day of week (ccc..cccccc)", function( assert ) {
	assert.ok( "gregorian/days/stand-alone/abbreviated" in tokenizerProperties( "ccc", cldr ) );
	assert.ok( "gregorian/days/stand-alone/wide" in tokenizerProperties( "cccc", cldr ) );
	assert.ok( "gregorian/days/stand-alone/narrow" in tokenizerProperties( "ccccc", cldr ) );
	assert.ok( "gregorian/days/stand-alone/short" in tokenizerProperties( "cccccc", cldr ) );
});

QUnit.test( "should return properties for day of week (E..EEEEEE)", function( assert ) {
	[ "E", "EE", "EEE" ].forEach(function( pattern ) {
		assert.ok( "gregorian/days/format/abbreviated" in tokenizerProperties( pattern, cldr ) );
	});
	assert.ok( "gregorian/days/format/wide" in tokenizerProperties( "EEEE", cldr ) );
	assert.ok( "gregorian/days/format/narrow" in tokenizerProperties( "EEEEE", cldr ) );
	assert.ok( "gregorian/days/format/short" in tokenizerProperties( "EEEEEE", cldr ) );
});

/**
 *  Period
 */

QUnit.test( "should return properties for period (a)", function( assert ) {
	assert.ok( "gregorian/dayPeriods/format/wide" in tokenizerProperties( "a", cldr ) );
});

/**
 *  Zone
 */

var properties;
QUnit.test( "should return properties for timezone (z)", function( assert ) {
	var enGb = new Cldr( "en-GB" );

	properties = tokenizerProperties( "z", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);
	properties = tokenizerProperties( "zzzz", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);

	properties = tokenizerProperties( "z", cldr, "America/Los_Angeles" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"standardOrDaylightTzName",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);
	properties = tokenizerProperties( "zzzz", cldr, "America/Los_Angeles" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"standardOrDaylightTzName",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);

	properties = tokenizerProperties( "z", enGb, "Europe/London" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"standardOrDaylightTzName",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);
	properties = tokenizerProperties( "zzzz", cldr, "Europe/London" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"standardOrDaylightTzName",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);

	properties = tokenizerProperties( "zzzz", cldr, "Asia/Dubai" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"standardOrDaylightTzName",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);
});

QUnit.test( "should return properties for timezone (Z)", function( assert ) {
	properties = tokenizerProperties( "Z", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);

	properties = tokenizerProperties( "ZZZZ", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);

	properties = tokenizerProperties( "ZZZZZ", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"x"
	]);
});

QUnit.test( "should return properties for timezone (O)", function( assert ) {
	properties = tokenizerProperties( "O", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);

	properties = tokenizerProperties( "OOOO", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);
});

QUnit.test( "should return properties for timezone (v)", function( assert ) {
	properties = tokenizerProperties( "v", cldr, "America/Los_Angeles" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"genericTzName",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);
	properties = tokenizerProperties( "vvvv", cldr, "America/Los_Angeles" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"genericTzName",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);

	// Use metazone.
	properties = tokenizerProperties( "vvvv", cldr, "America/Sao_Paulo" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"genericTzName",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);

	// Fall through 'VVVV' format.
	properties = tokenizerProperties( "v", cldr, "America/Sao_Paulo" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneName",
		"timeZoneNameRe",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);

	properties = tokenizerProperties( "v", cldr, "Foo/Baz" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneName",
		"timeZoneNameRe",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);
	properties = tokenizerProperties( "vvvv", cldr, "Foo/Baz" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneName",
		"timeZoneNameRe",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);

	// Fall through 'O' and 'OOOO' formats.
	properties = tokenizerProperties( "v", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);
	properties = tokenizerProperties( "vvvv", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);
});

QUnit.test( "should return properties for timezone (V)", function( assert ) {
	// FIXME assert.equal( JSON.stringify( properties ), "" );
	properties = tokenizerProperties( "VV", cldr, "America/Los_Angeles" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneName",
		"timeZoneNameRe"
	]);

	properties = tokenizerProperties( "VVV", cldr, "America/Los_Angeles" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneName",
		"timeZoneNameRe",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);

	properties = tokenizerProperties( "VVVV", cldr, "America/Los_Angeles" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneName",
		"timeZoneNameRe",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);

	// Fall through to 'VVV' format with "Unknown" exemplarCity.
	properties = tokenizerProperties( "VVV", cldr, "Foo/Bar" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneName",
		"timeZoneNameRe",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);

	// Fall through 'OOOO' format.
	properties = tokenizerProperties( "VVVV", cldr, "America/Los_Angeles" );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"timeZoneName",
		"timeZoneNameRe",
		"timeZoneNames/gmtZeroFormat",
		"timeZoneNames/hourFormat",
		"timeZoneNames/gmtZeroFormatRe",
		"x"
	]);
});

QUnit.test( "should return properties for timezone (X)", function( assert ) {
	properties = tokenizerProperties( "X", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"x"
	]);

	properties = tokenizerProperties( "XX", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"x"
	]);

	properties = tokenizerProperties( "XXX", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"x"
	]);

	properties = tokenizerProperties( "XXXX", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"x"
	]);

	properties = tokenizerProperties( "XXXXX", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"x"
	]);
});

QUnit.test( "should return properties for timezone (x)", function( assert ) {
	properties = tokenizerProperties( "x", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"x"
	]);

	properties = tokenizerProperties( "xx", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"x"
	]);

	properties = tokenizerProperties( "xxx", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"x"
	]);

	properties = tokenizerProperties( "xxxx", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"x"
	]);

	properties = tokenizerProperties( "xxxxx", cldr );
	assert.deepEqual( Object.keys( properties ), [
		"pattern",
		"digitsRe",
		"x"
	]);
});

});


<|start_filename|>src/number/format.js<|end_filename|>
define([
	"./compact-pattern-re",
	"./format/grouping-separator",
	"./format/integer-fraction-digits",
	"./format/significant-digits",
	"./symbol/name",
	"../common/parts/push",
	"../util/remove-literal-quotes"
], function( numberCompactPatternRe, numberFormatGroupingSeparator,
	numberFormatIntegerFractionDigits, numberFormatSignificantDigits,
	numberSymbolName, partsPush, removeLiteralQuotes ) {

/**
 * format( number, properties )
 *
 * @number [Number].
 *
 * @properties [Object] Output of number/format-properties.
 *
 * Return the formatted number.
 * ref: http://www.unicode.org/reports/tr35/tr35-numbers.html
 */
return function( number, properties, pluralGenerator ) {
	var aux, compactMap, infinitySymbol, maximumFractionDigits, maximumSignificantDigits,
		minimumFractionDigits, minimumIntegerDigits, minimumSignificantDigits, nanSymbol,
		nuDigitsMap, prefix, primaryGroupingSize, pattern, round, roundIncrement,
		secondaryGroupingSize, stringToParts, suffix, symbolMap;

	minimumIntegerDigits = properties[ 2 ];
	minimumFractionDigits = properties[ 3 ];
	maximumFractionDigits = properties[ 4 ];
	minimumSignificantDigits = properties[ 5 ];
	maximumSignificantDigits = properties[ 6 ];
	roundIncrement = properties[ 7 ];
	primaryGroupingSize = properties[ 8 ];
	secondaryGroupingSize = properties[ 9 ];
	round = properties[ 15 ];
	infinitySymbol = properties[ 16 ];
	nanSymbol = properties[ 17 ];
	symbolMap = properties[ 18 ];
	nuDigitsMap = properties[ 19 ];
	compactMap = properties[ 20 ];

	// NaN
	if ( isNaN( number ) ) {
		return [ { type: "nan", value: nanSymbol } ];
	}

	if ( number < 0 ) {
		pattern = properties[ 12 ];
		prefix = properties[ 13 ];
		suffix = properties[ 14 ];
	} else {
		pattern = properties[ 11 ];
		prefix = properties[ 0 ];
		suffix = properties[ 10 ];
	}

	// For prefix, suffix, and number parts.
	stringToParts = function( string ) {
		var numberType = "integer",
			parts = [];

		// TODO Move the tokenization of all parts that don't depend on number into
		// format-properties.
		string.replace( /('([^']|'')+'|'')|./g, function( character, literal ) {

			// Literals
			if ( literal ) {
				partsPush( parts, "literal", removeLiteralQuotes( literal ) );
				return;
			}

			// Currency symbol
			if ( character === "\u00A4" ) {
				partsPush( parts, "currency", character );
				return;
			}

			// Symbols
			character = character.replace( /[.,\-+E%\u2030]/, function( symbol ) {
				if ( symbol === "." ) {
					numberType = "fraction";
				}
				partsPush( parts, numberSymbolName[ symbol ], symbolMap[ symbol ] );

				// "Erase" handled character.
				return "";
			});

			// Number
			character = character.replace( /[0-9]/, function( digit ) {

				// Numbering system
				if ( nuDigitsMap ) {
					digit = nuDigitsMap[ +digit ];
				}
				partsPush( parts, numberType, digit );

				// "Erase" handled character.
				return "";
			});

			// Etc
			character.replace( /./, function( etc ) {
				partsPush( parts, "literal", etc );
			});
		});
		return parts;
	};

	prefix = stringToParts( prefix );
	suffix = stringToParts( suffix );

	// Infinity
	if ( !isFinite( number ) ) {
		return prefix.concat(
			{ type: "infinity", value: infinitySymbol },
			suffix
		);
	}

	// Percent
	if ( pattern.indexOf( "%" ) !== -1 ) {
		number *= 100;

	// Per mille
	} else if ( pattern.indexOf( "\u2030" ) !== -1 ) {
		number *= 1000;
	}

	var compactPattern, compactDigits, compactProperties, divisor, numberExponent, pluralForm;

	// Compact mode: initial number digit processing
	if ( compactMap ) {
		numberExponent = Math.abs( Math.floor( number ) ).toString().length - 1;
		numberExponent = Math.min( numberExponent, compactMap.maxExponent );

		// Use default plural form to perform initial decimal shift
		if ( numberExponent >= 3 ) {
			compactPattern = compactMap[ numberExponent ] && compactMap[ numberExponent ].other;
		}

		if ( compactPattern === "0" ) {
			compactPattern = null;
		} else if ( compactPattern ) {
			compactDigits = compactPattern.split( "0" ).length - 1;
			divisor = numberExponent - ( compactDigits - 1 );
			number = number / Math.pow( 10, divisor );
		}
	}

	// Significant digit format
	if ( !isNaN( minimumSignificantDigits * maximumSignificantDigits ) ) {
		number = numberFormatSignificantDigits( number, minimumSignificantDigits,
			maximumSignificantDigits, round );

	// Integer and fractional format
	} else {
		number = numberFormatIntegerFractionDigits( number, minimumIntegerDigits,
			minimumFractionDigits, maximumFractionDigits, round, roundIncrement );
	}

	// Compact mode: apply formatting
	if ( compactMap && compactPattern ) {

		// Get plural form after possible roundings
		pluralForm = pluralGenerator ? pluralGenerator( +number ) : "other";

		compactPattern = compactMap[ numberExponent ][ pluralForm ] || compactPattern;
		compactProperties = compactPattern.match( numberCompactPatternRe );

		// TODO Move the tokenization of all parts that don't depend on number into
		// format-properties.
		aux = function( string ) {
			var parts = [];
			string.replace( /(\s+)|([^\s0]+)/g, function( _garbage, space, compact ) {

				// Literals
				if ( space ) {
					partsPush( parts, "literal", space );
					return;
				}

				// Compact value
				if ( compact ) {
					partsPush( parts, "compact", compact );
					return;
				}
			});
			return parts;
		};

		// update prefix/suffix with compact prefix/suffix
		prefix = prefix.concat( aux( compactProperties[ 1 ] ) );
		suffix = aux( compactProperties[ 3 ] ).concat( suffix );
	}

	// Remove the possible number minus sign
	number = number.replace( /^-/, "" );

	// Grouping separators
	if ( primaryGroupingSize ) {
		number = numberFormatGroupingSeparator( number, primaryGroupingSize,
			secondaryGroupingSize );
	}

	// Scientific notation
	// TODO implement here

	// Padding/'([^']|'')+'|''|[.,\-+E%\u2030]/g
	// TODO implement here

	return prefix.concat(
		stringToParts( number ),
		suffix
	);
};

});


<|start_filename|>src/currency/name-format.js<|end_filename|>
define([
	"../common/format-message-to-parts",
	"../common/parts/push"
], function( formatMessageToParts, partsPush ) {

/**
 * nameFormat( formattedNumber, pluralForm, properties )
 *
 * Return the appropriate name form currency format.
 */
return function( formattedNumber, pluralForm, properties ) {
	var displayName, unitPattern,
		parts = [],
		displayNames = properties.displayNames || {},
		unitPatterns = properties.unitPatterns;

	displayName = displayNames[ "displayName-count-" + pluralForm ] ||
		displayNames[ "displayName-count-other" ] ||
		displayNames.displayName ||
		properties.currency;
	unitPattern = unitPatterns[ "unitPattern-count-" + pluralForm ] ||
		unitPatterns[ "unitPattern-count-other" ];

	formatMessageToParts( unitPattern, [ formattedNumber, displayName ]).forEach(function( part ) {
		if ( part.type === "variable" && part.name === "0" ) {
			part.value.forEach(function( part ) {
				partsPush( parts, part.type, part.value );
			});
		} else if ( part.type === "variable" && part.name === "1" ) {
			partsPush( parts, "currency", part.value );
		} else {
			partsPush( parts, "literal", part.value );
		}
	});

	return parts;
};

});


<|start_filename|>test/unit/currency/name-format.js<|end_filename|>
define([
	"cldr",
	"src/currency/name-format",
	"src/currency/name-properties",
	"json!cldr-data/main/en/currencies.json",
	"json!cldr-data/main/en/numbers.json",
	"json!cldr-data/main/zh/currencies.json",
	"json!cldr-data/main/zh/numbers.json",
	"json!cldr-data/supplemental/currencyData.json",
	"json!cldr-data/supplemental/likelySubtags.json",

	"cldr/event",
	"cldr/supplemental"
], function( Cldr, format, properties, enCurrencies, enNumbers, zhCurrencies, zhNumbers,
	currencyData, likelySubtags ) {

var en, zh;

Cldr.load(
	currencyData,
	enCurrencies,
	enNumbers,
	likelySubtags,
	zhCurrencies,
	zhNumbers
);

en = new Cldr( "en" );
zh = new Cldr( "zh" );

QUnit.module( "Currency Name Format" );

QUnit.test( "should format currencies", function( assert ) {
	assert.deepEqual( format( [{ type: "integer", value: "1" }], "one", properties( "USD", en ) ), [
		{
			"type": "integer",
			"value": "1"
		},
		{
			"type": "literal",
			"value": " "
		},
		{
			"type": "currency",
			"value": "US dollar"
		}
	]);

	assert.deepEqual( format( [{ type: "integer", value: "2" }], "other", properties( "USD", en ) ), [
		{
			"type": "integer",
			"value": "2"
		},
		{
			"type": "literal",
			"value": " "
		},
		{
			"type": "currency",
			"value": "US dollars"
		}
	]);

	// Test the fallback to displayNames by the lack of displayNames-count-*.
	assert.deepEqual( format( [{ type: "integer", value: "1" }], "something", {
		"displayNames": {
			"displayName": "US Dollar",
		},
		"unitPatterns": {
			"unitPattern-count-other": "{0} {1}"
		}
	}), [
		{
			"type": "integer",
			"value": "1"
		},
		{
			"type": "literal",
			"value": " "
		},
		{
			"type": "currency",
			"value": "US Dollar"
		}
	]);

	// Test the fallback to currency by the lack of displayName and displayName-count-*.
	assert.deepEqual( format( [{ type: "integer", value: "1" }], "something", {
		"currency": "USD",
		"unitPatterns": {
			"unitPattern-count-other": "{0} {1}"
		}
	}), [
		{
			"type": "integer",
			"value": "1"
		},
		{
			"type": "literal",
			"value": " "
		},
		{
			"type": "currency",
			"value": "USD"
		}
	]);

	assert.deepEqual( format( [{ type: "integer", value: "10" }], "other", properties( "CNY", zh ) ), [
		{
			"type": "integer",
			"value": "10"
		},
		{
			"type": "currency",
			"value": "人民币"
		}
	]);

	// Testing inverted unitPattern {1} {0}.
	assert.deepEqual( format( [{ type: "integer", value: "1" }], "other", {
		"currency": "TZS",
		"unitPatterns": {
			"unitPattern-count-other": "{1} {0}"
		}
	}), [
		{
			"type": "currency",
			"value": "TZS"
		},
		{
			"type": "literal",
			"value": " "
		},
		{
			"type": "integer",
			"value": "1"
		}
	]);

});

});


<|start_filename|>test/functional/core.js<|end_filename|>
define([
	"globalize",
	"../util"
], function( Globalize, util ) {

QUnit.module( "Globalize class constructor" );

QUnit.test( "should validate parameters", function( assert ) {
	util.assertParameterPresence( assert, "locale", function() {
		new Globalize();
	});

	util.assertParameterPresence( assert, "locale", function() {
		Globalize();
	});

	util.assertLocaleParameter( assert, "locale", function( invalidValue ) {
		return function() {
			new Globalize( invalidValue );
		};
	});

	util.assertLocaleParameter( assert, "locale", function( invalidValue ) {
		return function() {
			Globalize( invalidValue );
		};
	});
});

});


<|start_filename|>test/functional/currency/currency-formatter.js<|end_filename|>
define([
	"globalize",
	"json!cldr-data/main/de/currencies.json",
	"json!cldr-data/main/de/numbers.json",
	"json!cldr-data/main/en/currencies.json",
	"json!cldr-data/main/en/numbers.json",
	"json!cldr-data/main/zh/currencies.json",
	"json!cldr-data/main/zh/numbers.json",
	"json!cldr-data/supplemental/currencyData.json",
	"json!cldr-data/supplemental/likelySubtags.json",
	"json!cldr-data/supplemental/plurals.json",
	"../../util",

	"globalize/currency",
	"globalize/number",
	"globalize/plural"
], function( Globalize, deCurrencies, deNumbers, enCurrencies, enNumbers, zhCurrencies,
	zhNumbers, currencyData, likelySubtags, plurals, util ) {

var accounting = { style: "accounting" },
	code = { style: "code" },
	name = { style: "name" },
	narrow = { symbolForm: "narrow" },
	teslaS = 69900;

function extraSetup() {
	Globalize.load(
		currencyData,
		deCurrencies,
		deNumbers,
		enCurrencies,
		enNumbers,
		plurals,
		zhCurrencies,
		zhNumbers
	);

}

QUnit.module( ".currencyFormatter( currency [, options] )", {
	beforeEach: function() {
		Globalize.load( likelySubtags, {
			main: {
				en: {}
			}
		});
		Globalize.locale( "en" );
	},
	afterEach: util.resetCldrContent
});

QUnit.test( "should validate parameters", function( assert ) {
	util.assertParameterPresence( assert, "currency", function() {
		Globalize.currencyFormatter();
	});

	util.assertCurrencyParameter( assert, "currency", function( invalidValue ) {
		return function() {
			Globalize.currencyFormatter( invalidValue );
		};
	});

	util.assertPlainObjectParameter( assert, "options", function( invalidValue ) {
		return function() {
			Globalize.currencyFormatter( "USD", invalidValue );
		};
	});
});

QUnit.test( "should validate CLDR content", function( assert ) {
	util.assertCldrContent( assert, function() {
		Globalize.currencyFormatter( "USD" );
	});
});

QUnit.test( "should un-register event listener", function( assert ) {
	try {
		Globalize.currencyFormatter( "USD" );
	} catch ( error ) {
		assert.equal( Globalize.cldr.ee.getListeners( "get" ).length, 0 );
	}
});

QUnit.test( "should return a currency formatter", function( assert ) {
	var de, zh;

	extraSetup();

	de = Globalize( "de" );
	zh = Globalize( "zh" );

	assert.equal( Globalize.currencyFormatter( "USD" )( teslaS ), "$69,900.00" );
	assert.equal( de.currencyFormatter( "USD" )( teslaS ), "69.900,00 $" );
	assert.equal( zh.currencyFormatter( "USD" )( teslaS ), "US$69,900.00" );

	assert.equal( Globalize.currencyFormatter( "USD" )( -teslaS ), "-$69,900.00" );
	assert.equal( de.currencyFormatter( "USD" )( -teslaS ), "-69.900,00 $" );
	assert.equal( zh.currencyFormatter( "USD" )( -teslaS ), "-US$69,900.00" );

	assert.equal( Globalize.currencyFormatter( "HKD", narrow )( teslaS ), "$69,900.00" );

	assert.equal( Globalize.currencyFormatter( "USD", code )( teslaS ), "USD 69,900.00" );
	assert.equal( de.currencyFormatter( "USD", code )( teslaS ), "69.900,00 USD" );
	assert.equal( zh.currencyFormatter( "USD", code )( teslaS ), "USD 69,900.00" );

	assert.equal( Globalize.currencyFormatter( "USD", name )( teslaS ), "69,900.00 US dollars" );
	assert.equal( de.currencyFormatter( "USD", name )( teslaS ), "69.900,00 US-Dollar" );
	assert.equal( zh.currencyFormatter( "USD", name )( teslaS ), "69,900.00美元" );

	assert.equal( Globalize.currencyFormatter( "USD", accounting )( -1 ), "($1.00)" );
});

// The number of decimal places and the rounding for each currency is not locale-specific data.
// Those values are overriden by Supplemental Currency Data.
QUnit.test( "should return a currency formatter, overriden by Supplemental Currency Data",
			function( assert ) {
	extraSetup();

	assert.equal( Globalize.currencyFormatter( "CLF" )( 12345 ), "CLF 12,345.0000" );
	assert.equal( Globalize.currencyFormatter( "CLF" )( 12345.67 ), "CLF 12,345.6700" );
	assert.equal( Globalize.currencyFormatter( "ZWD" )( 12345 ), "ZWD 12,345" );
	assert.equal( Globalize.currencyFormatter( "ZWD" )( 12345.67 ), "ZWD 12,346" );
	assert.equal( Globalize.currencyFormatter( "JPY" )( 12345.67 ), "¥12,346" );

	assert.equal( Globalize.currencyFormatter( "CLF", code )( 12345.67 ),
		"CLF 12,345.6700" );

	assert.equal( Globalize.currencyFormatter( "CLF", name )( 12345.67 ),
		"12,345.6700 Chilean units of account (UF)" );
});

// User options should override everything.
QUnit.test( "should return a currency formatter, overriden by user options",
			function( assert ) {
	extraSetup();

	assert.equal( Globalize.currencyFormatter( "CLF", {
		minimumFractionDigits: 0
	})( 12345 ), "CLF 12,345" );

	assert.equal( Globalize.currencyFormatter( "JPY", {
		maximumFractionDigits: 0
	})( 12345 ), "¥12,345" );

	assert.equal( Globalize.currencyFormatter( "JPY", {
		minimumFractionDigits: 2
	})( 12345 ), "¥12,345.00" );

	assert.equal( Globalize.currencyFormatter( "CLF", {
		style: "code",
		minimumFractionDigits: 0
	})( 12345 ), "CLF 12,345" );

	assert.equal( Globalize.currencyFormatter( "CLF", {
		style: "name",
		minimumFractionDigits: 0
	})( 12345 ), "12,345 Chilean units of account (UF)" );
});

});


<|start_filename|>src/util/regexp/dash-g.js<|end_filename|>
define(function() {

/**
 * Generated by:
 *
 * var regenerate = require( "regenerate" );
 * var dashSymbols = require( "https://github.com/node-unicode/unicode-13.0.0/General_Category/Dash_Punctuation/symbols" );
 * regenerate().add( dashSymbols ).toString();
 *
 * https://github.com/mathiasbynens/regenerate
 * https://github.com/node-unicode/unicode-13.0.0
 *
 * NOTE: In addition to [:dash:],  the below includes MINUS SIGN U+2212.
 */
return /[\x2D\u058A\u05BE\u1400\u1806\u2010-\u2015\u2E17\u2E1A\u2E3A\u2E3B\u2E40\u301C\u3030\u30A0\uFE31\uFE32\uFE58\uFE63\uFF0D\u2212]|\uD803\uDEAD/g;

});


<|start_filename|>test/unit/common/runtime-bind.js<|end_filename|>
define([
	"src/common/runtime-bind",
], function( runtimeBind ) {

QUnit.module( "Common (runtimeBind)" );

QUnit.test( "runtimeBind should work with anonymous function", function( assert ) {
	var fn = function() {
		return "passed";
	};
	assert.equal( runtimeBind({}, {}, fn, {})(), "passed" );
});

});


<|start_filename|>src/relative-time.js<|end_filename|>
define([
	"./core",
	"./common/runtime-bind",
	"./common/validate/cldr",
	"./common/validate/default-locale",
	"./common/validate/parameter-presence",
	"./common/validate/parameter-type/number",
	"./common/validate/parameter-type/string",
	"./relative-time/formatter-fn",
	"./relative-time/properties",

	"./number",
	"./plural",
	"cldr/event"
], function( Globalize, runtimeBind, validateCldr, validateDefaultLocale, validateParameterPresence,
	validateParameterTypeNumber, validateParameterTypeString, relativeTimeFormatterFn,
	relativeTimeProperties ) {

/**
 * .formatRelativeTime( value, unit [, options] )
 *
 * @value [Number] The number of unit to format.
 *
 * @unit [String] see .relativeTimeFormatter() for details.
 *
 * @options [Object] see .relativeTimeFormatter() for details.
 *
 * Formats a relative time according to the given unit, options, and the default/instance locale.
 */
Globalize.formatRelativeTime =
Globalize.prototype.formatRelativeTime = function( value, unit, options ) {
	validateParameterPresence( value, "value" );
	validateParameterTypeNumber( value, "value" );

	return this.relativeTimeFormatter( unit, options )( value );
};

/**
 * .relativeTimeFormatter( unit [, options ])
 *
 * @unit [String] String value indicating the unit to be formatted. eg. "day", "week", "month", etc.
 *
 * @options [Object]
 * - form: [String] eg. "short" or "narrow". Or falsy for default long form.
 *
 * Returns a function that formats a relative time according to the given unit, options, and the
 * default/instance locale.
 */
Globalize.relativeTimeFormatter =
Globalize.prototype.relativeTimeFormatter = function( unit, options ) {
	var args, cldr, numberFormatter, pluralGenerator, properties, returnFn;

	validateParameterPresence( unit, "unit" );
	validateParameterTypeString( unit, "unit" );

	cldr = this.cldr;
	options = options || {};

	args = [ unit, options ];

	validateDefaultLocale( cldr );

	cldr.on( "get", validateCldr );
	try {
		properties = relativeTimeProperties( unit, cldr, options );
	} finally {
		cldr.off( "get", validateCldr );
	}
	numberFormatter = this.numberFormatter( options );
	pluralGenerator = this.pluralGenerator();

	returnFn = relativeTimeFormatterFn( numberFormatter, pluralGenerator, properties );

	runtimeBind( args, cldr, returnFn, [ numberFormatter, pluralGenerator, properties ] );

	return returnFn;
};

return Globalize;

});


<|start_filename|>src/number/parse-properties.js<|end_filename|>
define([
	"./format-properties",
	"./symbol/inverted-map",
	"../util/loose-matching",
	"../util/object/map",
	"../util/regexp/escape",
	"../util/remove-literal-quotes"
], function( numberFormatProperties, numberSymbolInvertedMap, looseMatching, objectMap,
	regexpEscape, removeLiteralQuotes ) {

/**
 * parseProperties( pattern, cldr )
 *
 * @pattern [String] raw pattern for numbers.
 *
 * @cldr [Cldr instance].
 *
 * Return parser properties, used to feed parser function.
 *
 * TODO:
 * - Scientific_notation;
 * - Padding;
 */
return function( pattern, cldr, options ) {
	var aux, decimalSymbolRe, digitsRe, groupingSeparatorRe, infinitySymbol, invertedNuDigitsMap,
		invertedSymbolMap, maximumFractionDigits, maximumSignificantDigits,
		minimumSignificantDigits, nanSymbol, negativePrefix, negativeSuffix, nuDigitsMap,
		numberTokenizer, prefix, primaryGroupingSize, secondaryGroupingSize, suffix, symbolMap,
		formatProperties = numberFormatProperties( pattern, cldr, options );

	prefix = looseMatching( formatProperties[ 0 ] );
	maximumFractionDigits = formatProperties[ 4 ];
	minimumSignificantDigits = formatProperties[ 5 ];
	maximumSignificantDigits = formatProperties[ 6 ];
	primaryGroupingSize = formatProperties[ 8 ];
	secondaryGroupingSize = formatProperties[ 9 ];
	suffix = looseMatching( formatProperties[ 10 ] );
	negativePrefix = looseMatching( formatProperties[ 13 ] );
	negativeSuffix = looseMatching( formatProperties[ 14 ] );
	infinitySymbol = looseMatching( formatProperties[ 16 ] );
	nanSymbol = looseMatching( formatProperties[ 17 ] );
	symbolMap = objectMap( formatProperties[ 18 ], function( pair ) {
		return [ pair[ 0 ], looseMatching( pair[ 1 ] ) ];
	});
	nuDigitsMap = formatProperties[ 19 ];

	invertedSymbolMap = objectMap( numberSymbolInvertedMap( cldr ), function( pair ) {
		return [ looseMatching( pair[ 0 ] ), pair[ 1 ] ];
	});

	digitsRe = nuDigitsMap ? "[" + nuDigitsMap + "]" : "\\d";
	groupingSeparatorRe = regexpEscape( symbolMap[ "," ] );
	decimalSymbolRe = regexpEscape( symbolMap[ "." ] );

	if ( nuDigitsMap ) {
		invertedNuDigitsMap = nuDigitsMap.split( "" ).reduce(function( object, localizedDigit, i ) {
			object[ localizedDigit ] = String( i );
			return object;
		}, {} );
	}

	aux = [ prefix, suffix, negativePrefix, negativeSuffix ].map(function( value ) {
		return value.replace( /('([^']|'')+'|'')|./g, function( character, literal ) {

			// Literals
			if ( literal ) {
				return removeLiteralQuotes( literal );
			}

			// Symbols
			character = character.replace( /[\-+E%\u2030]/, function( symbol ) {
				return symbolMap[ symbol ];
			});

			return character;
		});
	});

	prefix = aux[ 0 ];
	suffix = aux[ 1 ];
	negativePrefix = aux[ 2 ];
	negativeSuffix = aux[ 3 ];

	// Number
	//
	// number_re =                       integer fraction?
	//
	// integer =                         digits | digits_using_grouping_separators
	//
	// fraction =                        regexp((.\d+)?)
	//
	// digits =                          regexp(\d+)
	//
	// digits_w_grouping_separators =    digits_w_1_grouping_separators |
	//                                   digits_w_2_grouping_separators
	//
	// digits_w_1_grouping_separators =  regexp(\d{1,3}(,\d{3})+)
	//
	// digits_w_2_grouping_separators =  regexp(\d{1,2}((,\d{2})*(,\d{3})))

	// Integer part
	numberTokenizer = digitsRe + "+";

	// Grouping separators
	if ( primaryGroupingSize ) {
		if ( secondaryGroupingSize ) {
			aux = digitsRe + "{1," + secondaryGroupingSize + "}((" + groupingSeparatorRe +
				digitsRe + "{" + secondaryGroupingSize + "})*(" + groupingSeparatorRe +
				digitsRe + "{" + primaryGroupingSize + "}))";
		} else {
			aux = digitsRe + "{1," + primaryGroupingSize + "}(" + groupingSeparatorRe +
				digitsRe + "{" + primaryGroupingSize + "})+";
		}
		numberTokenizer = "(" + aux + "|" + numberTokenizer + ")";
	}

	// Fraction part? Only included if 1 or 2.
	// 1: Using significant digit format.
	// 2: Using integer and fractional format && it has a maximumFractionDigits.
	if ( !isNaN( minimumSignificantDigits * maximumSignificantDigits ) || /* 1 */
				maximumFractionDigits /* 2 */ ) {

		// 1: Handle trailing decimal separator, e.g., `"1." => `1``.
		aux = decimalSymbolRe + digitsRe + "+";
		numberTokenizer = numberTokenizer + "(" + aux + "|" + decimalSymbolRe /* 1 */ + ")?" +

			// Handle non-padded decimals, e.g., `".12"` => `0.12` by making the integer part
			// optional.
			"|(" + numberTokenizer + ")?" + aux;

		numberTokenizer = "(" + numberTokenizer + ")";
	}

	// 0: @invertedSymbolMap [Object] Inverted symbol map.
	// 1: @invertedNuDigitsMap [Object] Inverted digits map if numbering system is different than
	//    `latn`.
	// 2: @tokenizer [Object] Tokenizer map, used by parser to consume input.
	return [
		invertedSymbolMap,
		invertedNuDigitsMap,
		{
			infinity: new RegExp( "^" + regexpEscape( infinitySymbol ) ),
			nan: new RegExp( "^" + regexpEscape( nanSymbol ) ),
			negativePrefix: new RegExp( "^" + regexpEscape( negativePrefix ) ),
			negativeSuffix: new RegExp( "^" + regexpEscape( negativeSuffix ) ),
			number: new RegExp( "^" + numberTokenizer ),
			prefix: new RegExp( "^" + regexpEscape( prefix ) ),
			suffix: new RegExp( "^" + regexpEscape( suffix ) )
		}
	];

};

});


<|start_filename|>test/unit/number/pattern-properties.js<|end_filename|>
define([
	"cldr",
	"src/number/format-properties",
	"json!cldr-data/main/en/numbers.json",
	"json!cldr-data/supplemental/likelySubtags.json",

	"cldr/event",
	"cldr/supplemental"
], function( Cldr, properties, enNumbers, likelySubtags ) {

var en;

Cldr.load( enNumbers, likelySubtags );

en = new Cldr( "en" );

QUnit.module( "Number Pattern Properties" );

QUnit.test( "should return prefix", function( assert ) {
	assert.equal( properties( "0", en )[ 0 ], "" );
	assert.equal( properties( "foo 0", en )[ 0 ], "foo " );
	assert.equal( properties( "-0", en )[ 0 ], "-" );
	assert.equal( properties( "'-'0", en )[ 0 ], "'-'" );
	assert.equal( properties( "-'$'0", en )[ 0 ], "-'$'" );
});

QUnit.test( "should return minimumIntegerDigits", function( assert ) {
	assert.equal( properties( "0", en )[ 2 ], 1 );
	assert.equal( properties( "#,##0", en )[ 2 ], 1 );
	assert.equal( properties( "00", en )[ 2 ], 2 );
	assert.equal( properties( "#0.00", en )[ 2 ], 1 );
});

QUnit.test( "should return minimumFractionDigits", function( assert ) {
	assert.equal( properties( "0", en )[ 3 ], 0 );
	assert.equal( properties( "0.##", en )[ 3 ], 0 );
	assert.equal( properties( "0.0#", en )[ 3 ], 1 );
});

QUnit.test( "should return maximumFractionDigits", function( assert ) {
	assert.equal( properties( "0", en )[ 4 ], 0 );
	assert.equal( properties( "0.##", en )[ 4 ], 2 );
	assert.equal( properties( "0.0#", en )[ 4 ], 2 );
});

QUnit.test( "should return minimumSignificantDigits", function( assert ) {
	assert.equal( properties( "0", en )[ 5 ], undefined );
	assert.equal( properties( "0.##", en )[ 5 ], undefined );
	assert.equal( properties( "@##", en )[ 5 ], 1 );
	assert.equal( properties( "#,#@@", en )[ 5 ], 2 );
});

QUnit.test( "should return maximumSignificantDigits", function( assert ) {
	assert.equal( properties( "0", en )[ 6 ], undefined );
	assert.equal( properties( "0.##", en )[ 6 ], undefined );
	assert.equal( properties( "@##", en )[ 6 ], 3 );
	assert.equal( properties( "#,#@@", en )[ 6 ], 2 );
});

QUnit.test( "should return roundIncrement", function( assert ) {
	assert.equal( properties( "0.##", en )[ 7 ], undefined );
	assert.equal( properties( "0.05", en )[ 7 ], 0.05 );
	assert.equal( properties( "0.002", en )[ 7 ], 0.002 );
});

QUnit.test( "should return primaryGroupingSize", function( assert ) {
	assert.equal( properties( "0.##", en )[ 8 ], undefined );
	assert.equal( properties( "#,##0.##", en )[ 8 ], 3 );
	assert.equal( properties( "#,##,##0.##", en )[ 8 ], 3 );
});

QUnit.test( "should return secondaryGroupingSize", function( assert ) {
	assert.equal( properties( "0.##", en )[ 9 ], undefined );
	assert.equal( properties( "#,##0.##", en )[ 9 ], undefined );
	assert.equal( properties( "#,##,##0.##", en )[ 9 ], 2 );
});

QUnit.test( "should return suffix", function( assert ) {
	assert.equal( properties( "0.##", en )[ 10 ], "" );
	assert.equal( properties( "0.## bar", en )[ 10 ], " bar" );
});

});


<|start_filename|>src/number/to-parts-formatter-fn.js<|end_filename|>
define([
	"../common/validate/parameter-presence",
	"../common/validate/parameter-type/number",
	"./format"
], function( validateParameterPresence, validateParameterTypeNumber, numberFormat ) {

return function( properties, pluralGenerator ) {
	return function numberToPartsFormatter( value ) {
		validateParameterPresence( value, "value" );
		validateParameterTypeNumber( value, "value" );

		return numberFormat( value, properties, pluralGenerator );
	};
};

});


<|start_filename|>test/unit/date/parse-properties.js<|end_filename|>
define([
	"cldr",
	"src/date/parse-properties",
	"json!cldr-data/main/en/ca-gregorian.json",
	"json!cldr-data/supplemental/likelySubtags.json",
	"json!cldr-data/supplemental/timeData.json",
	"json!iana-tz-data.json",

	"cldr/event",
	"cldr/supplemental"
], function( Cldr, parseProperties, enCaGregorian, likelySubtags, timeData, ianaTimezoneData ) {

var cldr;

Cldr.load(
	enCaGregorian,
	likelySubtags,
	timeData
);

// Needed for globalizeDate.
Cldr.load({
	"globalize-iana": ianaTimezoneData
});

cldr = new Cldr( "en" );

QUnit.module( "Date Parse Properties" );

QUnit.test( "should return parse properties", function( assert ) {
	var properties;

	assert.ok( "preferredTimeData" in parseProperties( cldr ) );

	properties = parseProperties( cldr, "America/Los_Angeles" );
	assert.ok( "preferredTimeData" in properties );
	assert.ok( "timeZoneData" in properties );
	assert.ok( "offsets" in properties.timeZoneData() );
	assert.ok( "untils" in properties.timeZoneData() );
	assert.ok( "isdsts" in properties.timeZoneData() );
});

});


<|start_filename|>test/functional/date/date-formatter.js<|end_filename|>
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( ".dateFormatter( pattern )", {
	beforeEach: function() {
		Globalize.load( likelySubtags, {
			main: {
				en: {}
			}
		});
		Globalize.locale( "en" );
	},
	afterEach: util.resetCldrContent
});

QUnit.test( "should validate parameters", function( assert ) {
	util.assertPlainObjectParameter( assert, "options", function( invalidPattern ) {
		return function() {
			Globalize.dateFormatter( invalidPattern );
		};
	});

	assert.throws(function() {
		Globalize.dateFormatter({ date: "invalid-stuff" });
	}, /E_INVALID_OPTIONS.*date.*invalid-stuff/ );

	assert.throws(function() {
		Globalize.dateFormatter({ time: "invalid-stuff" });
	}, /E_INVALID_OPTIONS.*time.*invalid-stuff/ );

	assert.throws(function() {
		Globalize.dateFormatter({ datetime: "invalid-stuff" });
	}, /E_INVALID_OPTIONS.*datetime.*invalid-stuff/ );

	assert.throws(function() {
		Globalize.dateFormatter({ skeleton: "invalid-stuff" });
	}, /E_INVALID_OPTIONS.*skeleton.*invalid-stuff/ );
});

QUnit.test( "should validate CLDR content", function( assert ) {
	Globalize.load({
		"main": {
			"en": {
				"dates": {
					"calendars": {
						"gregorian": {
							"dateTimeFormats": {
								"availableFormats": {
									"MMMd": "MMM d"
								}
							}
						}
					}
				}
			}
		}
	});
	util.assertCldrContent( assert, function() {
		Globalize.dateFormatter({ skeleton: "MMMd" });
	});
});

QUnit.test( "should return a formatter", function( assert ) {
	extraSetup();

	assert.equal( Globalize.dateFormatter({ skeleton: "GyMMMEd" })( date ), "Wed, Sep 15, 2010 AD" );
	assert.equal( Globalize.dateFormatter({ skeleton: "dhms" })( date ), "15, 5:35:07 PM" );
	assert.equal( Globalize.dateFormatter({ skeleton: "GyMMMEdhms" })( date ), "Wed, Sep 15, 2010 AD, 5:35:07 PM" );
	assert.equal( Globalize.dateFormatter({ skeleton: "GyMMMEdhmsSSS" })( date ), "Wed, Sep 15, 2010 AD, 5:35:07.369 PM" );
	assert.equal( Globalize.dateFormatter({ skeleton: "Ems" })( date ), "Wed, 35:07" );
	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" );
});

});


<|start_filename|>src/currency/to-parts-formatter-fn.js<|end_filename|>
define([
	"../common/validate/parameter-presence",
	"../common/validate/parameter-type/number",
	"./name-format",
	"./symbol-format"
], function( validateParameterPresence, validateParameterTypeNumber, currencyNameFormat,
	currencySymbolFormat ) {

return function( numberToPartsFormatter, pluralGenerator, properties ) {
	var fn;

	// Return formatter when style is "name".
	if ( pluralGenerator && properties ) {
		fn = function currencyToPartsFormatter( value ) {
			validateParameterPresence( value, "value" );
			validateParameterTypeNumber( value, "value" );
			return currencyNameFormat(
				numberToPartsFormatter( value ),
				pluralGenerator( value ),
				properties
			);
		};

	// Return formatter when style is "symbol", "accounting", or "code".
	} else {
		fn = function currencyToPartsFormatter( value ) {

			// 1: Reusing pluralGenerator argument, but in this case it is actually `symbol`
			return currencySymbolFormat( numberToPartsFormatter( value ), pluralGenerator /* 1 */ );
		};
	}

	return fn;
};

});


<|start_filename|>test/unit/util/regexp/escape.js<|end_filename|>
define([
	"src/util/regexp/escape",
], function( regexpEscape ) {

QUnit.module( "Util regexp escape" );

QUnit.test( "it shouldn't escape not-reserved characters", function( assert ) {
	assert.equal( regexpEscape( "foo" ), "foo" );
});

QUnit.test( "it should escape reserved characters", function( assert ) {
	assert.equal(
		regexpEscape( ".*+?^=!:${}()|\[\]\/\\" ),
		"\\.\\*\\+\\?\\^\\=\\!\\:\\$\\{\\}\\(\\)\\|\\[\\]\\/\\\\"
	);
});

});


<|start_filename|>src/message.js<|end_filename|>
define([
	"cldr",
	"messageformat",
	"./common/create-error/plural-module-presence",
	"./common/runtime-bind",
	"./common/validate/default-locale",
	"./common/validate/message-bundle",
	"./common/validate/message-presence",
	"./common/validate/message-type",
	"./common/validate/parameter-presence",
	"./common/validate/parameter-type",
	"./common/validate/parameter-type/plain-object",
	"./core",
	"./message/formatter-fn",
	"./message/formatter-runtime-bind",
	"./util/always-array",

	"cldr/event"
], function( Cldr, MessageFormat, createErrorPluralModulePresence, runtimeBind,
	validateDefaultLocale, validateMessageBundle, validateMessagePresence, validateMessageType,
	validateParameterPresence, validateParameterType, validateParameterTypePlainObject, Globalize,
	messageFormatterFn, messageFormatterRuntimeBind, alwaysArray ) {

var slice = [].slice;

/**
 * .loadMessages( json )
 *
 * @json [JSON]
 *
 * Load translation data.
 */
Globalize.loadMessages = function( json ) {
	var locale,
		customData = {
			"globalize-messages": json,
			"main": {}
		};

	validateParameterPresence( json, "json" );
	validateParameterTypePlainObject( json, "json" );

	// Set available bundles by populating customData main dataset.
	for ( locale in json ) {
		if ( json.hasOwnProperty( locale ) ) {
			customData.main[ locale ] = {};
		}
	}

	Cldr.load( customData );
};

/**
 * .messageFormatter( path )
 *
 * @path [String or Array]
 *
 * Format a message given its path.
 */
Globalize.messageFormatter =
Globalize.prototype.messageFormatter = function( path ) {
	var cldr, formatter, message, pluralGenerator, returnFn,
		args = slice.call( arguments, 0 );

	validateParameterPresence( path, "path" );
	validateParameterType( path, "path", typeof path === "string" || Array.isArray( path ),
		"a String nor an Array" );

	path = alwaysArray( path );
	cldr = this.cldr;

	validateDefaultLocale( cldr );
	validateMessageBundle( cldr );

	message = cldr.get( [ "globalize-messages/{bundle}" ].concat( path ) );
	validateMessagePresence( path, message );

	// If message is an Array, concatenate it.
	if ( Array.isArray( message ) ) {
		message = message.join( " " );
	}
	validateMessageType( path, message );

	// Is plural module present? Yes, use its generator. Nope, use an error generator.
	pluralGenerator = this.plural !== undefined ?
		this.pluralGenerator() :
		createErrorPluralModulePresence;

	formatter = new MessageFormat( cldr.locale, pluralGenerator ).compile( message );

	returnFn = messageFormatterFn( formatter );

	runtimeBind( args, cldr, returnFn,
		[ messageFormatterRuntimeBind( cldr, formatter ), pluralGenerator ] );

	return returnFn;
};

/**
 * .formatMessage( path [, variables] )
 *
 * @path [String or Array]
 *
 * @variables [Number, String, Array or Object]
 *
 * Format a message given its path.
 */
Globalize.formatMessage =
Globalize.prototype.formatMessage = function( path /* , variables */ ) {
	return this.messageFormatter( path ).apply( {}, slice.call( arguments, 1 ) );
};

return Globalize;

});


<|start_filename|>src/currency-runtime.js<|end_filename|>
define([
	"./common/runtime-key",
	"./common/validate/parameter-presence",
	"./common/validate/parameter-type/number",
	"./core-runtime",
	"./currency/formatter-fn",
	"./currency/name-format",
	"./currency/to-parts-formatter-fn",

	"./number-runtime"
], function( runtimeKey, validateParameterPresence, validateParameterTypeNumber, Globalize,
	currencyFormatterFn, currencyNameFormat, currencyToPartsFormatterFn ) {

Globalize._currencyFormatterFn = currencyFormatterFn;
Globalize._currencyNameFormat = currencyNameFormat;
Globalize._currencyToPartsFormatterFn = currencyToPartsFormatterFn;

Globalize.currencyFormatter =
Globalize.prototype.currencyFormatter = function( currency, options ) {
	options = options || {};
	return Globalize[ runtimeKey( "currencyFormatter", this._locale, [ currency, options ] ) ];
};

Globalize.currencyToPartsFormatter =
Globalize.prototype.currencyToPartsFormatter = function( currency, options ) {
	options = options || {};
	return Globalize[
		runtimeKey( "currencyToPartsFormatter", this._locale, [ currency, options ] )
	];
};

Globalize.formatCurrency =
Globalize.prototype.formatCurrency = function( value, currency, options ) {
	validateParameterPresence( value, "value" );
	validateParameterTypeNumber( value, "value" );

	return this.currencyFormatter( currency, options )( value );
};

Globalize.formatCurrencyToParts =
Globalize.prototype.formatCurrencyToParts = function( value, currency, options ) {
	validateParameterPresence( value, "value" );
	validateParameterTypeNumber( value, "value" );

	return this.currencyToPartsFormatter( currency, options )( value );
};

return Globalize;

});


<|start_filename|>test/functional/currency/format-currency.js<|end_filename|>
define([
	"globalize",
	"json!cldr-data/main/en/currencies.json",
	"json!cldr-data/main/en/numbers.json",
	"json!cldr-data/supplemental/currencyData.json",
	"json!cldr-data/supplemental/likelySubtags.json",
	"json!cldr-data/supplemental/plurals.json",
	"../../util",

	"globalize/currency",
	"globalize/number"
], function( Globalize, enCurrencies, enNumbers, currencyData, likelySubtags, plurals, util ) {

var teslaS = 69900;

function extraSetup() {
	Globalize.load(
		currencyData,
		enCurrencies,
		enNumbers,
		plurals
	);
}

QUnit.module( ".formatCurrency( value, currency [, options] )", {
	beforeEach: function() {
		Globalize.load( likelySubtags, {
			main: {
				en: {}
			}
		});
		Globalize.locale( "en" );
	},
	afterEach: util.resetCldrContent
});

QUnit.test( "should validate parameters", function( assert ) {
	util.assertParameterPresence( assert, "value", function() {
		Globalize.formatCurrency();
	});

	util.assertNumberParameter( assert, "value", function( invalidValue ) {
		return function() {
			Globalize.formatCurrency( invalidValue );
		};
	});

	util.assertParameterPresence( assert, "currency", function() {
		Globalize.formatCurrency( 7 );
	});

	util.assertCurrencyParameter( assert, "currency", function( invalidValue ) {
		return function() {
			Globalize.formatCurrency( 7, invalidValue );
		};
	});

	util.assertPlainObjectParameter( assert, "options", function( invalidValue ) {
		return function() {
			Globalize.formatCurrency( 7, "USD", invalidValue );
		};
	});
});

QUnit.test( "should validate CLDR content", function( assert ) {
	util.assertCldrContent( assert, function() {
		Globalize.formatCurrency( 7, "USD" );
	});
});

QUnit.test( "should format currencies", function( assert ) {
	extraSetup();
	assert.equal( Globalize.formatCurrency( teslaS, "USD" ), "$69,900.00" );
});

});


<|start_filename|>test/unit/currency/symbol-properties.js<|end_filename|>
define([
	"cldr",
	"src/currency/symbol-properties",
	"json!cldr-data/main/de/currencies.json",
	"json!cldr-data/main/de/numbers.json",
	"json!cldr-data/main/en/currencies.json",
	"json!cldr-data/main/en/numbers.json",
	"json!cldr-data/main/zh/currencies.json",
	"json!cldr-data/main/zh/numbers.json",
	"json!cldr-data/supplemental/currencyData.json",
	"json!cldr-data/supplemental/likelySubtags.json",

	"cldr/event",
	"cldr/supplemental"
], function( Cldr, symbolProperties, deCurrencies, deNumbers, enCurrencies, enNumbers, zhCurrencies,
	zhNumbers, currencyData, likelySubtags ) {

var de, en, zh;

Cldr.load(
	currencyData,
	deCurrencies,
	deNumbers,
	enCurrencies,
	enNumbers,
	likelySubtags,
	zhCurrencies,
	zhNumbers
);

de = new Cldr( "de" );
en = new Cldr( "en" );
zh = new Cldr( "zh" );

QUnit.module( "Currency Symbol Properties" );

QUnit.test( "should return pattern replacing `¤` with the appropriate currency symbol literal", function( assert ) {
	assert.deepEqual( symbolProperties( "USD", en, {} ), {
	"pattern": "¤#,##0.00",
	"symbol": "$"
	});
	assert.deepEqual( symbolProperties( "EUR", en, {} ), {
		"pattern": "¤#,##0.00",
		"symbol": "€"
	});
	assert.deepEqual( symbolProperties( "CLF", en, {} ), {
		"pattern": "¤ #,##0.0000",
		"symbol": "CLF"
	});
	assert.deepEqual( symbolProperties( "USD", de, {} ), {
		"pattern": "#,##0.00 ¤",
		"symbol": "$"
	});
	assert.deepEqual( symbolProperties( "EUR", de, {} ), {
		"pattern": "#,##0.00 ¤",
		"symbol": "€"
	});
	assert.deepEqual( symbolProperties( "USD", zh, {} ), {
		"pattern": "¤#,##0.00",
		"symbol": "US$"
	});
	assert.deepEqual( symbolProperties( "EUR", zh, {} ), {
		"pattern": "¤#,##0.00",
		"symbol": "€"
	});
	assert.deepEqual( symbolProperties( "RUB", en, {} ), {
		"pattern": "¤ #,##0.00",
		"symbol": "RUB"
	});

	assert.deepEqual( symbolProperties( "USD", en, {
		style: "accounting"
	}), {
		"pattern": "¤#,##0.00;(¤#,##0.00)",
		"symbol": "$"
	});
});

QUnit.test( "Should use the supplied symbolForm, falling back to standard if none is found", function( assert ) {
	assert.deepEqual(
		symbolProperties( "RUB", en, { symbolForm: "narrow" } ),
		{ "pattern": "¤#,##0.00", "symbol": "₽" }
	);
	assert.deepEqual(
		symbolProperties( "HKD", en, { symbolForm: "narrow" } ),
		{ "pattern": "¤#,##0.00", "symbol": "$" }
	);
	assert.deepEqual(
		symbolProperties( "CHF", en, { symbolForm: "narrow" } ),
		{ "pattern": "¤ #,##0.00", "symbol": "CHF" }
	);
});

});


<|start_filename|>test/unit/date/expand-pattern/compare-formats.js<|end_filename|>
define([
	"src/date/expand-pattern/compare-formats"
], function( compareFormats ) {

QUnit.module( "Date Expand Pattern Compare Formats" );

// "Most symbols have a small distance from each other, e.g., M ≅ L; E ≅ c; a ≅ b ≅ B;
//  H ≅ k ≅ h ≅ K; ..."
QUnit.test( "should add a small distance on similar patterns", function( assert ) {
	assert.ok( compareFormats( "MM", "LL" ) > compareFormats( "MM", "MM" ) );
	assert.ok( compareFormats( "MM", "LLL" ) > compareFormats( "MM", "MMM" ) );
	assert.ok( compareFormats( "E", "c" ) > compareFormats( "E", "E" ) );
});

// Numeric (l<3) and text fields (l>=3) are given a larger distance from each other.
QUnit.test( "should add a larger distance comparing numeric vs text fields", function( assert ) {
	assert.ok( compareFormats( "MM", "MMM" ) > compareFormats( "MM", "M" ) );
	assert.ok( compareFormats( "MMM", "MM" ) > compareFormats( "MMM", "MMMMM" ) );
});

QUnit.test( "should mark not equal things", function( assert ) {
	assert.equal( compareFormats( "yMd", "d" ), -1 );
	assert.equal( compareFormats( "MM", "d" ), -1 );
	assert.equal( compareFormats( "yMMd", "MMM" ), -1 );
});

});


<|start_filename|>test/unit/number/format/significant-digits.js<|end_filename|>
define([
	"src/number/format/significant-digits",
	"src/util/number/round"
], function( formatSignificantDigits, round ) {

var ceil = round( "ceil" ),
	deci = 0.1,
	floor = round( "floor" ),
	pi = 3.14159265359,
	truncate = round( "truncate" ),
	round = round( "round" );

QUnit.module( "Number Significant Format" );

QUnit.test( "should zero-pad minimum significant figures", function( assert ) {
	assert.equal( formatSignificantDigits( deci, 3, 3, round ), "0.100" );
});

QUnit.test( "should limit maximum significant figures", function( assert ) {
	assert.equal( formatSignificantDigits( 123, 3, 3, round ), "123" );
	assert.equal( formatSignificantDigits( 12345, 3, 3, round ), "12300" );
	assert.equal( formatSignificantDigits( pi, 2, 2, round ), "3.1" );
	assert.equal( formatSignificantDigits( pi, 2, 3, round ), "3.14" );
	assert.equal( formatSignificantDigits( pi, 2, 4, round ), "3.142" );
	assert.equal( formatSignificantDigits( pi, 1, 5, round ), "3.1416" );
	assert.equal( formatSignificantDigits( 0.10004, 2, 2, round ), "0.10" );
	assert.equal( formatSignificantDigits( 0.12345, 3, 3, round ), "0.123" );
	assert.equal( formatSignificantDigits( 0.012345, 3, 3, round ), "0.0123" );
});

QUnit.test( "should allow different round options", function( assert ) {
	assert.equal( formatSignificantDigits( 0.12345, 3, 3, ceil ), "0.124" );
	assert.equal( formatSignificantDigits( 0.12345, 3, 3, floor ), "0.123" );
	assert.equal( formatSignificantDigits( 0.12345, 3, 3, truncate ), "0.123" );
	assert.equal( formatSignificantDigits( -0.12345, 3, 3, ceil ), "-0.123" );
	assert.equal( formatSignificantDigits( -0.12345, 3, 3, floor ), "-0.124" );
	assert.equal( formatSignificantDigits( -0.12345, 3, 3, truncate ), "-0.123" );
});

QUnit.test( "should handle inaccurate floating point arithmetics", function( assert ) {
	assert.equal( formatSignificantDigits( 0.00012345, 1, 3, round ), "0.000123" );
});

});


<|start_filename|>src/date/expand-pattern/get-best-match-pattern.js<|end_filename|>
define([
	"./augment-format",
	"./compare-formats",
	"../../number/symbol"
], function( dateExpandPatternAugmentFormat, dateExpandPatternCompareFormats, numberSymbol ) {

return function( cldr, askedSkeleton ) {
	var availableFormats, decimalSeparator, pattern, ratedFormats, skeleton,
		path = "dates/calendars/gregorian/dateTimeFormats/availableFormats",

		// Using easier to read variables.
		augmentFormat = dateExpandPatternAugmentFormat,
		compareFormats = dateExpandPatternCompareFormats;

	pattern = cldr.main([ path, askedSkeleton ]);

	if ( askedSkeleton && !pattern ) {
		availableFormats = cldr.main([ path ]);
		ratedFormats = [];

		for ( skeleton in availableFormats ) {
			ratedFormats.push({
				skeleton: skeleton,
				pattern: availableFormats[ skeleton ],
				rate: compareFormats( askedSkeleton, skeleton )
			});
		}

		ratedFormats = ratedFormats
			.filter( function( format ) {
				return format.rate > -1;
			} )
			.sort( function( formatA, formatB ) {
				return formatA.rate - formatB.rate;
			});

		if ( ratedFormats.length ) {
			decimalSeparator = numberSymbol( "decimal", cldr );
			pattern = augmentFormat( askedSkeleton, ratedFormats[ 0 ].pattern, decimalSeparator );
		}
	}

	return pattern;
};

});


<|start_filename|>src/date/expand-pattern/augment-format.js<|end_filename|>
define([
	"./normalize-pattern-type",
	"../pattern-re",
	"../../util/string/repeat"
], function( dateExpandPatternNormalizePatternType, datePatternRe, stringRepeat ) {

function expandBestMatchFormat( skeletonWithoutFractionalSeconds, bestMatchFormat ) {
	var i, j, bestMatchFormatParts, matchedType, matchedLength, requestedType,
		requestedLength, requestedSkeletonParts,

		// Using an easier to read variable.
		normalizePatternType = dateExpandPatternNormalizePatternType;

	requestedSkeletonParts = skeletonWithoutFractionalSeconds.match( datePatternRe );
	bestMatchFormatParts = bestMatchFormat.match( datePatternRe );

	for ( i = 0; i < bestMatchFormatParts.length; i++ ) {
		matchedType = bestMatchFormatParts[ i ].charAt( 0 );
		matchedLength = bestMatchFormatParts[ i ].length;
		for ( j = 0; j < requestedSkeletonParts.length; j++ ) {
			requestedType = requestedSkeletonParts[ j ].charAt( 0 );
			requestedLength = requestedSkeletonParts[ j ].length;
			if ( normalizePatternType( matchedType ) === normalizePatternType( requestedType ) &&
				matchedLength < requestedLength
			) {
				bestMatchFormatParts[ i ] = stringRepeat( matchedType, requestedLength );
			}
		}
	}

	return bestMatchFormatParts.join( "" );
}

// See: http://www.unicode.org/reports/tr35/tr35-dates.html#Matching_Skeletons
return function( requestedSkeleton, bestMatchFormat, decimalSeparator ) {
	var countOfFractionalSeconds, fractionalSecondMatch, lastSecondIdx,
		skeletonWithoutFractionalSeconds;

	fractionalSecondMatch = requestedSkeleton.match( /S/g );
	countOfFractionalSeconds = fractionalSecondMatch ? fractionalSecondMatch.length : 0;
	skeletonWithoutFractionalSeconds = requestedSkeleton.replace( /S/g, "" );

	bestMatchFormat = expandBestMatchFormat( skeletonWithoutFractionalSeconds, bestMatchFormat );

	lastSecondIdx = bestMatchFormat.lastIndexOf( "s" );
	if ( lastSecondIdx !== -1 && countOfFractionalSeconds !== 0 ) {
		bestMatchFormat =
			bestMatchFormat.slice( 0, lastSecondIdx + 1 ) +
			decimalSeparator +
			stringRepeat( "S", countOfFractionalSeconds ) +
			bestMatchFormat.slice( lastSecondIdx + 1 );
	}
	return bestMatchFormat;
};

});


<|start_filename|>src/number/format/integer-fraction-digits.js<|end_filename|>
define([
	"../../util/string/pad"
], function( stringPad ) {

/**
 * integerFractionDigits( number, minimumIntegerDigits, minimumFractionDigits,
 * maximumFractionDigits, round, roundIncrement )
 *
 * @number [Number]
 *
 * @minimumIntegerDigits [Number]
 *
 * @minimumFractionDigits [Number]
 *
 * @maximumFractionDigits [Number]
 *
 * @round [Function]
 *
 * @roundIncrement [Function]
 *
 * Return the formatted integer and fraction digits.
 */
return function( number, minimumIntegerDigits, minimumFractionDigits, maximumFractionDigits, round,
	roundIncrement ) {

	// Fraction
	if ( maximumFractionDigits ) {

		// Rounding
		if ( roundIncrement ) {
			number = round( number, roundIncrement );

		// Maximum fraction digits
		} else {
			number = round( number, { exponent: -maximumFractionDigits } );
		}

	} else {
		number = round( number );
	}

	number = String( number );

	// Maximum integer digits (post string phase)
	if ( maximumFractionDigits && /e-/.test( number ) ) {

		// Use toFixed( maximumFractionDigits ) to make sure small numbers like 1e-7 are
		// displayed using plain digits instead of scientific notation.
		// 1: Remove leading decimal zeros.
		// 2: Remove leading decimal separator.
		// Note: String() is still preferred so it doesn't mess up with a number precision
		// unnecessarily, e.g., (123456789.123).toFixed(10) === "123456789.1229999959",
		// String(123456789.123) === "123456789.123".
		number = ( +number ).toFixed( maximumFractionDigits )
			.replace( /0+$/, "" ) /* 1 */
			.replace( /\.$/, "" ); /* 2 */
	}

	// Minimum fraction digits (post string phase)
	if ( minimumFractionDigits ) {
		number = number.split( "." );
		number[ 1 ] = stringPad( number[ 1 ] || "", minimumFractionDigits, true );
		number = number.join( "." );
	}

	// Minimum integer digits
	if ( minimumIntegerDigits ) {
		number = number.split( "." );
		number[ 0 ] = stringPad( number[ 0 ], minimumIntegerDigits );
		number = number.join( "." );
	}

	return number;
};

});


<|start_filename|>test/unit/util/object/invert.js<|end_filename|>
define([
	"src/util/object/invert",
], function( objectInvert ) {

QUnit.module( "Util object invert" );

QUnit.test( "it should invert an object", function( assert ) {
	assert.deepEqual(
		objectInvert({ a: "x", b: "y" }),
		{ x: "a", y: "b" }
	);
});

QUnit.test( "it should invert an object using a custom setter", function( assert ) {
	assert.deepEqual(
		objectInvert({ a: "x", b: "y" }, function( object, key, value ) {
			object[ value ] = "foo-" + key;
			return object;
		}),
		{ x: "foo-a", y: "foo-b" }
	);
});

});


<|start_filename|>src/common/format-message-to-parts.js<|end_filename|>
define([
	"./parts/push"
], function( partsPush ) {

/**
 * formatMessage( message, data )
 *
 * @message [String] A message with optional {vars} to be replaced.
 *
 * @data [Array or JSON] Object with replacing-variables content.
 *
 * Return the formatted message. For example:
 *
 * - formatMessage( "{0} second", [ 1 ] );
 * > [{type: "variable", value: "1", name: "0"}, {type: "literal", value: " second"}]
 *
 * - formatMessage( "{0}/{1}", ["m", "s"] );
 * > [
 *     { type: "variable", value: "m", name: "0" },
 *     { type: "literal", value: " /" },
 *     { type: "variable", value: "s", name: "1" }
 *   ]
 */
return function( message, data ) {

	var lastOffset = 0,
		parts = [];

	// Create parts.
	message.replace( /{[0-9a-zA-Z-_. ]+}/g, function( nameIncludingBrackets, offset ) {
		var name = nameIncludingBrackets.slice( 1, -1 );
		partsPush( parts, "literal", message.slice( lastOffset, offset ));
		partsPush( parts, "variable", data[ name ] );
		parts[ parts.length - 1 ].name = name;
		lastOffset += offset + nameIncludingBrackets.length;
	});

	// Skip empty ones such as `{ type: 'literal', value: '' }`.
	return parts.filter(function( part ) {
		return part.value !== "";
	});
};

});


<|start_filename|>src/currency/formatter-fn.js<|end_filename|>
define([
	"../common/parts/join"
], function( partsJoin ) {

return function( currencyToPartsFormatter ) {
	return function currencyFormatter( value ) {
		return partsJoin( currencyToPartsFormatter( value ));
	};
};

});


<|start_filename|>src/currency/symbol-format.js<|end_filename|>
define(function() {

/**
 * symbolFormat( parts, symbol )
 *
 * Return the appropriate symbol/account form format.
 */
return function( parts, symbol ) {
	parts.forEach(function( part ) {
		if ( part.type === "currency" ) {
			part.value = symbol;
		}
	});
	return parts;
};

});


<|start_filename|>test/functional/number/parse-number.js<|end_filename|>
define([
	"globalize",
	"json!cldr-data/main/ar/numbers.json",
	"json!cldr-data/main/en/numbers.json",
	"json!cldr-data/main/en-IN/numbers.json",
	"json!cldr-data/main/es/numbers.json",
	"json!cldr-data/main/fa/numbers.json",
	"json!cldr-data/main/sv/numbers.json",
	"json!cldr-data/main/zh/numbers.json",
	"json!cldr-data/supplemental/likelySubtags.json",
	"json!cldr-data/supplemental/numberingSystems.json",
	"../../util",

	"globalize/number"
], function( Globalize, arNumbers, enNumbers, enInNumbers, esNumbers, faNumbers, svNumbers,
	zhNumbers, likelySubtags, numberingSystems, util ) {

var ar, enIn, es, fa, sv, zh;

function extraSetup() {
	Globalize.load(
		arNumbers,
		enNumbers,
		enInNumbers,
		esNumbers,
		faNumbers,
		svNumbers,
		zhNumbers,
		numberingSystems
	);
}

QUnit.module( ".parseNumber( value [, options] )", {
	beforeEach: function() {
		Globalize.load( likelySubtags, {
			main: {
				ar: {},
				en: {},
				"en-IN": {},
				es: {},
				fa: {},
				sv: {},
				zh: {}
			}
		});
		ar = new Globalize( "ar" );
		enIn = new Globalize( "en-IN" );
		es = new Globalize( "es" );
		fa = new Globalize( "fa" );
		sv = new Globalize( "sv" );
		zh = new Globalize( "zh-u-nu-native" );
		Globalize.locale( "en" );
	},
	afterEach: util.resetCldrContent
});

QUnit.test( "should validate parameters", function( assert ) {
	util.assertParameterPresence( assert, "value", function() {
		Globalize.parseNumber();
	});

	util.assertStringParameter( assert, "value", function( invalidValue ) {
		return function() {
			Globalize.parseNumber( invalidValue );
		};
	});

	util.assertPlainObjectParameter( assert, "options", function( invalidValue ) {
		return function() {
			Globalize.parseNumber( "3", invalidValue );
		};
	});
});

QUnit.test( "should validate CLDR content", function( assert ) {
	util.assertCldrContent( assert, function() {
		Globalize.parseNumber( "3" );
	});
});

/**
 *  Integers
 */

QUnit.test( "should parse integers", function( assert ) {
	extraSetup();

	assert.equal( Globalize.parseNumber( "3" ), 3 );
	assert.equal( Globalize.parseNumber( "12735" ), 12735 );

	// Loose match: ignore control format symbols.
	assert.equal( ar.parseNumber( "-٣" ), -3 );

	// Grouping separator.
	assert.equal( Globalize.parseNumber( "12,735" ), 12735 );
	assert.equal( enIn.parseNumber( "76,54,321" ), 7654321 );
	assert.deepEqual( enIn.parseNumber( "654,321" ), NaN );
	assert.equal( es.parseNumber( "12.735" ), 12735 );
	assert.equal( sv.parseNumber( "12\xA0735" ), 12735 );

	// Loose match: map all characters in [:Zs:] to U+0020 SPACE, e.g., accept non-breaking space as
	// grouping separator.
	assert.equal( sv.parseNumber( "12 735" ), 12735 );
});

QUnit.test( "should parse negative integers", function( assert ) {
	extraSetup();

	assert.equal( Globalize.parseNumber( "-3" ), -3 );
	assert.equal( Globalize.parseNumber( "-12,735" ), -12735 );
});

/**
 *  Decimals
 */

QUnit.test( "should parse decimals", function( assert ) {
	extraSetup();

	assert.equal( Globalize.parseNumber( "3.14" ), 3.14 );
	assert.deepEqual( Globalize.parseNumber( "3,14" ), NaN );
	assert.equal( es.parseNumber( "3,14" ), 3.14 );
	assert.deepEqual( es.parseNumber( "3.14" ), NaN );
	assert.equal( ar.parseNumber( "٣٫١٤" ), 3.14 );
	assert.equal( zh.parseNumber( "三.一四" ), 3.14 );
	assert.equal( Globalize.parseNumber( "3.00" ), 3 );
	assert.equal( Globalize.parseNumber( "12735.0" ), 12735 );
	assert.equal( Globalize.parseNumber( "0.10" ), 0.1 );
});

QUnit.test( "should parse negative decimal", function( assert ) {
	extraSetup();

	assert.equal( Globalize.parseNumber( "-3.14" ), -3.14 );
});

/**
 *  Percent
 */

QUnit.test( "should parse percent", function( assert ) {
	extraSetup();

	assert.equal( Globalize.parseNumber( "1%", { style: "percent" } ), 0.01 );
	assert.equal( Globalize.parseNumber( "01%", { style: "percent" } ), 0.01 );
	assert.equal( Globalize.parseNumber( "10%", { style: "percent" } ), 0.1 );
	assert.equal( Globalize.parseNumber( "50%", { style: "percent" } ), 0.5 );
	assert.equal( Globalize.parseNumber( "100%", { style: "percent" } ), 1 );

	assert.equal( Globalize.parseNumber( "0.5%", {
		style: "percent",
		minimumFractionDigits: 0,
		maximumFractionDigits: 1
	}), 0.005 );

	assert.equal( Globalize.parseNumber( "0.5%", {
		style: "percent",
		minimumFractionDigits: 0,
		maximumFractionDigits: 1
	}), 0.005 );

	assert.equal( ar.parseNumber( "٥٠٪", { style: "percent" } ), 0.5 );
	assert.equal( Globalize.parseNumber( "-10%", { style: "percent" } ), -0.1 );
});

/**
 *  Infinite number
 */
QUnit.test( "should parse infinite numbers", function( assert ) {
	extraSetup();

	assert.equal( Globalize.parseNumber( "∞" ), Infinity );
	assert.equal( Globalize.parseNumber( "-∞" ), -Infinity );
});

/**
 *  NaN
 */

QUnit.test( "should parse invalid numbers as NaN", function( assert ) {
	extraSetup();

	assert.deepEqual( Globalize.parseNumber( "invalid" ), NaN );
	assert.deepEqual( Globalize.parseNumber( "NaN" ), NaN );
});

/**
 *  Prefix
 */

QUnit.test( "should parse literals", function( assert ) {
	extraSetup();

	// TODO: Move this test to parse-currency when implemented.
	assert.equal( Globalize.parseNumber( "-$1,214.12", { raw: "'$'#,##0.##" } ), -1214.12 );
});

/**
 *  Other
 */
QUnit.test( "should parse a formatted number (reverse operation test)", function( assert ) {
	extraSetup();
	var options;
	var number = 12345.67;
	assert.equal( Globalize.parseNumber( Globalize.formatNumber( number ) ), number );
	assert.equal( ar.parseNumber( ar.formatNumber( number ) ), number );
	assert.equal( fa.parseNumber( fa.formatNumber( number ) ), number );

	number = -12345.67;
	assert.equal( Globalize.parseNumber( Globalize.formatNumber( number ) ), number );
	assert.equal( ar.parseNumber( ar.formatNumber( number ) ), number );
	assert.equal( fa.parseNumber( fa.formatNumber( number ) ), number );

	number = 0.5;
	options = { style: "percent" };

	assert.equal(
		Globalize.parseNumber( Globalize.formatNumber( number, options ), options ),
		number
	);

	assert.equal( ar.parseNumber( ar.formatNumber( number, options ), options ), number );
	assert.equal( fa.parseNumber( fa.formatNumber( number, options ), options ), number );
});

});


<|start_filename|>src/currency.js<|end_filename|>
define([
	"./core",
	"./common/create-error/plural-module-presence",
	"./common/runtime-bind",
	"./common/validate/cldr",
	"./common/validate/default-locale",
	"./common/validate/parameter-presence",
	"./common/validate/parameter-type/currency",
	"./common/validate/parameter-type/number",
	"./common/validate/parameter-type/plain-object",
	"./currency/formatter-fn",
	"./currency/name-properties",
	"./currency/symbol-properties",
	"./currency/to-parts-formatter-fn",
	"./util/object/omit",
	"./number",

	"cldr/event",
	"cldr/supplemental"

], function( Globalize, createErrorPluralModulePresence, runtimeBind, validateCldr,
	validateDefaultLocale, validateParameterPresence, validateParameterTypeCurrency,
	validateParameterTypeNumber, validateParameterTypePlainObject, currencyFormatterFn,
	currencyNameProperties, currencySymbolProperties, currencyToPartsFormatterFn, objectOmit ) {

function validateRequiredCldr( path, value ) {
	validateCldr( path, value, {
		skip: [
			/numbers\/currencies\/[^/]+\/symbol-alt-/,
			/supplemental\/currencyData\/fractions\/[A-Za-z]{3}$/
		]
	});
}

/**
 * .currencyFormatter( currency [, options] )
 *
 * @currency [String] 3-letter currency code as defined by ISO 4217.
 *
 * @options [Object]:
 * - style: [String] "symbol" (default), "accounting", "code" or "name".
 * - see also number/format options.
 *
 * Return a function that formats a currency according to the given options and default/instance
 * locale.
 */
Globalize.currencyFormatter =
Globalize.prototype.currencyFormatter = function( currency, options ) {
	var args, currencyToPartsFormatter, returnFn;

	validateParameterPresence( currency, "currency" );
	validateParameterTypeCurrency( currency, "currency" );

	validateParameterTypePlainObject( options, "options" );

	options = options || {};
	args = [ currency, options ];

	currencyToPartsFormatter = this.currencyToPartsFormatter( currency, options );
	returnFn = currencyFormatterFn( currencyToPartsFormatter );
	runtimeBind( args, this.cldr, returnFn, [ currencyToPartsFormatter ] );

	return returnFn;
};

/**
 * .currencyToPartsFormatter( currency [, options] )
 *
 * @currency [String] 3-letter currency code as defined by ISO 4217.
 *
 * @options [Object]:
 * - style: [String] "symbol" (default), "accounting", "code" or "name".
 * - see also number/format options.
 *
 * Return a currency formatter function (of the form below) according to the given options and the
 * default/instance locale.
 *
 * fn( value )
 *
 * @value [Number]
 *
 * Return a function that formats a currency to parts according to the given options
 * and the default/instance locale.
 */
Globalize.currencyToPartsFormatter =
Globalize.prototype.currencyToPartsFormatter = function( currency, options ) {
	var args, cldr, numberToPartsFormatter, pluralGenerator, properties, returnFn, style;

	validateParameterPresence( currency, "currency" );
	validateParameterTypeCurrency( currency, "currency" );

	validateParameterTypePlainObject( options, "options" );

	cldr = this.cldr;
	options = options || {};

	args = [ currency, options ];
	style = options.style || "symbol";

	validateDefaultLocale( cldr );

	// Get properties given style ("symbol" default, "code" or "name").
	cldr.on( "get", validateRequiredCldr );
	try {
		properties = ({
			accounting: currencySymbolProperties,
			code: currencySymbolProperties,
			name: currencyNameProperties,
			symbol: currencySymbolProperties
		}[ style ] )( currency, cldr, options );
	} finally {
		cldr.off( "get", validateRequiredCldr );
	}

	// options = options minus style, plus raw pattern.
	options = objectOmit( options, "style" );
	options.raw = properties.pattern;

	// Return formatter when style is "symbol", "accounting", or "code".
	if ( style === "symbol" || style === "accounting" || style === "code" ) {
		numberToPartsFormatter = this.numberToPartsFormatter( options );

		returnFn = currencyToPartsFormatterFn( numberToPartsFormatter, properties.symbol );

		runtimeBind( args, cldr, returnFn, [ numberToPartsFormatter, properties.symbol ] );

	// Return formatter when style is "name".
	} else {
		numberToPartsFormatter = this.numberToPartsFormatter( options );

		// Is plural module present? Yes, use its generator. Nope, use an error generator.
		pluralGenerator = this.plural !== undefined ?
			this.pluralGenerator() :
			createErrorPluralModulePresence;

		returnFn = currencyToPartsFormatterFn(
			numberToPartsFormatter,
			pluralGenerator,
			properties
		);

		runtimeBind( args, cldr, returnFn, [
			numberToPartsFormatter,
			pluralGenerator,
			properties
		]);
	}

	return returnFn;
};

/**
 * .currencyParser( currency [, options] )
 *
 * @currency [String] 3-letter currency code as defined by ISO 4217.
 *
 * @options [Object] see currencyFormatter.
 *
 * Return the currency parser according to the given options and the default/instance locale.
 */
Globalize.currencyParser =
Globalize.prototype.currencyParser = function( /* currency, options */ ) {

	// TODO implement parser.

};

/**
 * .formatCurrency( value, currency [, options] )
 *
 * @value [Number] number to be formatted.
 *
 * @currency [String] 3-letter currency code as defined by ISO 4217.
 *
 * @options [Object] see currencyFormatter.
 *
 * Format a currency according to the given options and the default/instance locale.
 */
Globalize.formatCurrency =
Globalize.prototype.formatCurrency = function( value, currency, options ) {
	validateParameterPresence( value, "value" );
	validateParameterTypeNumber( value, "value" );
	return this.currencyFormatter( currency, options )( value );
};

/**
 * .formatCurrencyToParts( value, currency [, options] )
 *
 * @value [Number] number to be formatted.
 *
 * @currency [String] 3-letter currency code as defined by ISO 4217.
 *
 * @options [Object] see currencyFormatter.
 *
 * Format a currency to parts according to the given options and the default/instance locale.
 */
Globalize.formatCurrencyToParts =
Globalize.prototype.formatCurrencyToParts = function( value, currency, options ) {
	validateParameterPresence( value, "value" );
	validateParameterTypeNumber( value, "value" );
	return this.currencyToPartsFormatter( currency, options )( value );
};

/**
 * .parseCurrency( value, currency [, options] )
 *
 * @value [String]
 *
 * @currency [String] 3-letter currency code as defined by ISO 4217.
 *
 * @options [Object]: See currencyFormatter.
 *
 * Return the parsed currency or NaN when value is invalid.
 */
Globalize.parseCurrency =
Globalize.prototype.parseCurrency = function( /* value, currency, options */ ) {
};

return Globalize;

});


<|start_filename|>src/date/tokenizer-properties.js<|end_filename|>
define([
	"./get-time-zone-name",
	"./pattern-re",
	"./timezone-hour-format/h",
	"./timezone-hour-format/hm",
	"../common/create-error/unsupported-feature",
	"../common/format-message",
	"../number/numbering-system-digits-map",
	"../number/symbol",
	"../util/is-plain-object",
	"../util/loose-matching",
	"../util/object/filter",
	"../util/regexp/escape"
], function( dateGetTimeZoneName, datePatternRe, dateTimezoneHourFormatH, dateTimezoneHourFormatHm,
	createErrorUnsupportedFeature, formatMessage, numberNumberingSystemDigitsMap, numberSymbol,
	isPlainObject, looseMatching, objectFilter, regexpEscape ) {

/**
 * tokenizerProperties( pattern, cldr )
 *
 * @pattern [String] raw pattern.
 *
 * @cldr [Cldr instance].
 *
 * Return Object with data that will be used by tokenizer.
 */
return function( pattern, cldr, timeZone ) {
	var digitsReSource,
		properties = {
			pattern: looseMatching( pattern )
		},
		timeSeparator = numberSymbol( "timeSeparator", cldr ),
		widths = [ "abbreviated", "wide", "narrow" ];

	digitsReSource = numberNumberingSystemDigitsMap( cldr );
	digitsReSource = digitsReSource ? "[" + digitsReSource + "]" : "\\d";
	properties.digitsRe = new RegExp( digitsReSource );

	// Transform:
	// - "+H;-H" -> /\+(\d\d?)|-(\d\d?)/
	// - "+HH;-HH" -> /\+(\d\d)|-(\d\d)/
	// - "+HHmm;-HHmm" -> /\+(\d\d)(\d\d)|-(\d\d)(\d\d)/
	// - "+HH:mm;-HH:mm" -> /\+(\d\d):(\d\d)|-(\d\d):(\d\d)/
	//
	// If gmtFormat is GMT{0}, the regexp must fill {0} in each side, e.g.:
	// - "+H;-H" -> /GMT\+(\d\d?)|GMT-(\d\d?)/
	function hourFormatRe( hourFormat, gmtFormat, digitsReSource, timeSeparator ) {
		var re;

		if ( !digitsReSource ) {
			digitsReSource = "\\d";
		}
		if ( !gmtFormat ) {
			gmtFormat = "{0}";
		}

		re = hourFormat
			.replace( "+", "\\+" )

			// Unicode equivalent to (\\d\\d)
			.replace( /HH|mm|ss/g, "((" + digitsReSource + "){2})" )

			// Unicode equivalent to (\\d\\d?)
			.replace( /H|m/g, "((" + digitsReSource + "){1,2})" );

		if ( timeSeparator ) {
			re = re.replace( /:/g, timeSeparator );
		}

		re = re.split( ";" ).map(function( part ) {
			return gmtFormat.replace( "{0}", part );
		}).join( "|" );

		return new RegExp( "^" + re );
	}

	function populateProperties( path, value ) {

		// Skip
		var skipRe = /(timeZoneNames\/zone|supplemental\/metaZones|timeZoneNames\/metazone|timeZoneNames\/regionFormat|timeZoneNames\/gmtFormat)/;
		if ( skipRe.test( path ) ) {
			return;
		}

		if ( !value ) {
			return;
		}

		// The `dates` and `calendars` trim's purpose is to reduce properties' key size only.
		path = path.replace( /^.*\/dates\//, "" ).replace( /calendars\//, "" );

		// Specific filter for "gregorian/dayPeriods/format/wide".
		if ( path === "gregorian/dayPeriods/format/wide" ) {
			value = objectFilter( value, /^am|^pm/ );
		}

		// Transform object into array of pairs [key, /value/], sort by desc value length.
		if ( isPlainObject( value ) ) {
			value = Object.keys( value ).map(function( key ) {
				return [ key, new RegExp( "^" + regexpEscape( looseMatching( value[ key ] ) ) ) ];
			}).sort(function( a, b ) {
				return b[ 1 ].source.length - a[ 1 ].source.length;
			});

		// If typeof value === "string".
		} else {
			value = looseMatching( value );
		}
		properties[ path ] = value;
	}

	function regexpSourceSomeTerm( terms ) {
		return "(" + terms.filter(function( item ) {
			return item;
		}).reduce(function( memo, item ) {
			return memo + "|" + item;
		}) + ")";
	}

	cldr.on( "get", populateProperties );

	pattern.match( datePatternRe ).forEach(function( current ) {
		var aux, chr, daylightTzName, gmtFormat, length, standardTzName;

		chr = current.charAt( 0 );
		length = current.length;

		if ( chr === "Z" ) {
			if ( length < 5 ) {
				chr = "O";
				length = 4;
			} else {
				chr = "X";
				length = 5;
			}
		}

		// z...zzz: "{shortRegion}", eg. "PST" or "PDT".
		// zzzz: "{regionName} {Standard Time}" or "{regionName} {Daylight Time}",
		//       e.g., "Pacific Standard Time" or "Pacific Daylight Time".
		// http://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns
		if ( chr === "z" ) {
			standardTzName = dateGetTimeZoneName( length, "standard", timeZone, cldr );
			daylightTzName = dateGetTimeZoneName( length, "daylight", timeZone, cldr );
			if ( standardTzName ) {
				standardTzName = regexpEscape( looseMatching( standardTzName ) );
			}
			if ( daylightTzName ) {
				daylightTzName = regexpEscape( looseMatching( daylightTzName ) );
			}
			if ( standardTzName || daylightTzName ) {
				properties.standardOrDaylightTzName = new RegExp(
					"^" + regexpSourceSomeTerm([ standardTzName, daylightTzName ])
				);
			}

			// Fall through the "O" format in case one name is missing.
			if ( !standardTzName || !daylightTzName ) {
				chr = "O";
				if ( length < 4 ) {
					length = 1;
				}
			}
		}

		// v...vvv: "{shortRegion}", eg. "PT".
		// vvvv: "{regionName} {Time}" or "{regionName} {Time}",
		// e.g., "Pacific Time"
		// http://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns
		if ( chr === "v" ) {
			if ( length !== 1 && length !== 4 ) {
				throw createErrorUnsupportedFeature({
					feature: "timezone pattern `" + pattern + "`"
				});
			}
			var genericTzName = dateGetTimeZoneName( length, "generic", timeZone, cldr );
			if ( genericTzName ) {
				properties.genericTzName = new RegExp(
					"^" + regexpEscape( looseMatching( genericTzName ) )
				);
				chr = "O";

			// Fall back to "V" format.
			} else {
				chr = "V";
				length = 4;
			}
		}

		switch ( chr ) {

			// Era
			case "G":
				cldr.main([
					"dates/calendars/gregorian/eras",
					length <= 3 ? "eraAbbr" : ( length === 4 ? "eraNames" : "eraNarrow" )
				]);
				break;

			// Year
			case "u": // Extended year. Need to be implemented.
			case "U": // Cyclic year name. Need to be implemented.
				throw createErrorUnsupportedFeature({
					feature: "year pattern `" + chr + "`"
				});

			// Quarter
			case "Q":
			case "q":
				if ( length > 2 ) {
					cldr.main([
						"dates/calendars/gregorian/quarters",
						chr === "Q" ? "format" : "stand-alone",
						widths[ length - 3 ]
					]);
				}
				break;

			// Month
			case "M":
			case "L":

				// number l=1:{1,2}, l=2:{2}.
				// lookup l=3...
				if ( length > 2 ) {
					cldr.main([
						"dates/calendars/gregorian/months",
						chr === "M" ? "format" : "stand-alone",
						widths[ length - 3 ]
					]);
				}
				break;

			// Day
			case "g":

				// Modified Julian day. Need to be implemented.
				throw createErrorUnsupportedFeature({
					feature: "Julian day pattern `g`"
				});

			// Week day
			case "e":
			case "c":

				// lookup for length >=3.
				if ( length <= 2 ) {
					break;
				}

			/* falls through */
			case "E":
				if ( length === 6 ) {

					// Note: if short day names are not explicitly specified, abbreviated day
					// names are used instead http://www.unicode.org/reports/tr35/tr35-dates.html#months_days_quarters_eras
					// eslint-disable-next-line no-unused-expressions
					cldr.main([
						"dates/calendars/gregorian/days",
						[ chr === "c" ? "stand-alone" : "format" ],
						"short"
					]) || cldr.main([
						"dates/calendars/gregorian/days",
						[ chr === "c" ? "stand-alone" : "format" ],
						"abbreviated"
					]);
				} else {
					cldr.main([
						"dates/calendars/gregorian/days",
						[ chr === "c" ? "stand-alone" : "format" ],
						widths[ length < 3 ? 0 : length - 3 ]
					]);
				}
				break;

			// Period (AM or PM)
			case "a":
				cldr.main(
					"dates/calendars/gregorian/dayPeriods/format/wide"
				);
				break;

			// Zone
			case "V":

				if ( length === 1 ) {
					throw createErrorUnsupportedFeature({
						feature: "timezone pattern `" + pattern + "`"
					});
				}

				if ( timeZone ) {
					if ( length === 2 ) {

						// Skip looseMatching processing since timeZone is a canonical posix value.
						properties.timeZoneName = timeZone;
						properties.timeZoneNameRe = new RegExp( "^" + regexpEscape( timeZone ) );
						break;
					}

					var timeZoneName,
						exemplarCity = cldr.main([
							"dates/timeZoneNames/zone", timeZone, "exemplarCity"
						]);

					if ( length === 3 ) {
						if ( !exemplarCity ) {
							exemplarCity = cldr.main([
								"dates/timeZoneNames/zone/Etc/Unknown/exemplarCity"
							]);
						}
						timeZoneName = exemplarCity;
					}

					if ( exemplarCity && length === 4 ) {
						timeZoneName = formatMessage(
							cldr.main(
								"dates/timeZoneNames/regionFormat"
							),
							[ exemplarCity ]
						);
					}

					if ( timeZoneName ) {
						timeZoneName = looseMatching( timeZoneName );
						properties.timeZoneName = timeZoneName;
						properties.timeZoneNameRe = new RegExp(
							"^" + regexpEscape( timeZoneName )
						);
					}
				}

				if ( current === "v" ) {
					length = 1;
				}

			/* falls through */
			case "z":
			case "O":
				gmtFormat = cldr.main( "dates/timeZoneNames/gmtFormat" );
				cldr.main( "dates/timeZoneNames/gmtZeroFormat" );
				cldr.main( "dates/timeZoneNames/hourFormat" );
				properties[ "timeZoneNames/gmtZeroFormatRe" ] =
					new RegExp( "^" + regexpEscape( properties[ "timeZoneNames/gmtZeroFormat" ] ) );
				aux = properties[ "timeZoneNames/hourFormat" ];
				properties[ "timeZoneNames/hourFormat" ] = (
					length < 4 ?
						[ dateTimezoneHourFormatHm( aux, "H" ), dateTimezoneHourFormatH( aux ) ] :
						[ dateTimezoneHourFormatHm( aux, "HH" ) ]
				).map(function( hourFormat ) {
					return hourFormatRe(
						hourFormat,
						gmtFormat,
						digitsReSource,
						timeSeparator
					);
				});

			/* falls through */
			case "X":
			case "x":

				// x: hourFormat("+HH[mm];-HH[mm]")
				// xx: hourFormat("+HHmm;-HHmm")
				// xxx: hourFormat("+HH:mm;-HH:mm")
				// xxxx: hourFormat("+HHmm[ss];-HHmm[ss]")
				// xxxxx: hourFormat("+HH:mm[:ss];-HH:mm[:ss]")
				properties.x = [
					[ "+HHmm;-HHmm", "+HH;-HH" ],
					[ "+HHmm;-HHmm" ],
					[ "+HH:mm;-HH:mm" ],
					[ "+HHmmss;-HHmmss", "+HHmm;-HHmm" ],
					[ "+HH:mm:ss;-HH:mm:ss", "+HH:mm;-HH:mm" ]
				][ length - 1 ].map(function( hourFormat ) {
					return hourFormatRe( hourFormat );
				});
		}
	});

	cldr.off( "get", populateProperties );

	return properties;
};

});


<|start_filename|>src/number/formatter-fn.js<|end_filename|>
define([
	"../common/parts/join"
], function( partsJoin ) {

return function( numberToPartsFormatter ) {
	return function numberFormatter( value ) {
		return partsJoin( numberToPartsFormatter( value ));
	};
};

});


<|start_filename|>src/common/parts/push.js<|end_filename|>
define(function() {

/**
 * Pushes part to parts array, concat two consecutive parts of the same type.
 */
return function( parts, type, value ) {

		// Concat two consecutive parts of same type
		if ( parts.length && parts[ parts.length - 1 ].type === type ) {
			parts[ parts.length - 1 ].value += value;
			return;
		}

		parts.push( { type: type, value: value } );
};

});


<|start_filename|>test/functional.js<|end_filename|>
require([
	"qunit",

	// core
	"./functional/core",
	"./functional/core/load",
	"./functional/core/locale",

	// currency
	"./functional/currency/currency-formatter",
	"./functional/currency/currency-to-parts-formatter",
	"./functional/currency/format-currency",
	"./functional/currency/format-currency-to-parts",

	// 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
	"./functional/message/message-formatter",
	"./functional/message/format-message",

	// number
	"./functional/number/number-formatter",
	"./functional/number/number-to-parts-formatter",
	"./functional/number/number-parser",
	"./functional/number/format-number",
	"./functional/number/format-number-to-parts",
	"./functional/number/parse-number",

	// plural
	"./functional/plural/plural",
	"./functional/plural/plural-generator",

	// relative-time
	"./functional/relative-time/format-relative-time",
	"./functional/relative-time/relative-time-formatter",

	// unit
	"./functional/unit/format-unit",
	"./functional/unit/unit-formatter"

], function() {
	QUnit.start();
}, function( error ) {
	QUnit.test( "requirejs load failure", function( assert ) {
		assert.ok( false, "requirejs failed to load: " + QUnit.dump.parse( error ) );
	});
	QUnit.start();
});



<|start_filename|>test/unit/relative-time/format.js<|end_filename|>
define([
	"cldr",
	"src/relative-time/format",
	"src/relative-time/properties",
	"json!cldr-data/main/en/dateFields.json",
	"json!cldr-data/supplemental/likelySubtags.json",

	"cldr/event",
	"cldr/supplemental"
], function( Cldr, format, properties, enDateFields, likelySubtags ) {

var cldr;

Cldr.load( enDateFields );
Cldr.load( likelySubtags );

cldr = new Cldr( "en" );

QUnit.module( "Relative Time Format" );

function mockNumberFormatter(assert, expectedValue) {
	return function( value ) {
		assert.equal( value, expectedValue );
		return expectedValue.toString();
	};
}

function mockPluralGenerator(plural) {
	return function() {
		return plural;
	};
}

QUnit.test( "should format number in past", function( assert ) {
	assert.equal(
		format(
			-7,
			mockNumberFormatter( assert, 7 ),
			mockPluralGenerator( "other" ),
			properties( "month", cldr, {} )
		),
		"7 months ago"
	);
});

QUnit.test( "should format number in future", function( assert ) {
	assert.equal(
		format(
			7,
			mockNumberFormatter( assert, 7 ),
			mockPluralGenerator( "other" ),
			properties( "month", cldr, {} )
		),
		"in 7 months"
	);
});

QUnit.test( "should format using word if possible", function( assert ) {
	function mockNumberFormatter() {
		assert.ok( false, "no need to call number formatter" );
	}
	function mockPluralGenerator() {
		assert.ok( false, "no need to call plural generator" );
	}
	assert.equal(
		format( 1, mockNumberFormatter, mockPluralGenerator, properties( "month", cldr, {} ) ),
		"next month"
	);
});

QUnit.test( "should format numerically if relative-type is absent", function( assert ) {
	assert.equal(
		format(
			1,
			mockNumberFormatter( assert, 1 ),
			mockPluralGenerator( "one" ), {
				"relative-type-0": "this month",
				"relativeTime-type-future": {
					"relativeTimePattern-count-one": "in {0} month",
					"relativeTimePattern-count-other": "in {0} months"
				},
				"relativeTime-type-past": {
					"relativeTimePattern-count-one": "{0} month ago",
					"relativeTimePattern-count-other": "{0} months ago"
				}
			}
		),
		"in 1 month"
	);
});

QUnit.test( "should format 0 as the past if no relative option is available", function( assert ) {
	assert.equal(
		format(
			0,
			mockNumberFormatter( assert, 0 ),
			mockPluralGenerator( "other" ), {
				"relativeTime-type-future": {
					"relativeTimePattern-count-one": "in {0} month",
					"relativeTimePattern-count-other": "in {0} months"
				},
				"relativeTime-type-past": {
					"relativeTimePattern-count-one": "{0} month ago",
					"relativeTimePattern-count-other": "{0} months ago"
				}
			}
		),
		"0 months ago"
	);
});

});


<|start_filename|>test/functional/date/date-to-parts-formatter.js<|end_filename|>
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 )", {
	beforeEach: function() {
		Globalize.load( likelySubtags, {
			main: {
				en: {}
			}
		});
		Globalize.locale( "en" );
	},
	afterEach: util.resetCldrContent
});

QUnit.test( "should validate parameters", function( assert ) {
	util.assertPlainObjectParameter( assert, "options", function( invalidPattern ) {
		return function() {
			Globalize.dateToPartsFormatter( invalidPattern );
		};
	});

	assert.throws(function() {
		Globalize.dateToPartsFormatter({ date: "invalid-stuff" });
	}, /E_INVALID_OPTIONS.*date.*invalid-stuff/ );

	assert.throws(function() {
		Globalize.dateToPartsFormatter({ time: "invalid-stuff" });
	}, /E_INVALID_OPTIONS.*time.*invalid-stuff/ );

	assert.throws(function() {
		Globalize.dateToPartsFormatter({ datetime: "invalid-stuff" });
	}, /E_INVALID_OPTIONS.*datetime.*invalid-stuff/ );

	assert.throws(function() {
		Globalize.dateToPartsFormatter({ skeleton: "invalid-stuff" });
	}, /E_INVALID_OPTIONS.*skeleton.*invalid-stuff/ );
});

QUnit.test( "should validate CLDR content", function( assert ) {
	Globalize.load({
		"main": {
			"en": {
				"dates": {
					"calendars": {
						"gregorian": {
							"dateTimeFormats": {
								"availableFormats": {
									"MMMd": "MMM d"
								}
							}
						}
					}
				}
			}
		}
	});
	util.assertCldrContent( assert, function() {
		Globalize.dateToPartsFormatter({ skeleton: "MMMd" });
	});
});

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"
		}
	]);
});

});


<|start_filename|>src/plural.js<|end_filename|>
define([
	"cldr",
	"make-plural",
	"./common/runtime-bind",
	"./common/validate/cldr",
	"./common/validate/default-locale",
	"./common/validate/parameter-presence",
	"./common/validate/parameter-type/number",
	"./common/validate/parameter-type/plain-object",
	"./common/validate/parameter-type/plural-type",
	"./core",
	"./plural/generator-fn",

	"cldr/event",
	"cldr/supplemental"
], function( _Cldr, MakePlural, runtimeBind, validateCldr, validateDefaultLocale,
	validateParameterPresence, validateParameterTypeNumber,
	validateParameterTypePlainObject, validateParameterTypePluralType, Globalize,
	pluralGeneratorFn ) {

/**
 * .plural( value )
 *
 * @value [Number]
 *
 * Return the corresponding form (zero | one | two | few | many | other) of a
 * value given locale.
 */
Globalize.plural =
Globalize.prototype.plural = function( value, options ) {
	validateParameterPresence( value, "value" );
	validateParameterTypeNumber( value, "value" );
	return this.pluralGenerator( options )( value );
};

/**
 * .pluralGenerator( [options] )
 *
 * Return a plural function (of the form below).
 *
 * fn( value )
 *
 * @value [Number]
 *
 * Return the corresponding form (zero | one | two | few | many | other) of a value given the
 * default/instance locale.
 */
Globalize.pluralGenerator =
Globalize.prototype.pluralGenerator = function( options ) {
	var args, cldr, isOrdinal, plural, returnFn, type;

	validateParameterTypePlainObject( options, "options" );

	options = options || {};
	cldr = this.cldr;

	args = [ options ];
	type = options.type || "cardinal";

	validateParameterTypePluralType( options.type, "options.type" );

	validateDefaultLocale( cldr );

	isOrdinal = type === "ordinal";

	cldr.on( "get", validateCldr );
	try {
		cldr.supplemental([ "plurals-type-" + type, "{language}" ]);
	} finally {
		cldr.off( "get", validateCldr );
	}

	MakePlural.rules = {};
	MakePlural.rules[ type ] = cldr.supplemental( "plurals-type-" + type );

	plural = new MakePlural( cldr.attributes.language, {
		"ordinals": isOrdinal,
		"cardinals": !isOrdinal
	});

	returnFn = pluralGeneratorFn( plural );

	runtimeBind( args, cldr, returnFn, [ plural ] );

	return returnFn;
};

return Globalize;

});


<|start_filename|>test/functional/unit/format-unit.js<|end_filename|>
define( [
	"globalize",
	"json!cldr-data/main/en/numbers.json",
	"json!cldr-data/main/de/numbers.json",
	"json!cldr-data/main/en/units.json",
	"json!cldr-data/main/de/units.json",
	"json!cldr-data/supplemental/likelySubtags.json",
	"json!cldr-data/supplemental/numberingSystems.json",
	"json!cldr-data/supplemental/plurals.json",
	"../../util",

	"globalize/unit"
], function( Globalize, enNumbers, deNumbers, enUnitFields, deUnitFields, likelySubtags,
	numberingSystems, plurals, util ) {

var de, en;

QUnit.module( ".formatUnit( value, unit, options ) - no CLDR", {
	beforeEach: function() {
		Globalize.load( enUnitFields, likelySubtags );
		Globalize.locale( "en" );
	},
	afterEach: util.resetCldrContent
});

QUnit.test( "should validate CLDR content", function( assert ) {
	util.assertCldrContent( assert, function() {
		Globalize.formatUnit( 1, "day", { form: "long" } );
	});
});

QUnit.module( ".formatUnit( value, unit, options )", {
	beforeEach: function() {
		Globalize.load( enNumbers, deNumbers, enUnitFields, deUnitFields, likelySubtags,
			numberingSystems, plurals );
		de = new Globalize( "de" );
		en = new Globalize( "en" );
	},
	afterEach: util.resetCldrContent
});

QUnit.test( "should validate value argument presence", function( assert ) {
	util.assertParameterPresence( assert, "value", function() {
		Globalize.formatUnit();
	});
});

QUnit.test( "should validate value argument is number", function( assert ) {
	util.assertNumberParameter( assert, "value", function( invalidValue ) {
		return function() {
			Globalize.formatUnit( invalidValue, "day" );
		};
	});
});

QUnit.test( "should validate unit argument presence", function( assert ) {
	util.assertParameterPresence( assert, "unit", function() {
		Globalize.formatUnit( 0 );
	});
});

QUnit.test( "should validate unit argument is string", function( assert ) {
	util.assertStringParameter( assert, "unit", function( invalidValue ) {
		return function() {
			Globalize.formatUnit( 0, invalidValue );
		};
	});
});

QUnit.test( "should validate options argument is object", function( assert ) {
	util.assertPlainObjectParameter( assert, "options", function( invalidValue ) {
		return function() {
			Globalize.formatUnit( 1, "day", invalidValue );
		};
	});
});

QUnit.test( "should format units using default form", function( assert ) {
	assert.equal( en.formatUnit( 1, "day" ), "1 day" );
	assert.equal( en.formatUnit( 100, "day" ), "100 days" );

	assert.equal( de.formatUnit( 1, "day" ), "1 Tag" );
	assert.equal( de.formatUnit( 100, "day" ), "100 Tage" );
});

QUnit.test( "should format long form units", function( assert ) {
	assert.equal( en.formatUnit( 1, "day", { form: "long" } ), "1 day" );
	assert.equal( en.formatUnit( 100, "day", { form: "long" } ), "100 days" );

	assert.equal( de.formatUnit( 1, "day", { form: "long" } ), "1 Tag" );
	assert.equal( de.formatUnit( 100, "day", { form: "long" } ), "100 Tage" );
});

QUnit.test( "should format short form units", function( assert ) {
	assert.equal( en.formatUnit( 1, "second", { form: "short" } ), "1 sec" );
	assert.equal( en.formatUnit( 100, "second", { form: "short" } ), "100 sec" );
});

QUnit.test( "should format narrow form units", function( assert ) {
	assert.equal( en.formatUnit( 1, "second", { form: "narrow" } ), "1s" );
	assert.equal( en.formatUnit( 100, "second", { form: "narrow" } ), "100s" );
});

QUnit.test( "should format precomputed compound units", function( assert ) {
	assert.equal( en.formatUnit( 5, "mile-per-hour", { form: "narrow" } ), "5mph" );
});

QUnit.test( "should format computed compound units", function( assert ) {
	assert.equal( en.formatUnit( 5, "mile-per-second", { form: "narrow" } ), "5mi/s" );
});

QUnit.test( "should format precomputed compound units with '/'", function( assert ) {
	assert.equal( en.formatUnit( 5, "mile/hour", { form: "narrow" } ), "5mph" );
});

QUnit.test( "should format computed compound units with '/'", function( assert ) {
	assert.equal( en.formatUnit( 5, "mile/second", { form: "narrow" } ), "5mi/s" );
});

QUnit.test( "should format numbers correctly", function( assert ) {
	assert.equal( en.formatUnit( 55000, "mile/hour", { form: "short" } ), "55,000 mph" );
	assert.equal( de.formatUnit( 55000, "mile/hour", { form: "short" } ), "55.000 mi/h" );
});

QUnit.test( "should accept custom number formatters", function( assert ) {
	var enCustomFormatter = en.numberFormatter({ useGrouping: false }),
		deCustomFormatter = de.numberFormatter({ useGrouping: false });

	assert.equal( en.formatUnit( 55000, "mile/hour", {
		form: "short",
		numberFormatter: enCustomFormatter
	}), "55000 mph" );
	assert.equal( de.formatUnit( 55000, "mile/hour", {
		form: "short",
		numberFormatter: deCustomFormatter
	}), "55000 mi/h" );
});

});


<|start_filename|>src/common/parts/join.js<|end_filename|>
define(function() {

/**
 * Returns joined parts values.
 */
return function( parts ) {
	return parts.map( function( part ) {
		return part.value;
	}).join( "" );
};

});


<|start_filename|>test/functional/plural/plural.js<|end_filename|>
define([
	"globalize",
	"json!cldr-data/supplemental/likelySubtags.json",
	"json!cldr-data/supplemental/plurals.json",
	"json!cldr-data/supplemental/ordinals.json",
	"../../util",

	"globalize/plural"
], function( Globalize, likelySubtags, plurals, ordinals, util ) {

function extraSetup() {
	Globalize.load( plurals );
	Globalize.load( ordinals );

	// Temporary fix due to CLDR v26 regression about pt_BR plural
	// http://unicode.org/cldr/trac/ticket/7178
	Globalize.load({
		"supplemental": {
			"plurals-type-cardinal": {
				pt: {
					"pluralRule-count-one": "i = 0,1",
					"pluralRule-count-other": ""
				}
			}
		}
	});

}

QUnit.module( ".plural( value )", {
	beforeEach: function() {
		Globalize.load( likelySubtags, {
			main: {
				en: {}
			}
		});
		Globalize.locale( "en" );
	},
	afterEach: util.resetCldrContent
});

QUnit.test( "should validate parameters", function( assert ) {
	util.assertParameterPresence( assert, "value", function() {
		Globalize.plural();
	});

	util.assertNumberParameter( assert, "value", function( invalidValue ) {
		return function() {
			Globalize.plural( invalidValue );
		};
	});

	util.assertPlainObjectParameter( assert, "options", function( invalidOptions ) {
		return function() {
			Globalize.plural( 0, invalidOptions );
		};
	});
});

QUnit.test( "should validate CLDR content", function( assert ) {
	util.assertCldrContent( assert, function() {
		Globalize.plural( 1 );
	});
});

QUnit.test( "should un-register event listener", function( assert ) {
	try {
		Globalize.plural( 1 );
	} catch ( error ) {
		assert.equal( Globalize.cldr.ee.getListeners( "get" ).length, 0 );
	}
});

QUnit.test( "should return plural form", function( assert ) {
	extraSetup();
	assert.equal( Globalize.plural( 0 ), "other" );
	assert.equal( Globalize.plural( 0.14 ), "other" );

	assert.equal( Globalize( "en" ).plural( 0 ), "other" );
	assert.equal( Globalize( "en" ).plural( 1 ), "one" );
	assert.equal( Globalize( "en" ).plural( 2 ), "other" );
	assert.equal( Globalize( "en" ).plural( 1412 ), "other" );
	assert.equal( Globalize( "en" ).plural( 0.14 ), "other" );
	assert.equal( Globalize( "en" ).plural( 3.14 ), "other" );

	assert.equal( Globalize( "en" ).plural( 0, { type: "ordinal" } ), "other" );
	assert.equal( Globalize( "en" ).plural( 1, { type: "ordinal" } ), "one" );
	assert.equal( Globalize( "en" ).plural( 2, { type: "ordinal" } ), "two" );
	assert.equal( Globalize( "en" ).plural( 3, { type: "ordinal" } ), "few" );
	assert.equal( Globalize( "en" ).plural( 1412, { type: "ordinal" } ), "other" );
	assert.equal( Globalize( "en" ).plural( 0.14, { type: "ordinal" } ), "other" );
	assert.equal( Globalize( "en" ).plural( 3.14, { type: "ordinal" } ), "other" );

	assert.equal( Globalize( "ar" ).plural( 0 ), "zero" );
	assert.equal( Globalize( "ar" ).plural( 1 ), "one" );
	assert.equal( Globalize( "ar" ).plural( 2 ), "two" );
	assert.equal( Globalize( "ar" ).plural( 3 ), "few" );
	assert.equal( Globalize( "ar" ).plural( 6 ), "few" );
	assert.equal( Globalize( "ar" ).plural( 9 ), "few" );
	assert.equal( Globalize( "ar" ).plural( 10 ), "few" );
	assert.equal( Globalize( "ar" ).plural( 11 ), "many" );
	assert.equal( Globalize( "ar" ).plural( 15 ), "many" );
	assert.equal( Globalize( "ar" ).plural( 21 ), "many" );
	assert.equal( Globalize( "ar" ).plural( 70 ), "many" );
	assert.equal( Globalize( "ar" ).plural( 99 ), "many" );
	assert.equal( Globalize( "ar" ).plural( 100 ), "other" );
	assert.equal( Globalize( "ar" ).plural( 101 ), "other" );
	assert.equal( Globalize( "ar" ).plural( 102 ), "other" );
	assert.equal( Globalize( "ar" ).plural( 103 ), "few" );
	assert.equal( Globalize( "ar" ).plural( 111 ), "many" );
	assert.equal( Globalize( "ar" ).plural( 199 ), "many" );
	assert.equal( Globalize( "ar" ).plural( 3.14 ), "other" );

	[ 0, 1, 2, 3, 9, 10, 11, 99, 100, 101, 3.14 ].forEach(function( value ) {
		assert.equal( Globalize( "ar" ).plural( value, { type: "ordinal" } ), "other" );
	});

	assert.equal( Globalize( "ja" ).plural( 0 ), "other" );
	assert.equal( Globalize( "ja" ).plural( 1 ), "other" );
	assert.equal( Globalize( "ja" ).plural( 2 ), "other" );
	assert.equal( Globalize( "ja" ).plural( 3.14 ), "other" );

	assert.equal( Globalize( "pt" ).plural( 0 ), "one" );
	assert.equal( Globalize( "pt" ).plural( 1 ), "one" );
	assert.equal( Globalize( "pt" ).plural( 2 ), "other" );
	assert.equal( Globalize( "pt" ).plural( 0.1 ), "one" );
	assert.equal( Globalize( "pt" ).plural( 3.14 ), "other" );

	assert.equal( Globalize( "ru" ).plural( 0 ), "many" );
	assert.equal( Globalize( "ru" ).plural( 1 ), "one" );
	assert.equal( Globalize( "ru" ).plural( 2 ), "few" );
	assert.equal( Globalize( "ru" ).plural( 3 ), "few" );
	assert.equal( Globalize( "ru" ).plural( 4 ), "few" );
	assert.equal( Globalize( "ru" ).plural( 5 ), "many" );
	assert.equal( Globalize( "ru" ).plural( 6 ), "many" );
	assert.equal( Globalize( "ru" ).plural( 9 ), "many" );
	assert.equal( Globalize( "ru" ).plural( 11 ), "many" );
	assert.equal( Globalize( "ru" ).plural( 12 ), "many" );
	assert.equal( Globalize( "ru" ).plural( 19 ), "many" );
	assert.equal( Globalize( "ru" ).plural( 21 ), "one" );
	assert.equal( Globalize( "ru" ).plural( 22 ), "few" );
	assert.equal( Globalize( "ru" ).plural( 29 ), "many" );
	assert.equal( Globalize( "ru" ).plural( 3.14 ), "other" );

	assert.equal( Globalize( "zh" ).plural( 0 ), "other" );
	assert.equal( Globalize( "zh" ).plural( 1 ), "other" );
	assert.equal( Globalize( "zh" ).plural( 2 ), "other" );
	assert.equal( Globalize( "zh" ).plural( 3.14 ), "other" );
});

});


<|start_filename|>test/unit/date/format-properties.js<|end_filename|>
define([
	"cldr",
	"src/date/format-properties",
	"json!cldr-data/main/en/ca-gregorian.json",
	"json!cldr-data/main/en/timeZoneNames.json",
	"json!cldr-data/main/en-GB/ca-gregorian.json",
	"json!cldr-data/main/en-GB/timeZoneNames.json",
	"json!cldr-data/supplemental/likelySubtags.json",
	"json!cldr-data/supplemental/timeData.json",
	"json!cldr-data/supplemental/weekData.json",
	"json!cldr-data/supplemental/metaZones.json",
	"json!iana-tz-data.json",

	"cldr/event",
	"cldr/supplemental"
], function( Cldr, properties, enCaGregorian, enTimeZoneNames, enGbCaGregorian, enGbTimeZoneNames,
	likelySubtags, timeData, weekData, metaZones, ianaTimezoneData ) {

var cldr;

Cldr.load(
	enCaGregorian,
	enTimeZoneNames,
	enGbCaGregorian,
	enGbTimeZoneNames,
	likelySubtags,
	timeData,
	weekData,
	metaZones
);

// Needed for globalizeDate.
Cldr.load({
	"globalize-iana": ianaTimezoneData
});

cldr = new Cldr( "en" );

QUnit.module( "Date Format Properties" );

/**
 *  Era
 */

QUnit.test( "should return eras property for (G|GG|GGG|GGGG|GGGGG)", function( assert ) {
	[ "G", "GG", "GGG", "GGGG", "GGGGG" ].forEach(function( pattern ) {
		assert.ok( "eras" in properties( pattern, cldr ) );
	});
});

/**
 *  Year
 */

QUnit.test( "should return appropriate properties for year in \"week of year\" (Y+)",
		function( assert ) {
	[ "Y", "YY", "YYY", "YYYYY" ].forEach(function( pattern ) {
		assert.ok( "firstDay" in properties( pattern, cldr ) );
		assert.ok( "minDays" in properties( pattern, cldr ) );
	});
});

/**
 *  Quarter
 */

QUnit.test( "should return quarters properties for quarter (QQQ|QQQQ|qqq|qqqq)",
		function( assert ) {
	[ "QQQ", "qqq", "QQQQ", "qqqq" ].forEach(function( pattern ) {
		var character = pattern.charAt( 0 ),
			length = pattern.length;
		assert.ok( "quarters" in properties( pattern, cldr ) );
		assert.ok( character in properties( pattern, cldr ).quarters );
		assert.ok( length in properties( pattern, cldr ).quarters[ character ] );
	});
});

/**
 *  Month
 */

QUnit.test( "should return months properties for month (MMM|MMMM|MMMMM|LLL|LLLL|LLLLL)",
		function( assert ) {
	[ "MMM", "LLL", "MMMM", "LLLL", "MMMMM", "LLLLL" ].forEach(function( pattern ) {
		var character = pattern.charAt( 0 ),
			length = pattern.length;
		assert.ok( "months" in properties( pattern, cldr ) );
		assert.ok( character in properties( pattern, cldr ).months );
		assert.ok( length in properties( pattern, cldr ).months[ character ] );
	});
});

/**
 *  Week
 */

QUnit.test( "should return appropriate properties for week of year (w) or week of month (W)",
		function( assert ) {
	[ "w", "W" ].forEach(function( pattern ) {
		assert.ok( "firstDay" in properties( pattern, cldr ) );
		assert.ok( "minDays" in properties( pattern, cldr ) );
	});
});

/**
 *  Week day
 */

QUnit.test( "should return firstDay property for day of week (e|ee|c|cc)", function( assert ) {
	[ "e", "c", "ee", "cc" ].forEach(function( pattern ) {
		assert.ok( "firstDay" in properties( pattern, cldr ) );
	});
});

QUnit.test( "should return days properties for day of week (eee..eeeeee|ccc..cccccc)",
		function( assert ) {
	[ "eee", "ccc", "eeee", "cccc", "eeeee", "ccccc", "eeeeee", "cccccc" ].forEach(
			function( pattern ) {
		var character = pattern.charAt( 0 ),
			length = pattern.length;
		assert.ok( "days" in properties( pattern, cldr ) );
		assert.ok( character in properties( pattern, cldr ).days );
		assert.ok( length in properties( pattern, cldr ).days[ character ] );
	});
});

/**
 *  Period
 */

QUnit.test( "should return dayPeriods property for period (a)", function( assert ) {
	assert.ok( "dayPeriods" in properties( "a", cldr ) );
	assert.equal( Object.keys(properties( "a", cldr ).dayPeriods).length, 2 );
});

/**
 *  Zone
 */

QUnit.test( "should return properties for timezone (z)", function( assert ) {
	var timeZone,
		enGb = new Cldr( "en-GB" );

	timeZone = "America/Los_Angeles";
	[ "z", "zz", "zzz" ].forEach(function( pattern ) {
		assert.equal( properties( pattern, cldr, timeZone ).standardTzName, "PST" );
		assert.equal( properties( pattern, cldr, timeZone ).daylightTzName, "PDT" );
	});
	[ "zzzz" ].forEach(function( pattern ) {
		assert.equal( properties( pattern, cldr, timeZone ).standardTzName, "Pacific Standard Time" );
		assert.equal( properties( pattern, cldr, timeZone ).daylightTzName, "Pacific Daylight Time" );
	});

	// Test for ??:
	timeZone = "Asia/Dubai";
	[ "z", "zz", "zzz" ].forEach(function( pattern ) {
		var formatProperties = properties( pattern, cldr, timeZone );
		assert.ok( !( "standardTzName" in formatProperties ) );
		assert.ok( !( "daylightTzName" in formatProperties ) );
		assert.ok( "gmtFormat" in formatProperties );
		assert.ok( "gmtZeroFormat" in formatProperties );
		assert.ok( "hourFormat" in formatProperties );
	});
	[ "zzzz" ].forEach(function( pattern ) {
		var formatProperties = properties( pattern, cldr, timeZone );
		assert.equal( formatProperties.standardTzName, "Gulf Standard Time" );
		assert.ok( !( "daylightTzName" in formatProperties ) );
		assert.ok( "gmtFormat" in formatProperties );
		assert.ok( "gmtZeroFormat" in formatProperties );
		assert.ok( "hourFormat" in formatProperties );
	});

	// Test for two things:
	// - daylightTzName using the zone data (primary), not the metazone (secondary try);
	// - standardTzName being undefined, therefore requiring the O fallback properties;
	timeZone = "Europe/London";
	[ "z", "zz", "zzz" ].forEach(function( pattern ) {
		var formatProperties = properties( pattern, enGb, timeZone );
		assert.ok( !( "standardTzName" in formatProperties ) );
		assert.equal( formatProperties.daylightTzName, "BST" );
		assert.ok( "gmtFormat" in formatProperties );
		assert.ok( "gmtZeroFormat" in formatProperties );
		assert.ok( "hourFormat" in formatProperties );
	});
	[ "zzzz" ].forEach(function( pattern ) {
		var formatProperties = properties( pattern, enGb, timeZone );
		assert.ok( !( "standardTzName" in formatProperties ) );
		assert.equal( formatProperties.daylightTzName, "British Summer Time" );
		assert.ok( "gmtFormat" in formatProperties );
		assert.ok( "gmtZeroFormat" in formatProperties );
		assert.ok( "hourFormat" in formatProperties );
	});
});

QUnit.test( "should return properties for timezone (v)", function( assert ) {
	assert.equal( properties( "v", cldr, "America/Los_Angeles" ).genericTzName, "PT" );
	assert.equal( properties( "vvvv", cldr, "America/Los_Angeles" ).genericTzName, "Pacific Time" );
});

QUnit.test( "should return properties for timezone (V)", function( assert ) {
	assert.equal( properties( "VV", cldr, "America/Los_Angeles" ).timeZoneName, "America/Los_Angeles" );
	assert.equal( properties( "VVV", cldr, "America/Los_Angeles" ).timeZoneName, "Los Angeles" );
	assert.equal( properties( "VVVV", cldr, "America/Los_Angeles" ).timeZoneName, "Los Angeles Time" );
	assert.equal( properties( "VVVV", cldr, "America/Sao_Paulo" ).timeZoneName, "Sao Paulo Time" );
});

QUnit.test( "should return properties.timeZoneData when using timeZone argument", function( assert ) {
	var formatProperties = properties( "d", cldr, "America/Los_Angeles" );
	assert.ok( "timeZoneData" in formatProperties );
	assert.ok( "offsets" in formatProperties.timeZoneData() );
	assert.ok( "untils" in formatProperties.timeZoneData() );
	assert.ok( "isdsts" in formatProperties.timeZoneData() );
});

});


<|start_filename|>test/functional/plural/plural-generator.js<|end_filename|>
define([
	"globalize",
	"json!cldr-data/supplemental/likelySubtags.json",
	"json!cldr-data/supplemental/plurals.json",
	"json!cldr-data/supplemental/ordinals.json",
	"../../util",

	"globalize/plural"
], function( Globalize, likelySubtags, plurals, ordinals, util ) {

QUnit.module( ".pluralGenerator()", {
	beforeEach: function() {
		Globalize.load( likelySubtags, plurals, ordinals, {
			main: {
				en: {}
			}
		});
		Globalize.locale( "en" );
	},
	afterEach: util.resetCldrContent
});

});


<|start_filename|>test/unit/core.js<|end_filename|>
define([
	"cldr",
	"src/core",
	"json!cldr-data/supplemental/likelySubtags.json",

	"cldr/event"
], function( Cldr, Globalize, likelySubtags ) {

Cldr.load( likelySubtags, {
	supplemental: {
		likelySubtags: {

			// The below are fictitious locales for the purpose of this test.
			// Note to self: don't use zz, Zzzz or ZZ. These are reserved subtags.
			"xx": "xx-Xxxx-XX",
			"yy": "yy-Xxxx-YY"
		}
	},
	main: {
		"de-CH": {
			"test-bundle": "de-CH"
		},
		en: {
			"test-bundle": "en"
		},
		"en-GB": {
			"test-bundle": "en-GB"
		},
		"pa-Arab": {
			"test-bundle": "pa-Arab"
		},
		"sr-Cyrl": {
			"test-bundle": "sr-Cyrl"
		},
		"sr-Latn": {
			"test-bundle": "sr-Latn"
		},
		"uz-Arab": {
			"test-bundle": "uz-Arab"
		},
		"xx": {
			"test-bundle": "xx"
		},
		"yy-YY": {
			"test-bundle": "yy-YY"
		},
		"zh": {
			"test-bundle": "zh"
		},
		"zh-Hant": {
			"test-bundle": "zh-Hant"
		}
	}
});

QUnit.module( "Globalize (constructor)" );

QUnit.test( "should allow String locale", function( assert ) {
	var en = new Globalize( "en" );
	assert.ok( en instanceof Globalize );
	assert.equal( en.cldr.locale, "en" );
});

QUnit.test( "should allow Cldr instance to be passed as locale", function( assert ) {
	var en = Globalize( new Cldr( "en" ) );
	assert.ok( en instanceof Globalize );
	assert.equal( en.cldr.locale, "en" );
});

QUnit.test( "should lookup bundle", function( assert ) {
	assert.equal( Globalize( "de-Latn-CH" ).cldr.main( "test-bundle" ), "de-CH" );
	assert.equal( Globalize( "en" ).cldr.main( "test-bundle" ), "en" );
	assert.equal( Globalize( "en-GB" ).cldr.main( "test-bundle" ), "en-GB" );
	assert.equal( Globalize( "en-Latn-GB" ).cldr.main( "test-bundle" ), "en-GB" );
	assert.equal( Globalize( "pa-Arab" ).cldr.main( "test-bundle" ), "pa-Arab" );
	assert.equal( Globalize( "pa-PK" ).cldr.main( "test-bundle" ), "pa-Arab" );
	assert.equal( Globalize( "sr" ).cldr.main( "test-bundle" ), "sr-Cyrl" );
	assert.equal( Globalize( "sr-Cyrl" ).cldr.main( "test-bundle" ), "sr-Cyrl" );
	assert.equal( Globalize( "sr-Latn" ).cldr.main( "test-bundle" ), "sr-Latn" );
	assert.equal( Globalize( "sr-Latn-RS" ).cldr.main( "test-bundle" ), "sr-Latn" );
	assert.equal( Globalize( "sr-RS" ).cldr.main( "test-bundle" ), "sr-Cyrl" );
	assert.equal( Globalize( "uz-AF" ).cldr.main( "test-bundle" ), "uz-Arab" );
	assert.equal( Globalize( "uz-Arab" ).cldr.main( "test-bundle" ), "uz-Arab" );
	assert.equal( Globalize( "zh" ).cldr.main( "test-bundle" ), "zh" );
	assert.equal( Globalize( "zh-CN" ).cldr.main( "test-bundle" ), "zh" );
	assert.equal( Globalize( "zh-Hans" ).cldr.main( "test-bundle" ), "zh" );
	assert.equal( Globalize( "zh-Hant" ).cldr.main( "test-bundle" ), "zh-Hant" );
	assert.equal( Globalize( "zh-TW" ).cldr.main( "test-bundle" ), "zh-Hant" );

	// Simulate loading `en` main dataset. Both instances `en` or `en-US` will use
	// `en` bundle.
	assert.equal( Globalize( "xx" ).cldr.main( "test-bundle" ), "xx" );
	assert.equal( Globalize( "xx-XX" ).cldr.main( "test-bundle" ), "xx" );

	// Simulate loading `en-US` main dataset. Both instances `en` or `en-US` will use
	// `en-US` bundle.
	assert.equal( Globalize( "yy" ).cldr.main( "test-bundle" ), "yy-YY" );
	assert.equal( Globalize( "yy-YY" ).cldr.main( "test-bundle" ), "yy-YY" );

	assert.throws(function() {
		Globalize( "xx-XZ" ).cldr.main( "test-bundle" );
	}, function E_MISSING_BUNDLE( error ) {
		return error.code === "E_MISSING_BUNDLE" && error.locale === "xx-XZ";
	});
});

});


<|start_filename|>src/date/formatter-fn.js<|end_filename|>
define([
	"../common/parts/join"
], function( partsJoin ) {

return function( dateToPartsFormatter ) {
	return function dateFormatter( value ) {
		return partsJoin( dateToPartsFormatter( value ));
	};
};

});
