| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581 | 
							- /*!
 
-  * Globalize
 
-  *
 
-  * http://github.com/jquery/globalize
 
-  *
 
-  * Copyright Software Freedom Conservancy, Inc.
 
-  * Dual licensed under the MIT or GPL Version 2 licenses.
 
-  * http://jquery.org/license
 
-  */
 
- (function( window, undefined ) {
 
- var Globalize,
 
- 	// private variables
 
- 	regexHex,
 
- 	regexInfinity,
 
- 	regexParseFloat,
 
- 	regexTrim,
 
- 	// private JavaScript utility functions
 
- 	arrayIndexOf,
 
- 	endsWith,
 
- 	extend,
 
- 	isArray,
 
- 	isFunction,
 
- 	isObject,
 
- 	startsWith,
 
- 	trim,
 
- 	truncate,
 
- 	zeroPad,
 
- 	// private Globalization utility functions
 
- 	appendPreOrPostMatch,
 
- 	expandFormat,
 
- 	formatDate,
 
- 	formatNumber,
 
- 	getTokenRegExp,
 
- 	getEra,
 
- 	getEraYear,
 
- 	parseExact,
 
- 	parseNegativePattern;
 
- // Global variable (Globalize) or CommonJS module (globalize)
 
- Globalize = function( cultureSelector ) {
 
- 	return new Globalize.prototype.init( cultureSelector );
 
- };
 
- if ( typeof require !== "undefined" &&
 
- 	typeof exports !== "undefined" &&
 
- 	typeof module !== "undefined" ) {
 
- 	// Assume CommonJS
 
- 	module.exports = Globalize;
 
- } else {
 
- 	// Export as global variable
 
- 	window.Globalize = Globalize;
 
- }
 
- Globalize.cultures = {};
 
- Globalize.prototype = {
 
- 	constructor: Globalize,
 
- 	init: function( cultureSelector ) {
 
- 		this.cultures = Globalize.cultures;
 
- 		this.cultureSelector = cultureSelector;
 
- 		return this;
 
- 	}
 
- };
 
- Globalize.prototype.init.prototype = Globalize.prototype;
 
- // 1. When defining a culture, all fields are required except the ones stated as optional.
 
- // 2. Each culture should have a ".calendars" object with at least one calendar named "standard"
 
- //    which serves as the default calendar in use by that culture.
 
- // 3. Each culture should have a ".calendar" object which is the current calendar being used,
 
- //    it may be dynamically changed at any time to one of the calendars in ".calendars".
 
- Globalize.cultures[ "default" ] = {
 
- 	// A unique name for the culture in the form <language code>-<country/region code>
 
- 	name: "en",
 
- 	// the name of the culture in the english language
 
- 	englishName: "English",
 
- 	// the name of the culture in its own language
 
- 	nativeName: "English",
 
- 	// whether the culture uses right-to-left text
 
- 	isRTL: false,
 
- 	// "language" is used for so-called "specific" cultures.
 
- 	// For example, the culture "es-CL" means "Spanish, in Chili".
 
- 	// It represents the Spanish-speaking culture as it is in Chili,
 
- 	// which might have different formatting rules or even translations
 
- 	// than Spanish in Spain. A "neutral" culture is one that is not
 
- 	// specific to a region. For example, the culture "es" is the generic
 
- 	// Spanish culture, which may be a more generalized version of the language
 
- 	// that may or may not be what a specific culture expects.
 
- 	// For a specific culture like "es-CL", the "language" field refers to the
 
- 	// neutral, generic culture information for the language it is using.
 
- 	// This is not always a simple matter of the string before the dash.
 
- 	// For example, the "zh-Hans" culture is netural (Simplified Chinese).
 
- 	// And the "zh-SG" culture is Simplified Chinese in Singapore, whose lanugage
 
- 	// field is "zh-CHS", not "zh".
 
- 	// This field should be used to navigate from a specific culture to it's
 
- 	// more general, neutral culture. If a culture is already as general as it
 
- 	// can get, the language may refer to itself.
 
- 	language: "en",
 
- 	// numberFormat defines general number formatting rules, like the digits in
 
- 	// each grouping, the group separator, and how negative numbers are displayed.
 
- 	numberFormat: {
 
- 		// [negativePattern]
 
- 		// Note, numberFormat.pattern has no "positivePattern" unlike percent and currency,
 
- 		// but is still defined as an array for consistency with them.
 
- 		//   negativePattern: one of "(n)|-n|- n|n-|n -"
 
- 		pattern: [ "-n" ],
 
- 		// number of decimal places normally shown
 
- 		decimals: 2,
 
- 		// string that separates number groups, as in 1,000,000
 
- 		",": ",",
 
- 		// string that separates a number from the fractional portion, as in 1.99
 
- 		".": ".",
 
- 		// array of numbers indicating the size of each number group.
 
- 		// TODO: more detailed description and example
 
- 		groupSizes: [ 3 ],
 
- 		// symbol used for positive numbers
 
- 		"+": "+",
 
- 		// symbol used for negative numbers
 
- 		"-": "-",
 
- 		// symbol used for NaN (Not-A-Number)
 
- 		"NaN": "NaN",
 
- 		// symbol used for Negative Infinity
 
- 		negativeInfinity: "-Infinity",
 
- 		// symbol used for Positive Infinity
 
- 		positiveInfinity: "Infinity",
 
- 		percent: {
 
- 			// [negativePattern, positivePattern]
 
- 			//   negativePattern: one of "-n %|-n%|-%n|%-n|%n-|n-%|n%-|-% n|n %-|% n-|% -n|n- %"
 
- 			//   positivePattern: one of "n %|n%|%n|% n"
 
- 			pattern: [ "-n %", "n %" ],
 
- 			// number of decimal places normally shown
 
- 			decimals: 2,
 
- 			// array of numbers indicating the size of each number group.
 
- 			// TODO: more detailed description and example
 
- 			groupSizes: [ 3 ],
 
- 			// string that separates number groups, as in 1,000,000
 
- 			",": ",",
 
- 			// string that separates a number from the fractional portion, as in 1.99
 
- 			".": ".",
 
- 			// symbol used to represent a percentage
 
- 			symbol: "%"
 
- 		},
 
- 		currency: {
 
- 			// [negativePattern, positivePattern]
 
- 			//   negativePattern: one of "($n)|-$n|$-n|$n-|(n$)|-n$|n-$|n$-|-n $|-$ n|n $-|$ n-|$ -n|n- $|($ n)|(n $)"
 
- 			//   positivePattern: one of "$n|n$|$ n|n $"
 
- 			pattern: [ "($n)", "$n" ],
 
- 			// number of decimal places normally shown
 
- 			decimals: 2,
 
- 			// array of numbers indicating the size of each number group.
 
- 			// TODO: more detailed description and example
 
- 			groupSizes: [ 3 ],
 
- 			// string that separates number groups, as in 1,000,000
 
- 			",": ",",
 
- 			// string that separates a number from the fractional portion, as in 1.99
 
- 			".": ".",
 
- 			// symbol used to represent currency
 
- 			symbol: "$"
 
- 		}
 
- 	},
 
- 	// calendars defines all the possible calendars used by this culture.
 
- 	// There should be at least one defined with name "standard", and is the default
 
- 	// calendar used by the culture.
 
- 	// A calendar contains information about how dates are formatted, information about
 
- 	// the calendar's eras, a standard set of the date formats,
 
- 	// translations for day and month names, and if the calendar is not based on the Gregorian
 
- 	// calendar, conversion functions to and from the Gregorian calendar.
 
- 	calendars: {
 
- 		standard: {
 
- 			// name that identifies the type of calendar this is
 
- 			name: "Gregorian_USEnglish",
 
- 			// separator of parts of a date (e.g. "/" in 11/05/1955)
 
- 			"/": "/",
 
- 			// separator of parts of a time (e.g. ":" in 05:44 PM)
 
- 			":": ":",
 
- 			// the first day of the week (0 = Sunday, 1 = Monday, etc)
 
- 			firstDay: 0,
 
- 			days: {
 
- 				// full day names
 
- 				names: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
 
- 				// abbreviated day names
 
- 				namesAbbr: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
 
- 				// shortest day names
 
- 				namesShort: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ]
 
- 			},
 
- 			months: {
 
- 				// full month names (13 months for lunar calendards -- 13th month should be "" if not lunar)
 
- 				names: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", "" ],
 
- 				// abbreviated month names
 
- 				namesAbbr: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "" ]
 
- 			},
 
- 			// AM and PM designators in one of these forms:
 
- 			// The usual view, and the upper and lower case versions
 
- 			//   [ standard, lowercase, uppercase ]
 
- 			// The culture does not use AM or PM (likely all standard date formats use 24 hour time)
 
- 			//   null
 
- 			AM: [ "AM", "am", "AM" ],
 
- 			PM: [ "PM", "pm", "PM" ],
 
- 			eras: [
 
- 				// eras in reverse chronological order.
 
- 				// name: the name of the era in this culture (e.g. A.D., C.E.)
 
- 				// start: when the era starts in ticks (gregorian, gmt), null if it is the earliest supported era.
 
- 				// offset: offset in years from gregorian calendar
 
- 				{
 
- 					"name": "A.D.",
 
- 					"start": null,
 
- 					"offset": 0
 
- 				}
 
- 			],
 
- 			// when a two digit year is given, it will never be parsed as a four digit
 
- 			// year greater than this year (in the appropriate era for the culture)
 
- 			// Set it as a full year (e.g. 2029) or use an offset format starting from
 
- 			// the current year: "+19" would correspond to 2029 if the current year 2010.
 
- 			twoDigitYearMax: 2029,
 
- 			// set of predefined date and time patterns used by the culture
 
- 			// these represent the format someone in this culture would expect
 
- 			// to see given the portions of the date that are shown.
 
- 			patterns: {
 
- 				// short date pattern
 
- 				d: "M/d/yyyy",
 
- 				// long date pattern
 
- 				D: "dddd, MMMM dd, yyyy",
 
- 				// short time pattern
 
- 				t: "h:mm tt",
 
- 				// long time pattern
 
- 				T: "h:mm:ss tt",
 
- 				// long date, short time pattern
 
- 				f: "dddd, MMMM dd, yyyy h:mm tt",
 
- 				// long date, long time pattern
 
- 				F: "dddd, MMMM dd, yyyy h:mm:ss tt",
 
- 				// month/day pattern
 
- 				M: "MMMM dd",
 
- 				// month/year pattern
 
- 				Y: "yyyy MMMM",
 
- 				// S is a sortable format that does not vary by culture
 
- 				S: "yyyy\u0027-\u0027MM\u0027-\u0027dd\u0027T\u0027HH\u0027:\u0027mm\u0027:\u0027ss"
 
- 			}
 
- 			// optional fields for each calendar:
 
- 			/*
 
- 			monthsGenitive:
 
- 				Same as months but used when the day preceeds the month.
 
- 				Omit if the culture has no genitive distinction in month names.
 
- 				For an explaination of genitive months, see http://blogs.msdn.com/michkap/archive/2004/12/25/332259.aspx
 
- 			convert:
 
- 				Allows for the support of non-gregorian based calendars. This convert object is used to
 
- 				to convert a date to and from a gregorian calendar date to handle parsing and formatting.
 
- 				The two functions:
 
- 					fromGregorian( date )
 
- 						Given the date as a parameter, return an array with parts [ year, month, day ]
 
- 						corresponding to the non-gregorian based year, month, and day for the calendar.
 
- 					toGregorian( year, month, day )
 
- 						Given the non-gregorian year, month, and day, return a new Date() object
 
- 						set to the corresponding date in the gregorian calendar.
 
- 			*/
 
- 		}
 
- 	},
 
- 	// For localized strings
 
- 	messages: {}
 
- };
 
