File "Globalize.js"
Full path: /home/meharicl/www/recensement2/Globalize.js
File
size: 62.97 B
MIME-type: text/plain
Charset: utf-8
Download Open Edit Advanced Editor Back
//JS Globalize @0-79AC0597
/*!
* 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 arrayLocaleInfo = "fr|fr|FR|1;0;|2|,| |janvier;février;mars;avril;mai;juin;juillet;août;septembre;octobre;novembre;décembre|janv.;févr.;mars;avr.;mai;juin;juil.;août;sept.;oct.;nov.;déc.|dimanche;lundi;mardi;mercredi;jeudi;vendredi;samedi|dim.;lun.;mar.;mer.;jeu.;ven.;sam.|dd/mm/yyyy|dddd d mmmm yyyy|HH:nn|HH:nn:ss|1||".split("|");
function convertTojQueryDateFormat(srcFormat, expand) {
expand = !expand ? false : true;
switch (srcFormat) {
case "":
case "ShortDate":
return expand ? Globalize.culture().calendars.standard.patterns[srcFormat] : srcFormat;
// return "d"; // "M/d/yyyy"
case "GeneralDate":
return expand ? Globalize.culture().calendars.standard.patterns[srcFormat] : srcFormat;
// return "f"; // "dddd, MMMM dd, yyyy h:mm tt"
case "LongDate":
return expand ? Globalize.culture().calendars.standard.patterns[srcFormat] : srcFormat;
// return "D"; // "dddd, MMMM dd, yyyy"
case "ShortTime":
return expand ? Globalize.culture().calendars.standard.patterns[srcFormat] : srcFormat;
// return "t"; // "h:mm tt"
case "LongTime":
return expand ? Globalize.culture().calendars.standard.patterns[srcFormat] : srcFormat;
// return "T"; // "h:mm:ss tt";
}
srcFormat = srcFormat.replace("AM/PM", "tt");
srcFormat = srcFormat.replace("am/pm", "tt");
srcFormat = srcFormat.replace("M/P", "t");
srcFormat = srcFormat.replace("a/p", "t");
srcFormat = srcFormat.replace(/w/g, "");
srcFormat = srcFormat.replace(/m/g, "M");
srcFormat = srcFormat.replace(/n/g, "m");
return srcFormat;
}
function getLocaleInfo(id)
{
switch (id)
{
case "LanguageAndCountry": return arrayLocaleInfo[0];
case "language": return arrayLocaleInfo[1];
case "country": return arrayLocaleInfo[2];
case "booleanFormat": return arrayLocaleInfo[3];
case "decimalDigits": return parseInt(arrayLocaleInfo[4]);
case "decimalSeparator": return arrayLocaleInfo[5];
case "groupSeparator": return arrayLocaleInfo[6];
case "monthNames": return arrayLocaleInfo[7];
case "monthShortNames": return arrayLocaleInfo[8];
case "weekdayNames": return arrayLocaleInfo[9];
case "weekdayShortNames": return arrayLocaleInfo[10];
case "shortDate": return convertTojQueryDateFormat(arrayLocaleInfo[11], true);
case "longDate": return convertTojQueryDateFormat(arrayLocaleInfo[12], true);
case "shortTime": return convertTojQueryDateFormat(arrayLocaleInfo[13], true);
case "longTime": return convertTojQueryDateFormat(arrayLocaleInfo[14], true);
case "firstWeekDay": return parseInt(arrayLocaleInfo[15]);
case "AMDesignator": return arrayLocaleInfo[16];
case "PMDesignator": return arrayLocaleInfo[17];
}
return "";
}
var listMonths = getLocaleInfo("monthNames").split(";");
listMonths.push("");
var listShortMonths = getLocaleInfo("monthShortNames").split(";");
listShortMonths.push("");
var firstWeekDay = getLocaleInfo("firstWeekDay");
var listWeekdays = getLocaleInfo("weekdayNames").split(";");
var listShortWeekdays = getLocaleInfo("weekdayShortNames").split(";");
var amDesignator = getLocaleInfo("AMDesignator");
var pmDesignator = getLocaleInfo("PMDesignator");
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: getLocaleInfo("LanguageAndCountry"),
// the name of the culture in the english language
englishName: getLocaleInfo("language"),
// the name of the culture in its own language
nativeName: getLocaleInfo("language"),
// 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: getLocaleInfo("language"),
// 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: getLocaleInfo("decimalDigits"),
// string that separates number groups, as in 1,000,000
",": getLocaleInfo("groupSeparator"),
// string that separates a number from the fractional portion, as in 1.99
".": getLocaleInfo("decimalSeparator"),
// 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: getLocaleInfo("decimalDigits"),
// 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
",": getLocaleInfo("groupSeparator"),
// string that separates a number from the fractional portion, as in 1.99
".": getLocaleInfo("decimalSeparator"),
// 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: getLocaleInfo("decimalDigits"),
// 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
",": getLocaleInfo("groupSeparator"),
// string that separates a number from the fractional portion, as in 1.99
".": getLocaleInfo("decimalSeparator"),
// 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_CCSStandart",
// 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: firstWeekDay,
days: {
// full day names
names: listWeekdays,
// abbreviated day names
namesAbbr: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
// shortest day names
namesShort: listShortWeekdays
},
months: {
// full month names (13 months for lunar calendards -- 13th month should be "" if not lunar)
names: listMonths,
// abbreviated month names
namesAbbr: listShortMonths
},
// 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: amDesignator == "" ? null : [amDesignator, amDesignator.toLowerCase(), amDesignator.toUpperCase()],
PM: pmDesignator == "" ? null : [pmDesignator, pmDesignator.toLowerCase(), pmDesignator.toUpperCase()],
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: getLocaleInfo("shortDate"),
"ShortDate": getLocaleInfo("shortDate"),
// long date pattern
D: getLocaleInfo("longDate"),
"LongDate": getLocaleInfo("longDate"),
// short time pattern
t: getLocaleInfo("shortTime"),
"ShortTime": getLocaleInfo("shortTime"),
// long time pattern
T: getLocaleInfo("longTime"),
"LongTime": getLocaleInfo("longTime"),
// 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",
"GeneralDate": getLocaleInfo("shortDate") + ", " + getLocaleInfo("longTime"),
// 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: {
CCS_Now: "Maintenant",
CCS_RequiredField: "La valeur du champ {0} est obligatoire.",
CCS_MinimumLength: "Le nombre de caractères dans le champ {0} ne peut pas être inférieur à {1}.",
CCS_MaximumLength: "Le nombre de caractères dans le champ {0} ne peut pas être supérieur à {1}.",
CCS_IncorrectFormat: "La valeur du champ {0} n'est pas valide. Veuillez utiliser le format : {1}",
CCS_IncorrectValue: "La valeur du champ {0} n'est pas valide."
}
};
Globalize.cultures["default"].calendar = Globalize.cultures["default"].calendars.standard;
Globalize.cultures[getLocaleInfo("LanguageAndCountry")] = Globalize.cultures["default"];
Globalize.cultureSelector = getLocaleInfo("LanguageAndCountry");
//
// 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 (deep) {
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) {
return value | 0;
};
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;
if (!format || !format.length || format === "i") {
var ret;
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();
}
}
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 + "\'.";
break;
}
}
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);
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;
// fall through
case "C":
formatInfo = formatInfo || nf.currency;
// fall 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.
var now = new Date(),
era = getEra(now);
if (year < 100) {
var twoDigitYearMax = cal.twoDigitYearMax;
twoDigitYearMax = typeof twoDigitYearMax === "string" ? new Date().getFullYear() % 100 + parseInt(twoDigitYearMax, 10) : twoDigitYearMax;
var curr = getEraYear(now, cal, era);
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 = "(\\" + cal["/"] + ")";
break;
default:
throw "Invalid date format pattern \'" + m + "\'.";
break;
}
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;
// fall 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 += " ";
// fall 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.cultures[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) {
return a.pri < b.pri ? 1 : -1;
});
// 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) {
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.culture["default"];
};
} (this));
//End JS Globalize