- Globalize.cultures[ "default" ].calendar = Globalize.cultures[ "default" ].calendars.standard;
 
- Globalize.cultures.en = Globalize.cultures[ "default" ];
 
- Globalize.cultureSelector = "en";
 
- //
 
- // private variables
 
- //
 
- regexHex = /^0x[a-f0-9]+$/i;
 
- regexInfinity = /^[+\-]?infinity$/i;
 
- regexParseFloat = /^[+\-]?\d*\.?\d*(e[+\-]?\d+)?$/;
 
- regexTrim = /^\s+|\s+$/g;
 
- //
 
- // private JavaScript utility functions
 
- //
 
- arrayIndexOf = function( array, item ) {
 
- 	if ( array.indexOf ) {
 
- 		return array.indexOf( item );
 
- 	}
 
- 	for ( var i = 0, length = array.length; i < length; i++ ) {
 
- 		if ( array[i] === item ) {
 
- 			return i;
 
- 		}
 
- 	}
 
- 	return -1;
 
- };
 
- endsWith = function( value, pattern ) {
 
- 	return value.substr( value.length - pattern.length ) === pattern;
 
- };
 
- extend = function() {
 
- 	var options, name, src, copy, copyIsArray, clone,
 
- 		target = arguments[0] || {},
 
- 		i = 1,
 
- 		length = arguments.length,
 
- 		deep = false;
 
- 	// Handle a deep copy situation
 
- 	if ( typeof target === "boolean" ) {
 
- 		deep = target;
 
- 		target = arguments[1] || {};
 
- 		// skip the boolean and the target
 
- 		i = 2;
 
- 	}
 
- 	// Handle case when target is a string or something (possible in deep copy)
 
- 	if ( typeof target !== "object" && !isFunction(target) ) {
 
- 		target = {};
 
- 	}
 
- 	for ( ; i < length; i++ ) {
 
- 		// Only deal with non-null/undefined values
 
- 		if ( (options = arguments[ i ]) != null ) {
 
- 			// Extend the base object
 
- 			for ( name in options ) {
 
- 				src = target[ name ];
 
- 				copy = options[ name ];
 
- 				// Prevent never-ending loop
 
- 				if ( target === copy ) {
 
- 					continue;
 
- 				}
 
- 				// Recurse if we're merging plain objects or arrays
 
- 				if ( deep && copy && ( isObject(copy) || (copyIsArray = isArray(copy)) ) ) {
 
- 					if ( copyIsArray ) {
 
- 						copyIsArray = false;
 
- 						clone = src && isArray(src) ? src : [];
 
- 					} else {
 
- 						clone = src && isObject(src) ? src : {};
 
- 					}
 
- 					// Never move original objects, clone them
 
- 					target[ name ] = extend( deep, clone, copy );
 
- 				// Don't bring in undefined values
 
- 				} else if ( copy !== undefined ) {
 
- 					target[ name ] = copy;
 
- 				}
 
- 			}
 
- 		}
 
- 	}
 
- 	// Return the modified object
 
- 	return target;
 
- };
 
- isArray = Array.isArray || function( obj ) {
 
- 	return Object.prototype.toString.call( obj ) === "[object Array]";
 
- };
 
- isFunction = function( obj ) {
 
- 	return Object.prototype.toString.call( obj ) === "[object Function]";
 
- };
 
- isObject = function( obj ) {
 
- 	return Object.prototype.toString.call( obj ) === "[object Object]";
 
- };
 
- startsWith = function( value, pattern ) {
 
- 	return value.indexOf( pattern ) === 0;
 
- };
 
- trim = function( value ) {
 
- 	return ( value + "" ).replace( regexTrim, "" );
 
- };
 
- truncate = function( value ) {
 
- 	if ( isNaN( value ) ) {
 
- 		return NaN;
 
- 	}
 
- 	return Math[ value < 0 ? "ceil" : "floor" ]( value );
 
- };
 
- zeroPad = function( str, count, left ) {
 
- 	var l;
 
- 	for ( l = str.length; l < count; l += 1 ) {
 
- 		str = ( left ? ("0" + str) : (str + "0") );
 
- 	}
 
- 	return str;
 
- };
 
- //
 
- // private Globalization utility functions
 
- //
 
- appendPreOrPostMatch = function( preMatch, strings ) {
 
- 	// appends pre- and post- token match strings while removing escaped characters.
 
- 	// Returns a single quote count which is used to determine if the token occurs
 
- 	// in a string literal.
 
- 	var quoteCount = 0,
 
- 		escaped = false;
 
- 	for ( var i = 0, il = preMatch.length; i < il; i++ ) {
 
- 		var c = preMatch.charAt( i );
 
- 		switch ( c ) {
 
- 			case "\'":
 
- 				if ( escaped ) {
 
- 					strings.push( "\'" );
 
- 				}
 
- 				else {
 
- 					quoteCount++;
 
- 				}
 
- 				escaped = false;
 
- 				break;
 
- 			case "\\":
 
- 				if ( escaped ) {
 
- 					strings.push( "\\" );
 
- 				}
 
- 				escaped = !escaped;
 
- 				break;
 
- 			default:
 
- 				strings.push( c );
 
- 				escaped = false;
 
- 				break;
 
- 		}
 
- 	}
 
- 	return quoteCount;
 
- };
 
- expandFormat = function( cal, format ) {
 
- 	// expands unspecified or single character date formats into the full pattern.
 
- 	format = format || "F";
 
- 	var pattern,
 
- 		patterns = cal.patterns,
 
- 		len = format.length;
 
- 	if ( len === 1 ) {
 
- 		pattern = patterns[ format ];
 
- 		if ( !pattern ) {
 
- 			throw "Invalid date format string \'" + format + "\'.";
 
- 		}
 
- 		format = pattern;
 
- 	}
 
- 	else if ( len === 2 && format.charAt(0) === "%" ) {
 
- 		// %X escape format -- intended as a custom format string that is only one character, not a built-in format.
 
- 		format = format.charAt( 1 );
 
- 	}
 
- 	return format;
 
- };
 
- formatDate = function( value, format, culture ) {
 
- 	var cal = culture.calendar,
 
- 		convert = cal.convert,
 
- 		ret;
 
- 	if ( !format || !format.length || format === "i" ) {
 
- 		if ( culture && culture.name.length ) {
 
- 			if ( convert ) {
 
- 				// non-gregorian calendar, so we cannot use built-in toLocaleString()
 
- 				ret = formatDate( value, cal.patterns.F, culture );
 
- 			}
 
- 			else {
 
- 				var eraDate = new Date( value.getTime() ),
 
- 					era = getEra( value, cal.eras );
 
- 				eraDate.setFullYear( getEraYear(value, cal, era) );
 
- 				ret = eraDate.toLocaleString();
 
- 			}
 
- 		}
 
- 		else {
 
- 			ret = value.toString();
 
- 		}
 
- 		return ret;
 
- 	}
 
- 	var eras = cal.eras,
 
- 		sortable = format === "s";
 
- 	format = expandFormat( cal, format );
 
- 	// Start with an empty string
 
- 	ret = [];
 
- 	var hour,
 
- 		zeros = [ "0", "00", "000" ],
 
- 		foundDay,
 
- 		checkedDay,
 
- 		dayPartRegExp = /([^d]|^)(d|dd)([^d]|$)/g,
 
- 		quoteCount = 0,
 
- 		tokenRegExp = getTokenRegExp(),
 
- 		converted;
 
- 	function padZeros( num, c ) {
 
- 		var r, s = num + "";
 
- 		if ( c > 1 && s.length < c ) {
 
- 			r = ( zeros[c - 2] + s);
 
- 			return r.substr( r.length - c, c );
 
- 		}
 
- 		else {
 
- 			r = s;
 
- 		}
 
- 		return r;
 
- 	}
 
- 	function hasDay() {
 
- 		if ( foundDay || checkedDay ) {
 
- 			return foundDay;
 
- 		}
 
- 		foundDay = dayPartRegExp.test( format );
 
- 		checkedDay = true;
 
- 		return foundDay;
 
- 	}
 
- 	function getPart( date, part ) {
 
- 		if ( converted ) {
 
- 			return converted[ part ];
 
- 		}
 
- 		switch ( part ) {
 
- 			case 0:
 
- 				return date.getFullYear();
 
- 			case 1:
 
- 				return date.getMonth();
 
- 			case 2:
 
- 				return date.getDate();
 
- 			default:
 
- 				throw "Invalid part value " + part;
 
- 		}
 
- 	}
 
- 	if ( !sortable && convert ) {
 
- 		converted = convert.fromGregorian( value );
 
- 	}
 
- 	for ( ; ; ) {
 
- 		// Save the current index
 
- 		var index = tokenRegExp.lastIndex,
 
- 			// Look for the next pattern
 
- 			ar = tokenRegExp.exec( format );
 
- 		// Append the text before the pattern (or the end of the string if not found)
 
- 		var preMatch = format.slice( index, ar ? ar.index : format.length );
 
- 		quoteCount += appendPreOrPostMatch( preMatch, ret );
 
- 		if ( !ar ) {
 
- 			break;
 
- 		}
 
- 		// do not replace any matches that occur inside a string literal.
 
- 		if ( quoteCount % 2 ) {
 
- 			ret.push( ar[0] );
 
- 			continue;
 
- 		}
 
- 		var current = ar[ 0 ],
 
- 			clength = current.length;
 
- 		switch ( current ) {
 
- 			case "ddd":
 
- 				//Day of the week, as a three-letter abbreviation
 
- 			case "dddd":
 
- 				// Day of the week, using the full name
 
- 				var names = ( clength === 3 ) ? cal.days.namesAbbr : cal.days.names;
 
- 				ret.push( names[value.getDay()] );
 
- 				break;
 
- 			case "d":
 
- 				// Day of month, without leading zero for single-digit days
 
- 			case "dd":
 
- 				// Day of month, with leading zero for single-digit days
 
- 				foundDay = true;
 
- 				ret.push(
 
- 					padZeros( getPart(value, 2), clength )
 
- 				);
 
- 				break;
 
- 			case "MMM":
 
- 				// Month, as a three-letter abbreviation
 
- 			case "MMMM":
 
- 				// Month, using the full name
 
- 				var part = getPart( value, 1 );
 
- 				ret.push(
 
- 					( cal.monthsGenitive && hasDay() ) ?
 
- 					( cal.monthsGenitive[ clength === 3 ? "namesAbbr" : "names" ][ part ] ) :
 
- 					( cal.months[ clength === 3 ? "namesAbbr" : "names" ][ part ] )
 
- 				);
 
- 				break;
 
- 			case "M":
 
- 				// Month, as digits, with no leading zero for single-digit months
 
- 			case "MM":
 
- 				// Month, as digits, with leading zero for single-digit months
 
- 				ret.push(
 
- 					padZeros( getPart(value, 1) + 1, clength )
 
- 				);
 
- 				break;
 
- 			case "y":
 
- 				// Year, as two digits, but with no leading zero for years less than 10
 
- 			case "yy":
 
- 				// Year, as two digits, with leading zero for years less than 10
 
- 			case "yyyy":
 
- 				// Year represented by four full digits
 
- 				part = converted ? converted[ 0 ] : getEraYear( value, cal, getEra(value, eras), sortable );
 
- 				if ( clength < 4 ) {
 
- 					part = part % 100;
 
- 				}
 
- 				ret.push(
 
- 					padZeros( part, clength )
 
- 				);
 
- 				break;
 
- 			case "h":
 
- 				// Hours with no leading zero for single-digit hours, using 12-hour clock
 
- 			case "hh":
 
- 				// Hours with leading zero for single-digit hours, using 12-hour clock
 
- 				hour = value.getHours() % 12;
 
- 				if ( hour === 0 ) hour = 12;
 
- 				ret.push(
 
- 					padZeros( hour, clength )
 
- 				);
 
- 				break;
 
- 			case "H":
 
- 				// Hours with no leading zero for single-digit hours, using 24-hour clock
 
- 			case "HH":
 
- 				// Hours with leading zero for single-digit hours, using 24-hour clock
 
- 				ret.push(
 
- 					padZeros( value.getHours(), clength )
 
- 				);
 
- 				break;
 
- 			case "m":
 
- 				// Minutes with no leading zero for single-digit minutes
 
- 			case "mm":
 
- 				// Minutes with leading zero for single-digit minutes
 
- 				ret.push(
 
- 					padZeros( value.getMinutes(), clength )
 
- 				);
 
- 				break;
 
- 			case "s":
 
- 				// Seconds with no leading zero for single-digit seconds
 
- 			case "ss":
 
- 				// Seconds with leading zero for single-digit seconds
 
- 				ret.push(
 
- 					padZeros( value.getSeconds(), clength )
 
- 				);
 
- 				break;
 
- 			case "t":
 
- 				// One character am/pm indicator ("a" or "p")
 
- 			case "tt":
 
- 				// Multicharacter am/pm indicator
 
- 				part = value.getHours() < 12 ? ( cal.AM ? cal.AM[0] : " " ) : ( cal.PM ? cal.PM[0] : " " );
 
- 				ret.push( clength === 1 ? part.charAt(0) : part );
 
- 				break;
 
- 			case "f":
 
- 				// Deciseconds
 
- 			case "ff":
 
- 				// Centiseconds
 
- 			case "fff":
 
- 				// Milliseconds
 
- 				ret.push(
 
- 					padZeros( value.getMilliseconds(), 3 ).substr( 0, clength )
 
- 				);
 
- 				break;
 
- 			case "z":
 
- 				// Time zone offset, no leading zero
 
- 			case "zz":
 
- 				// Time zone offset with leading zero
 
- 				hour = value.getTimezoneOffset() / 60;
 
- 				ret.push(
 
- 					( hour <= 0 ? "+" : "-" ) + padZeros( Math.floor(Math.abs(hour)), clength )
 
- 				);
 
- 				break;
 
- 			case "zzz":
 
- 				// Time zone offset with leading zero
 
- 				hour = value.getTimezoneOffset() / 60;
 
- 				ret.push(
 
- 					( hour <= 0 ? "+" : "-" ) + padZeros( Math.floor(Math.abs(hour)), 2 ) +
 
- 					// Hard coded ":" separator, rather than using cal.TimeSeparator
 
- 					// Repeated here for consistency, plus ":" was already assumed in date parsing.
 
- 					":" + padZeros( Math.abs(value.getTimezoneOffset() % 60), 2 )
 
- 				);
 
- 				break;
 
- 			case "g":
 
- 			case "gg":
 
- 				if ( cal.eras ) {
 
- 					ret.push(
 
- 						cal.eras[ getEra(value, eras) ].name
 
- 					);
 
- 				}
 
- 				break;
 
- 		case "/":
 
- 			ret.push( cal["/"] );
 
- 			break;
 
- 		default:
 
- 			throw "Invalid date format pattern \'" + current + "\'.";
 
- 		}
 
- 	}
 
- 	return ret.join( "" );
 
- };
 
- // formatNumber
 
- (function() {
 
- 	var expandNumber;
 
- 	expandNumber = function( number, precision, formatInfo ) {
 
- 		var groupSizes = formatInfo.groupSizes,
 
- 			curSize = groupSizes[ 0 ],
 
- 			curGroupIndex = 1,
 
- 			factor = Math.pow( 10, precision ),
 
- 			rounded = Math.round( number * factor ) / factor;
 
- 		if ( !isFinite(rounded) ) {
 
- 			rounded = number;
 
- 		}
 
- 		number = rounded;
 
- 		var numberString = number+"",
 
- 			right = "",
 
- 			split = numberString.split( /e/i ),
 
- 			exponent = split.length > 1 ? parseInt( split[1], 10 ) : 0;
 
- 		numberString = split[ 0 ];
 
- 		split = numberString.split( "." );
 
- 		numberString = split[ 0 ];
 
- 		right = split.length > 1 ? split[ 1 ] : "";
 
- 		var l;
 
- 		if ( exponent > 0 ) {
 
- 			right = zeroPad( right, exponent, false );
 
- 			numberString += right.slice( 0, exponent );
 
- 			right = right.substr( exponent );
 
- 		}
 
- 		else if ( exponent < 0 ) {
 
- 			exponent = -exponent;
 
- 			numberString = zeroPad( numberString, exponent + 1, true );
 
- 			right = numberString.slice( -exponent, numberString.length ) + right;
 
- 			numberString = numberString.slice( 0, -exponent );
 
- 		}
 
- 		if ( precision > 0 ) {
 
- 			right = formatInfo[ "." ] +
 
- 				( (right.length > precision) ? right.slice(0, precision) : zeroPad(right, precision) );
 
- 		}
 
- 		else {
 
- 			right = "";
 
- 		}
 
- 		var stringIndex = numberString.length - 1,
 
- 			sep = formatInfo[ "," ],
 
- 			ret = "";
 
- 		while ( stringIndex >= 0 ) {
 
- 			if ( curSize === 0 || curSize > stringIndex ) {
 
- 				return numberString.slice( 0, stringIndex + 1 ) + ( ret.length ? (sep + ret + right) : right );
 
- 			}
 
- 			ret = numberString.slice( stringIndex - curSize + 1, stringIndex + 1 ) + ( ret.length ? (sep + ret) : "" );
 
- 			stringIndex -= curSize;
 
- 			if ( curGroupIndex < groupSizes.length ) {
 
- 				curSize = groupSizes[ curGroupIndex ];
 
- 				curGroupIndex++;
 
- 			}
 
- 		}
 
- 		return numberString.slice( 0, stringIndex + 1 ) + sep + ret + right;
 
- 	};
 
- 	formatNumber = function( value, format, culture ) {
 
- 		if ( !isFinite(value) ) {
 
- 			if ( value === Infinity ) {
 
- 				return culture.numberFormat.positiveInfinity;
 
- 			}
 
- 			if ( value === -Infinity ) {
 
- 				return culture.numberFormat.negativeInfinity;
 
- 			}
 
- 			return culture.numberFormat[ "NaN" ];
 
- 		}
 
- 		if ( !format || format === "i" ) {
 
- 			return culture.name.length ? value.toLocaleString() : value.toString();
 
- 		}
 
- 		format = format || "D";
 
- 		var nf = culture.numberFormat,
 
- 			number = Math.abs( value ),
 
- 			precision = -1,
 
- 			pattern;
 
- 		if ( format.length > 1 ) precision = parseInt( format.slice(1), 10 );
 
- 		var current = format.charAt( 0 ).toUpperCase(),
 
- 			formatInfo;
 
- 		switch ( current ) {
 
- 			case "D":
 
- 				pattern = "n";
 
- 				number = truncate( number );
 
- 				if ( precision !== -1 ) {
 
- 					number = zeroPad( "" + number, precision, true );
 
- 				}
 
- 				if ( value < 0 ) number = "-" + number;
 
- 				break;
 
- 			case "N":
 
- 				formatInfo = nf;
 
- 				/* falls through */
 
- 			case "C":
 
- 				formatInfo = formatInfo || nf.currency;
 
- 				/* falls through */
 
- 			case "P":
 
- 				formatInfo = formatInfo || nf.percent;
 
- 				pattern = value < 0 ? formatInfo.pattern[ 0 ] : ( formatInfo.pattern[1] || "n" );
 
- 				if ( precision === -1 ) precision = formatInfo.decimals;
 
- 				number = expandNumber( number * (current === "P" ? 100 : 1), precision, formatInfo );
 
- 				break;
 
- 			default:
 
- 				throw "Bad number format specifier: " + current;
 
- 		}
 
- 		var patternParts = /n|\$|-|%/g,
 
- 			ret = "";
 
- 		for ( ; ; ) {
 
- 			var index = patternParts.lastIndex,
 
- 				ar = patternParts.exec( pattern );
 
- 			ret += pattern.slice( index, ar ? ar.index : pattern.length );
 
- 			if ( !ar ) {
 
- 				break;
 
- 			}
 
- 			switch ( ar[0] ) {
 
- 				case "n":
 
- 					ret += number;
 
- 					break;
 
- 				case "$":
 
- 					ret += nf.currency.symbol;
 
- 					break;
 
- 				case "-":
 
- 					// don't make 0 negative
 
- 					if ( /[1-9]/.test(number) ) {
 
- 						ret += nf[ "-" ];
 
- 					}
 
- 					break;
 
- 				case "%":
 
- 					ret += nf.percent.symbol;
 
- 					break;
 
- 			}
 
- 		}
 
- 		return ret;
 
- 	};
 
- }());
 
- getTokenRegExp = function() {
 
- 	// regular expression for matching date and time tokens in format strings.
 
- 	return (/\/|dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z|gg|g/g);
 
- };
 
- getEra = function( date, eras ) {
 
- 	if ( !eras ) return 0;
 
- 	var start, ticks = date.getTime();
 
- 	for ( var i = 0, l = eras.length; i < l; i++ ) {
 
- 		start = eras[ i ].start;
 
- 		if ( start === null || ticks >= start ) {
 
- 			return i;
 
- 		}
 
- 	}
 
- 	return 0;
 
- };
 
- getEraYear = function( date, cal, era, sortable ) {
 
- 	var year = date.getFullYear();
 
- 	if ( !sortable && cal.eras ) {
 
- 		// convert normal gregorian year to era-shifted gregorian
 
- 		// year by subtracting the era offset
 
- 		year -= cal.eras[ era ].offset;
 
- 	}
 
- 	return year;
 
- };
 
- // parseExact
 
- (function() {
 
- 	var expandYear,
 
- 		getDayIndex,
 
- 		getMonthIndex,
 
- 		getParseRegExp,
 
- 		outOfRange,
 
- 		toUpper,
 
- 		toUpperArray;
 
- 	expandYear = function( cal, year ) {
 
- 		// expands 2-digit year into 4 digits.
 
- 		if ( year < 100 ) {
 
- 			var now = new Date(),
 
- 				era = getEra( now ),
 
- 				curr = getEraYear( now, cal, era ),
 
- 				twoDigitYearMax = cal.twoDigitYearMax;
 
- 			twoDigitYearMax = typeof twoDigitYearMax === "string" ? new Date().getFullYear() % 100 + parseInt( twoDigitYearMax, 10 ) : twoDigitYearMax;
 
- 			year += curr - ( curr % 100 );
 
- 			if ( year > twoDigitYearMax ) {
 
- 				year -= 100;
 
- 			}
 
- 		}
 
- 		return year;
 
- 	};
 
- 	getDayIndex = function	( cal, value, abbr ) {
 
- 		var ret,
 
- 			days = cal.days,
 
- 			upperDays = cal._upperDays;
 
- 		if ( !upperDays ) {
 
- 			cal._upperDays = upperDays = [
 
- 				toUpperArray( days.names ),
 
- 				toUpperArray( days.namesAbbr ),
 
- 				toUpperArray( days.namesShort )
 
- 			];
 
- 		}
 
- 		value = toUpper( value );
 
- 		if ( abbr ) {
 
- 			ret = arrayIndexOf( upperDays[1], value );
 
- 			if ( ret === -1 ) {
 
- 				ret = arrayIndexOf( upperDays[2], value );
 
- 			}
 
- 		}
 
- 		else {
 
- 			ret = arrayIndexOf( upperDays[0], value );
 
- 		}
 
- 		return ret;
 
- 	};
 
- 	getMonthIndex = function( cal, value, abbr ) {
 
- 		var months = cal.months,
 
- 			monthsGen = cal.monthsGenitive || cal.months,
 
- 			upperMonths = cal._upperMonths,
 
- 			upperMonthsGen = cal._upperMonthsGen;
 
- 		if ( !upperMonths ) {
 
- 			cal._upperMonths = upperMonths = [
 
- 				toUpperArray( months.names ),
 
- 				toUpperArray( months.namesAbbr )
 
- 			];
 
- 			cal._upperMonthsGen = upperMonthsGen = [
 
- 				toUpperArray( monthsGen.names ),
 
- 				toUpperArray( monthsGen.namesAbbr )
 
- 			];
 
- 		}
 
- 		value = toUpper( value );
 
- 		var i = arrayIndexOf( abbr ? upperMonths[1] : upperMonths[0], value );
 
- 		if ( i < 0 ) {
 
- 			i = arrayIndexOf( abbr ? upperMonthsGen[1] : upperMonthsGen[0], value );
 
- 		}
 
- 		return i;
 
- 	};
 
- 	getParseRegExp = function( cal, format ) {
 
- 		// converts a format string into a regular expression with groups that
 
- 		// can be used to extract date fields from a date string.
 
- 		// check for a cached parse regex.
 
- 		var re = cal._parseRegExp;
 
- 		if ( !re ) {
 
- 			cal._parseRegExp = re = {};
 
- 		}
 
- 		else {
 
- 			var reFormat = re[ format ];
 
- 			if ( reFormat ) {
 
- 				return reFormat;
 
- 			}
 
- 		}
 
- 		// expand single digit formats, then escape regular expression characters.
 
- 		var expFormat = expandFormat( cal, format ).replace( /([\^\$\.\*\+\?\|\[\]\(\)\{\}])/g, "\\\\$1" ),
 
- 			regexp = [ "^" ],
 
- 			groups = [],
 
- 			index = 0,
 
- 			quoteCount = 0,
 
- 			tokenRegExp = getTokenRegExp(),
 
- 			match;
 
- 		// iterate through each date token found.
 
- 		while ( (match = tokenRegExp.exec(expFormat)) !== null ) {
 
- 			var preMatch = expFormat.slice( index, match.index );
 
- 			index = tokenRegExp.lastIndex;
 
- 			// don't replace any matches that occur inside a string literal.
 
- 			quoteCount += appendPreOrPostMatch( preMatch, regexp );
 
- 			if ( quoteCount % 2 ) {
 
- 				regexp.push( match[0] );
 
- 				continue;
 
- 			}
 
- 			// add a regex group for the token.
 
- 			var m = match[ 0 ],
 
- 				len = m.length,
 
- 				add;
 
- 			switch ( m ) {
 
- 				case "dddd": case "ddd":
 
- 				case "MMMM": case "MMM":
 
- 				case "gg": case "g":
 
- 					add = "(\\D+)";
 
- 					break;
 
- 				case "tt": case "t":
 
- 					add = "(\\D*)";
 
- 					break;
 
- 				case "yyyy":
 
- 				case "fff":
 
- 				case "ff":
 
- 				case "f":
 
- 					add = "(\\d{" + len + "})";
 
- 					break;
 
- 				case "dd": case "d":
 
- 				case "MM": case "M":
 
- 				case "yy": case "y":
 
- 				case "HH": case "H":
 
- 				case "hh": case "h":
 
- 				case "mm": case "m":
 
- 				case "ss": case "s":
 
- 					add = "(\\d\\d?)";
 
- 					break;
 
- 				case "zzz":
 
- 					add = "([+-]?\\d\\d?:\\d{2})";
 
- 					break;
 
- 				case "zz": case "z":
 
- 					add = "([+-]?\\d\\d?)";
 
- 					break;
 
- 				case "/":
 
- 					add = "(\\/)";
 
- 					break;
 
- 				default:
 
- 					throw "Invalid date format pattern \'" + m + "\'.";
 
- 			}
 
- 			if ( add ) {
 
- 				regexp.push( add );
 
- 			}
 
- 			groups.push( match[0] );
 
- 		}
 
- 		appendPreOrPostMatch( expFormat.slice(index), regexp );
 
- 		regexp.push( "$" );
 
- 		// allow whitespace to differ when matching formats.
 
- 		var regexpStr = regexp.join( "" ).replace( /\s+/g, "\\s+" ),
 
- 			parseRegExp = { "regExp": regexpStr, "groups": groups };
 
- 		// cache the regex for this format.
 
- 		return re[ format ] = parseRegExp;
 
- 	};
 
- 	outOfRange = function( value, low, high ) {
 
- 		return value < low || value > high;
 
- 	};
 
- 	toUpper = function( value ) {
 
- 		// "he-IL" has non-breaking space in weekday names.
 
- 		return value.split( "\u00A0" ).join( " " ).toUpperCase();
 
- 	};
 
- 	toUpperArray = function( arr ) {
 
- 		var results = [];
 
- 		for ( var i = 0, l = arr.length; i < l; i++ ) {
 
- 			results[ i ] = toUpper( arr[i] );
 
- 		}
 
- 		return results;
 
- 	};
 
- 	parseExact = function( value, format, culture ) {
 
- 		// try to parse the date string by matching against the format string
 
- 		// while using the specified culture for date field names.
 
- 		value = trim( value );
 
- 		var cal = culture.calendar,
 
- 			// convert date formats into regular expressions with groupings.
 
- 			// use the regexp to determine the input format and extract the date fields.
 
- 			parseInfo = getParseRegExp( cal, format ),
 
- 			match = new RegExp( parseInfo.regExp ).exec( value );
 
- 		if ( match === null ) {
 
- 			return null;
 
- 		}
 
- 		// found a date format that matches the input.
 
- 		var groups = parseInfo.groups,
 
- 			era = null, year = null, month = null, date = null, weekDay = null,
 
- 			hour = 0, hourOffset, min = 0, sec = 0, msec = 0, tzMinOffset = null,
 
- 			pmHour = false;
 
- 		// iterate the format groups to extract and set the date fields.
 
- 		for ( var j = 0, jl = groups.length; j < jl; j++ ) {
 
- 			var matchGroup = match[ j + 1 ];
 
- 			if ( matchGroup ) {
 
- 				var current = groups[ j ],
 
- 					clength = current.length,
 
- 					matchInt = parseInt( matchGroup, 10 );
 
- 				switch ( current ) {
 
- 					case "dd": case "d":
 
- 						// Day of month.
 
- 						date = matchInt;
 
- 						// check that date is generally in valid range, also checking overflow below.
 
- 						if ( outOfRange(date, 1, 31) ) return null;
 
- 						break;
 
- 					case "MMM": case "MMMM":
 
- 						month = getMonthIndex( cal, matchGroup, clength === 3 );
 
- 						if ( outOfRange(month, 0, 11) ) return null;
 
- 						break;
 
- 					case "M": case "MM":
 
- 						// Month.
 
- 						month = matchInt - 1;
 
- 						if ( outOfRange(month, 0, 11) ) return null;
 
- 						break;
 
- 					case "y": case "yy":
 
- 					case "yyyy":
 
- 						year = clength < 4 ? expandYear( cal, matchInt ) : matchInt;
 
- 						if ( outOfRange(year, 0, 9999) ) return null;
 
- 						break;
 
- 					case "h": case "hh":
 
- 						// Hours (12-hour clock).
 
- 						hour = matchInt;
 
- 						if ( hour === 12 ) hour = 0;
 
- 						if ( outOfRange(hour, 0, 11) ) return null;
 
- 						break;
 
- 					case "H": case "HH":
 
- 						// Hours (24-hour clock).
 
- 						hour = matchInt;
 
- 						if ( outOfRange(hour, 0, 23) ) return null;
 
- 						break;
 
- 					case "m": case "mm":
 
- 						// Minutes.
 
- 						min = matchInt;
 
- 						if ( outOfRange(min, 0, 59) ) return null;
 
- 						break;
 
- 					case "s": case "ss":
 
- 						// Seconds.
 
- 						sec = matchInt;
 
- 						if ( outOfRange(sec, 0, 59) ) return null;
 
- 						break;
 
- 					case "tt": case "t":
 
- 						// AM/PM designator.
 
- 						// see if it is standard, upper, or lower case PM. If not, ensure it is at least one of
 
- 						// the AM tokens. If not, fail the parse for this format.
 
- 						pmHour = cal.PM && ( matchGroup === cal.PM[0] || matchGroup === cal.PM[1] || matchGroup === cal.PM[2] );
 
- 						if (
 
- 							!pmHour && (
 
- 								!cal.AM || ( matchGroup !== cal.AM[0] && matchGroup !== cal.AM[1] && matchGroup !== cal.AM[2] )
 
- 							)
 
- 						) return null;
 
- 						break;
 
- 					case "f":
 
- 						// Deciseconds.
 
- 					case "ff":
 
- 						// Centiseconds.
 
- 					case "fff":
 
- 						// Milliseconds.
 
- 						msec = matchInt * Math.pow( 10, 3 - clength );
 
- 						if ( outOfRange(msec, 0, 999) ) return null;
 
- 						break;
 
- 					case "ddd":
 
- 						// Day of week.
 
- 					case "dddd":
 
- 						// Day of week.
 
- 						weekDay = getDayIndex( cal, matchGroup, clength === 3 );
 
- 						if ( outOfRange(weekDay, 0, 6) ) return null;
 
- 						break;
 
- 					case "zzz":
 
- 						// Time zone offset in +/- hours:min.
 
- 						var offsets = matchGroup.split( /:/ );
 
- 						if ( offsets.length !== 2 ) return null;
 
- 						hourOffset = parseInt( offsets[0], 10 );
 
- 						if ( outOfRange(hourOffset, -12, 13) ) return null;
 
- 						var minOffset = parseInt( offsets[1], 10 );
 
- 						if ( outOfRange(minOffset, 0, 59) ) return null;
 
- 						tzMinOffset = ( hourOffset * 60 ) + ( startsWith(matchGroup, "-") ? -minOffset : minOffset );
 
- 						break;
 
- 					case "z": case "zz":
 
- 						// Time zone offset in +/- hours.
 
- 						hourOffset = matchInt;
 
- 						if ( outOfRange(hourOffset, -12, 13) ) return null;
 
- 						tzMinOffset = hourOffset * 60;
 
- 						break;
 
- 					case "g": case "gg":
 
- 						var eraName = matchGroup;
 
- 						if ( !eraName || !cal.eras ) return null;
 
- 						eraName = trim( eraName.toLowerCase() );
 
- 						for ( var i = 0, l = cal.eras.length; i < l; i++ ) {
 
- 							if ( eraName === cal.eras[i].name.toLowerCase() ) {
 
- 								era = i;
 
- 								break;
 
- 							}
 
- 						}
 
- 						// could not find an era with that name
 
- 						if ( era === null ) return null;
 
- 						break;
 
- 				}
 
- 			}
 
- 		}
 
- 		var result = new Date(), defaultYear, convert = cal.convert;
 
- 		defaultYear = convert ? convert.fromGregorian( result )[ 0 ] : result.getFullYear();
 
- 		if ( year === null ) {
 
- 			year = defaultYear;
 
- 		}
 
- 		else if ( cal.eras ) {
 
- 			// year must be shifted to normal gregorian year
 
- 			// but not if year was not specified, its already normal gregorian
 
- 			// per the main if clause above.
 
- 			year += cal.eras[( era || 0 )].offset;
 
- 		}
 
- 		// set default day and month to 1 and January, so if unspecified, these are the defaults
 
- 		// instead of the current day/month.
 
- 		if ( month === null ) {
 
- 			month = 0;
 
- 		}
 
- 		if ( date === null ) {
 
- 			date = 1;
 
- 		}
 
- 		// now have year, month, and date, but in the culture's calendar.
 
- 		// convert to gregorian if necessary
 
- 		if ( convert ) {
 
- 			result = convert.toGregorian( year, month, date );
 
- 			// conversion failed, must be an invalid match
 
- 			if ( result === null ) return null;
 
- 		}
 
- 		else {
 
- 			// have to set year, month and date together to avoid overflow based on current date.
 
- 			result.setFullYear( year, month, date );
 
- 			// check to see if date overflowed for specified month (only checked 1-31 above).
 
- 			if ( result.getDate() !== date ) return null;
 
- 			// invalid day of week.
 
- 			if ( weekDay !== null && result.getDay() !== weekDay ) {
 
- 				return null;
 
- 			}
 
- 		}
 
- 		// if pm designator token was found make sure the hours fit the 24-hour clock.
 
- 		if ( pmHour && hour < 12 ) {
 
- 			hour += 12;
 
- 		}
 
- 		result.setHours( hour, min, sec, msec );
 
- 		if ( tzMinOffset !== null ) {
 
- 			// adjust timezone to utc before applying local offset.
 
- 			var adjustedMin = result.getMinutes() - ( tzMinOffset + result.getTimezoneOffset() );
 
- 			// Safari limits hours and minutes to the range of -127 to 127.  We need to use setHours
 
- 			// to ensure both these fields will not exceed this range.	adjustedMin will range
 
- 			// somewhere between -1440 and 1500, so we only need to split this into hours.
 
- 			result.setHours( result.getHours() + parseInt(adjustedMin / 60, 10), adjustedMin % 60 );
 
- 		}
 
- 		return result;
 
- 	};
 
- }());
 
- parseNegativePattern = function( value, nf, negativePattern ) {
 
- 	var neg = nf[ "-" ],
 
- 		pos = nf[ "+" ],
 
- 		ret;
 
- 	switch ( negativePattern ) {
 
- 		case "n -":
 
- 			neg = " " + neg;
 
- 			pos = " " + pos;
 
- 			/* falls through */
 
- 		case "n-":
 
- 			if ( endsWith(value, neg) ) {
 
- 				ret = [ "-", value.substr(0, value.length - neg.length) ];
 
- 			}
 
- 			else if ( endsWith(value, pos) ) {
 
- 				ret = [ "+", value.substr(0, value.length - pos.length) ];
 
- 			}
 
- 			break;
 
- 		case "- n":
 
- 			neg += " ";
 
- 			pos += " ";
 
- 			/* falls through */
 
- 		case "-n":
 
- 			if ( startsWith(value, neg) ) {
 
- 				ret = [ "-", value.substr(neg.length) ];
 
- 			}
 
- 			else if ( startsWith(value, pos) ) {
 
- 				ret = [ "+", value.substr(pos.length) ];
 
- 			}
 
- 			break;
 
- 		case "(n)":
 
- 			if ( startsWith(value, "(") && endsWith(value, ")") ) {
 
- 				ret = [ "-", value.substr(1, value.length - 2) ];
 
- 			}
 
- 			break;
 
- 	}
 
- 	return ret || [ "", value ];
 
- };
 
- //
 
- // public instance functions
 
- //
 
- Globalize.prototype.findClosestCulture = function( cultureSelector ) {
 
- 	return Globalize.findClosestCulture.call( this, cultureSelector );
 
- };
 
- Globalize.prototype.format = function( value, format, cultureSelector ) {
 
- 	return Globalize.format.call( this, value, format, cultureSelector );
 
- };
 
- Globalize.prototype.localize = function( key, cultureSelector ) {
 
- 	return Globalize.localize.call( this, key, cultureSelector );
 
- };
 
- Globalize.prototype.parseInt = function( value, radix, cultureSelector ) {
 
- 	return Globalize.parseInt.call( this, value, radix, cultureSelector );
 
- };
 
- Globalize.prototype.parseFloat = function( value, radix, cultureSelector ) {
 
- 	return Globalize.parseFloat.call( this, value, radix, cultureSelector );
 
- };
 
- Globalize.prototype.culture = function( cultureSelector ) {
 
- 	return Globalize.culture.call( this, cultureSelector );
 
- };
 
- //
 
- // public singleton functions
 
- //
 
- Globalize.addCultureInfo = function( cultureName, baseCultureName, info ) {
 
- 	var base = {},
 
- 		isNew = false;
 
- 	if ( typeof cultureName !== "string" ) {
 
- 		// cultureName argument is optional string. If not specified, assume info is first
 
- 		// and only argument. Specified info deep-extends current culture.
 
- 		info = cultureName;
 
- 		cultureName = this.culture().name;
 
- 		base = this.cultures[ cultureName ];
 
- 	} else if ( typeof baseCultureName !== "string" ) {
 
- 		// baseCultureName argument is optional string. If not specified, assume info is second
 
- 		// argument. Specified info deep-extends specified culture.
 
- 		// If specified culture does not exist, create by deep-extending default
 
- 		info = baseCultureName;
 
- 		isNew = ( this.cultures[ cultureName ] == null );
 
- 		base = this.cultures[ cultureName ] || this.cultures[ "default" ];
 
- 	} else {
 
- 		// cultureName and baseCultureName specified. Assume a new culture is being created
 
- 		// by deep-extending an specified base culture
 
- 		isNew = true;
 
- 		base = this.cultures[ baseCultureName ];
 
- 	}
 
- 	this.cultures[ cultureName ] = extend(true, {},
 
- 		base,
 
- 		info
 
- 	);
 
- 	// Make the standard calendar the current culture if it's a new culture
 
- 	if ( isNew ) {
 
- 		this.cultures[ cultureName ].calendar = this.cultures[ cultureName ].calendars.standard;
 
- 	}
 
- };
 
- Globalize.findClosestCulture = function( name ) {
 
- 	var match;
 
- 	if ( !name ) {
 
- 		return this.findClosestCulture( this.cultureSelector ) || this.cultures[ "default" ];
 
- 	}
 
- 	if ( typeof name === "string" ) {
 
- 		name = name.split( "," );
 
- 	}
 
- 	if ( isArray(name) ) {
 
- 		var lang,
 
- 			cultures = this.cultures,
 
- 			list = name,
 
- 			i, l = list.length,
 
- 			prioritized = [];
 
- 		for ( i = 0; i < l; i++ ) {
 
- 			name = trim( list[i] );
 
- 			var pri, parts = name.split( ";" );
 
- 			lang = trim( parts[0] );
 
- 			if ( parts.length === 1 ) {
 
- 				pri = 1;
 
- 			}
 
- 			else {
 
- 				name = trim( parts[1] );
 
- 				if ( name.indexOf("q=") === 0 ) {
 
- 					name = name.substr( 2 );
 
- 					pri = parseFloat( name );
 
- 					pri = isNaN( pri ) ? 0 : pri;
 
- 				}
 
- 				else {
 
- 					pri = 1;
 
- 				}
 
- 			}
 
- 			prioritized.push({ lang: lang, pri: pri });
 
- 		}
 
- 		prioritized.sort(function( a, b ) {
 
- 			if ( a.pri < b.pri ) {
 
- 				return 1;
 
- 			} else if ( a.pri > b.pri ) {
 
- 				return -1;
 
- 			}
 
- 			return 0;
 
- 		});
 
- 		// exact match
 
- 		for ( i = 0; i < l; i++ ) {
 
- 			lang = prioritized[ i ].lang;
 
- 			match = cultures[ lang ];
 
- 			if ( match ) {
 
- 				return match;
 
- 			}
 
- 		}
 
- 		// neutral language match
 
- 		for ( i = 0; i < l; i++ ) {
 
- 			lang = prioritized[ i ].lang;
 
- 			do {
 
- 				var index = lang.lastIndexOf( "-" );
 
- 				if ( index === -1 ) {
 
- 					break;
 
- 				}
 
- 				// strip off the last part. e.g. en-US => en
 
- 				lang = lang.substr( 0, index );
 
- 				match = cultures[ lang ];
 
- 				if ( match ) {
 
- 					return match;
 
- 				}
 
- 			}
 
- 			while ( 1 );
 
- 		}
 
- 		// last resort: match first culture using that language
 
- 		for ( i = 0; i < l; i++ ) {
 
- 			lang = prioritized[ i ].lang;
 
- 			for ( var cultureKey in cultures ) {
 
- 				var culture = cultures[ cultureKey ];
 
- 				if ( culture.language == lang ) {
 
- 					return culture;
 
- 				}
 
- 			}
 
- 		}
 
- 	}
 
- 	else if ( typeof name === "object" ) {
 
- 		return name;
 
- 	}
 
- 	return match || null;
 
- };
 
- Globalize.format = function( value, format, cultureSelector ) {
 
- 	var culture = this.findClosestCulture( cultureSelector );
 
- 	if ( value instanceof Date ) {
 
- 		value = formatDate( value, format, culture );
 
- 	}
 
- 	else if ( typeof value === "number" ) {
 
- 		value = formatNumber( value, format, culture );
 
- 	}
 
- 	return value;
 
- };
 
- Globalize.localize = function( key, cultureSelector ) {
 
- 	return this.findClosestCulture( cultureSelector ).messages[ key ] ||
 
- 		this.cultures[ "default" ].messages[ key ];
 
- };
 
- Globalize.parseDate = function( value, formats, culture ) {
 
- 	culture = this.findClosestCulture( culture );
 
- 	var date, prop, patterns;
 
- 	if ( formats ) {
 
- 		if ( typeof formats === "string" ) {
 
- 			formats = [ formats ];
 
- 		}
 
- 		if ( formats.length ) {
 
- 			for ( var i = 0, l = formats.length; i < l; i++ ) {
 
- 				var format = formats[ i ];
 
- 				if ( format ) {
 
- 					date = parseExact( value, format, culture );
 
- 					if ( date ) {
 
- 						break;
 
- 					}
 
- 				}
 
- 			}
 
- 		}
 
- 	} else {
 
- 		patterns = culture.calendar.patterns;
 
- 		for ( prop in patterns ) {
 
- 			date = parseExact( value, patterns[prop], culture );
 
- 			if ( date ) {
 
- 				break;
 
- 			}
 
- 		}
 
- 	}
 
- 	return date || null;
 
- };
 
- Globalize.parseInt = function( value, radix, cultureSelector ) {
 
- 	return truncate( Globalize.parseFloat(value, radix, cultureSelector) );
 
- };
 
- Globalize.parseFloat = function( value, radix, cultureSelector ) {
 
- 	// radix argument is optional
 
- 	if ( typeof radix !== "number" ) {
 
- 		cultureSelector = radix;
 
- 		radix = 10;
 
- 	}
 
- 	var culture = this.findClosestCulture( cultureSelector );
 
- 	var ret = NaN,
 
- 		nf = culture.numberFormat;
 
- 	if ( value.indexOf(culture.numberFormat.currency.symbol) > -1 ) {
 
- 		// remove currency symbol
 
- 		value = value.replace( culture.numberFormat.currency.symbol, "" );
 
- 		// replace decimal seperator
 
- 		value = value.replace( culture.numberFormat.currency["."], culture.numberFormat["."] );
 
- 	}
 
- 	// trim leading and trailing whitespace
 
- 	value = trim( value );
 
- 	// allow infinity or hexidecimal
 
- 	if ( regexInfinity.test(value) ) {
 
- 		ret = parseFloat( value );
 
- 	}
 
- 	else if ( !radix && regexHex.test(value) ) {
 
- 		ret = parseInt( value, 16 );
 
- 	}
 
- 	else {
 
- 		// determine sign and number
 
- 		var signInfo = parseNegativePattern( value, nf, nf.pattern[0] ),
 
- 			sign = signInfo[ 0 ],
 
- 			num = signInfo[ 1 ];
 
- 		// #44 - try parsing as "(n)"
 
- 		if ( sign === "" && nf.pattern[0] !== "(n)" ) {
 
- 			signInfo = parseNegativePattern( value, nf, "(n)" );
 
- 			sign = signInfo[ 0 ];
 
- 			num = signInfo[ 1 ];
 
- 		}
 
- 		// try parsing as "-n"
 
- 		if ( sign === "" && nf.pattern[0] !== "-n" ) {
 
- 			signInfo = parseNegativePattern( value, nf, "-n" );
 
- 			sign = signInfo[ 0 ];
 
- 			num = signInfo[ 1 ];
 
- 		}
 
- 		sign = sign || "+";
 
- 		// determine exponent and number
 
- 		var exponent,
 
- 			intAndFraction,
 
- 			exponentPos = num.indexOf( "e" );
 
- 		if ( exponentPos < 0 ) exponentPos = num.indexOf( "E" );
 
- 		if ( exponentPos < 0 ) {
 
- 			intAndFraction = num;
 
- 			exponent = null;
 
- 		}
 
- 		else {
 
- 			intAndFraction = num.substr( 0, exponentPos );
 
- 			exponent = num.substr( exponentPos + 1 );
 
- 		}
 
- 		// determine decimal position
 
- 		var integer,
 
- 			fraction,
 
- 			decSep = nf[ "." ],
 
- 			decimalPos = intAndFraction.indexOf( decSep );
 
- 		if ( decimalPos < 0 ) {
 
- 			integer = intAndFraction;
 
- 			fraction = null;
 
- 		}
 
- 		else {
 
- 			integer = intAndFraction.substr( 0, decimalPos );
 
- 			fraction = intAndFraction.substr( decimalPos + decSep.length );
 
- 		}
 
- 		// handle groups (e.g. 1,000,000)
 
- 		var groupSep = nf[ "," ];
 
- 		integer = integer.split( groupSep ).join( "" );
 
- 		var altGroupSep = groupSep.replace( /\u00A0/g, " " );
 
- 		if ( groupSep !== altGroupSep ) {
 
- 			integer = integer.split( altGroupSep ).join( "" );
 
- 		}
 
- 		// build a natively parsable number string
 
- 		var p = sign + integer;
 
- 		if ( fraction !== null ) {
 
- 			p += "." + fraction;
 
- 		}
 
- 		if ( exponent !== null ) {
 
- 			// exponent itself may have a number patternd
 
- 			var expSignInfo = parseNegativePattern( exponent, nf, "-n" );
 
- 			p += "e" + ( expSignInfo[0] || "+" ) + expSignInfo[ 1 ];
 
- 		}
 
- 		if ( regexParseFloat.test(p) ) {
 
- 			ret = parseFloat( p );
 
- 		}
 
- 	}
 
- 	return ret;
 
- };
 
- Globalize.culture = function( cultureSelector ) {
 
- 	// setter
 
- 	if ( typeof cultureSelector !== "undefined" ) {
 
- 		this.cultureSelector = cultureSelector;
 
- 	}
 
- 	// getter
 
- 	return this.findClosestCulture( cultureSelector ) || this.cultures[ "default" ];
 
- };
 
- }( this ));
 
 
  |