diff --git a/numeral.js b/numeral.js index 22726c9e..b939dc5c 100644 --- a/numeral.js +++ b/numeral.js @@ -7,1007 +7,1143 @@ */ (function (global, factory) { - if (typeof define === 'function' && define.amd) { - define(factory); - } else if (typeof module === 'object' && module.exports) { - module.exports = factory(); - } else { - global.numeral = factory(); - } -}(this, function () { - /************************************ + if (typeof define === "function" && define.amd) { + define(factory); + } else if (typeof module === "object" && module.exports) { + module.exports = factory(); + } else { + global.numeral = factory(); + } +})(this, function () { + /************************************ Variables ************************************/ - var numeral, - _, - VERSION = '2.0.6', - formats = {}, - locales = {}, - defaults = { - currentLocale: 'en', - zeroFormat: null, - nullFormat: null, - defaultFormat: '0,0', - scalePercentBy100: true - }, - options = { - currentLocale: defaults.currentLocale, - zeroFormat: defaults.zeroFormat, - nullFormat: defaults.nullFormat, - defaultFormat: defaults.defaultFormat, - scalePercentBy100: defaults.scalePercentBy100 - }; - + var numeral, + _, + VERSION = "2.0.6", + formats = {}, + locales = {}, + defaults = { + currentLocale: "en", + zeroFormat: null, + nullFormat: null, + defaultFormat: "0,0", + scalePercentBy100: true, + }, + options = { + currentLocale: defaults.currentLocale, + zeroFormat: defaults.zeroFormat, + nullFormat: defaults.nullFormat, + defaultFormat: defaults.defaultFormat, + scalePercentBy100: defaults.scalePercentBy100, + }; - /************************************ + /************************************ Constructors ************************************/ - // Numeral prototype object - function Numeral(input, number) { - this._input = input; - - this._value = number; - } - - numeral = function(input) { - var value, - kind, - unformatFunction, - regexp; - - if (numeral.isNumeral(input)) { - value = input.value(); - } else if (input === 0 || typeof input === 'undefined') { - value = 0; - } else if (input === null || _.isNaN(input)) { - value = null; - } else if (typeof input === 'string') { - if (options.zeroFormat && input === options.zeroFormat) { - value = 0; - } else if (options.nullFormat && input === options.nullFormat || !input.replace(/[^0-9]+/g, '').length) { - value = null; - } else { - for (kind in formats) { - regexp = typeof formats[kind].regexps.unformat === 'function' ? formats[kind].regexps.unformat() : formats[kind].regexps.unformat; - - if (regexp && input.match(regexp)) { - unformatFunction = formats[kind].unformat; - - break; - } - } - - unformatFunction = unformatFunction || numeral._.stringToNumber; - - value = unformatFunction(input); - } - } else { - value = Number(input)|| null; + // Numeral prototype object + function Numeral(input, number) { + this._input = input; + + this._value = number; + } + + numeral = function (input) { + var value, kind, unformatFunction, regexp; + + if (numeral.isNumeral(input)) { + value = input.value(); + } else if (input === 0 || typeof input === "undefined") { + value = 0; + } else if (input === null || _.isNaN(input)) { + value = null; + } else if (typeof input === "string") { + if (options.zeroFormat && input === options.zeroFormat) { + value = 0; + } else if ( + (options.nullFormat && input === options.nullFormat) || + !input.replace(/[^0-9]+/g, "").length + ) { + value = null; + } else { + for (kind in formats) { + regexp = + typeof formats[kind].regexps.unformat === "function" + ? formats[kind].regexps.unformat() + : formats[kind].regexps.unformat; + + if (regexp && input.match(regexp)) { + unformatFunction = formats[kind].unformat; + + break; + } } - return new Numeral(input, value); - }; - - // version number - numeral.version = VERSION; - - // compare numeral object - numeral.isNumeral = function(obj) { - return obj instanceof Numeral; - }; - - // helper functions - numeral._ = _ = { - // formats numbers separators, decimals places, signs, abbreviations - numberToFormat: function(value, format, roundingFunction) { - var locale = locales[numeral.options.currentLocale], - negP = false, - optDec = false, - leadingCount = 0, - abbr = '', - trillion = 1000000000000, - billion = 1000000000, - million = 1000000, - thousand = 1000, - decimal = '', - neg = false, - abbrForce, // force abbreviation - abs, - min, - max, - power, - int, - precision, - signed, - thousands, - output; - - // make sure we never format a null value - value = value || 0; - - abs = Math.abs(value); - - // see if we should use parentheses for negative number or if we should prefix with a sign - // if both are present we default to parentheses - if (numeral._.includes(format, '(')) { - negP = true; - format = format.replace(/[\(|\)]/g, ''); - } else if (numeral._.includes(format, '+') || numeral._.includes(format, '-')) { - signed = numeral._.includes(format, '+') ? format.indexOf('+') : value < 0 ? format.indexOf('-') : -1; - format = format.replace(/[\+|\-]/g, ''); - } - - // see if abbreviation is wanted - if (numeral._.includes(format, 'a')) { - abbrForce = format.match(/a(k|m|b|t)?/); - - abbrForce = abbrForce ? abbrForce[1] : false; - - // check for space before abbreviation - if (numeral._.includes(format, ' a')) { - abbr = ' '; - } - - format = format.replace(new RegExp(abbr + 'a[kmbt]?'), ''); - - if (abs >= trillion && !abbrForce || abbrForce === 't') { - // trillion - abbr += locale.abbreviations.trillion; - value = value / trillion; - } else if (abs < trillion && abs >= billion && !abbrForce || abbrForce === 'b') { - // billion - abbr += locale.abbreviations.billion; - value = value / billion; - } else if (abs < billion && abs >= million && !abbrForce || abbrForce === 'm') { - // million - abbr += locale.abbreviations.million; - value = value / million; - } else if (abs < million && abs >= thousand && !abbrForce || abbrForce === 'k') { - // thousand - abbr += locale.abbreviations.thousand; - value = value / thousand; - } - } - - // check for optional decimals - if (numeral._.includes(format, '[.]')) { - optDec = true; - format = format.replace('[.]', '.'); - } - - // break number and format - int = value.toString().split('.')[0]; - precision = format.split('.')[1]; - thousands = format.indexOf(','); - leadingCount = (format.split('.')[0].split(',')[0].match(/0/g) || []).length; - - if (precision) { - if (numeral._.includes(precision, '[')) { - precision = precision.replace(']', ''); - precision = precision.split('['); - decimal = numeral._.toFixed(value, (precision[0].length + precision[1].length), roundingFunction, precision[1].length); - } else { - decimal = numeral._.toFixed(value, precision.length, roundingFunction); - } - - int = decimal.split('.')[0]; - - if (numeral._.includes(decimal, '.')) { - decimal = locale.delimiters.decimal + decimal.split('.')[1]; - } else { - decimal = ''; - } - - if (optDec && Number(decimal.slice(1)) === 0) { - decimal = ''; - } - } else { - int = numeral._.toFixed(value, 0, roundingFunction); - } - - // check abbreviation again after rounding - if (abbr && !abbrForce && Number(int) >= 1000 && abbr !== locale.abbreviations.trillion) { - int = String(Number(int) / 1000); - - switch (abbr) { - case locale.abbreviations.thousand: - abbr = locale.abbreviations.million; - break; - case locale.abbreviations.million: - abbr = locale.abbreviations.billion; - break; - case locale.abbreviations.billion: - abbr = locale.abbreviations.trillion; - break; - } - } - - - // format number - if (numeral._.includes(int, '-')) { - int = int.slice(1); - neg = true; - } + unformatFunction = unformatFunction || numeral._.stringToNumber; - if (int.length < leadingCount) { - for (var i = leadingCount - int.length; i > 0; i--) { - int = '0' + int; - } - } - - if (thousands > -1) { - int = int.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' + locale.delimiters.thousands); - } - - if (format.indexOf('.') === 0) { - int = ''; - } - - output = int + decimal + (abbr ? abbr : ''); - - if (negP) { - output = (negP && neg ? '(' : '') + output + (negP && neg ? ')' : ''); - } else { - if (signed >= 0) { - output = signed === 0 ? (neg ? '-' : '+') + output : output + (neg ? '-' : '+'); - } else if (neg) { - output = '-' + output; - } - } - - return output; - }, - // unformats numbers separators, decimals places, signs, abbreviations - stringToNumber: function(string) { - var locale = locales[options.currentLocale], - stringOriginal = string, - abbreviations = { - thousand: 3, - million: 6, - billion: 9, - trillion: 12 - }, - abbreviation, - value, - i, - regexp; - - if (options.zeroFormat && string === options.zeroFormat) { - value = 0; - } else if (options.nullFormat && string === options.nullFormat || !string.replace(/[^0-9]+/g, '').length) { - value = null; - } else { - value = 1; - - if (locale.delimiters.decimal !== '.') { - string = string.replace(/\./g, '').replace(locale.delimiters.decimal, '.'); - } - - for (abbreviation in abbreviations) { - regexp = new RegExp('[^a-zA-Z]' + locale.abbreviations[abbreviation] + '(?:\\)|(\\' + locale.currency.symbol + ')?(?:\\))?)?$'); - - if (stringOriginal.match(regexp)) { - value *= Math.pow(10, abbreviations[abbreviation]); - break; - } - } - - // check for negative number - value *= (string.split('-').length + Math.min(string.split('(').length - 1, string.split(')').length - 1)) % 2 ? 1 : -1; - - // remove non numbers - string = string.replace(/[^0-9\.]+/g, ''); - - value *= Number(string); - } - - return value; - }, - isNaN: function(value) { - return typeof value === 'number' && isNaN(value); - }, - includes: function(string, search) { - return string.indexOf(search) !== -1; - }, - insert: function(string, subString, start) { - return string.slice(0, start) + subString + string.slice(start); - }, - reduce: function(array, callback /*, initialValue*/) { - if (this === null) { - throw new TypeError('Array.prototype.reduce called on null or undefined'); - } - - if (typeof callback !== 'function') { - throw new TypeError(callback + ' is not a function'); - } - - var t = Object(array), - len = t.length >>> 0, - k = 0, - value; - - if (arguments.length === 3) { - value = arguments[2]; - } else { - while (k < len && !(k in t)) { - k++; - } - - if (k >= len) { - throw new TypeError('Reduce of empty array with no initial value'); - } - - value = t[k++]; - } - for (; k < len; k++) { - if (k in t) { - value = callback(value, t[k], k, t); - } - } - return value; - }, - /** - * Computes the multiplier necessary to make x >= 1, - * effectively eliminating miscalculations caused by - * finite precision. - */ - multiplier: function (x) { - var parts = x.toString().split('.'); - - return parts.length < 2 ? 1 : Math.pow(10, parts[1].length); - }, - /** - * Given a variable number of arguments, returns the maximum - * multiplier that must be used to normalize an operation involving - * all of them. - */ - correctionFactor: function () { - var args = Array.prototype.slice.call(arguments); - - return args.reduce(function(accum, next) { - var mn = _.multiplier(next); - return accum > mn ? accum : mn; - }, 1); - }, - /** - * Implementation of toFixed() that treats floats more like decimals - * - * Fixes binary rounding issues (eg. (0.615).toFixed(2) === '0.61') that present - * problems for accounting- and finance-related software. - */ - toFixed: function(value, maxDecimals, roundingFunction, optionals) { - var splitValue = value.toString().split('.'), - minDecimals = maxDecimals - (optionals || 0), - boundedPrecision, - optionalsRegExp, - power, - output; - - // Use the smallest precision value possible to avoid errors from floating point representation - if (splitValue.length === 2) { - boundedPrecision = Math.min(Math.max(splitValue[1].length, minDecimals), maxDecimals); - } else { - boundedPrecision = minDecimals; - } - - power = Math.pow(10, boundedPrecision); - - // Multiply up by precision, round accurately, then divide and use native toFixed(): - output = (roundingFunction(value + 'e+' + boundedPrecision) / power).toFixed(boundedPrecision); - - if (optionals > maxDecimals - boundedPrecision) { - optionalsRegExp = new RegExp('\\.?0{1,' + (optionals - (maxDecimals - boundedPrecision)) + '}$'); - output = output.replace(optionalsRegExp, ''); - } - - return output; - } - }; - - // avaliable options - numeral.options = options; - - // avaliable formats - numeral.formats = formats; - - // avaliable formats - numeral.locales = locales; + value = unformatFunction(input); + } + } else { + value = Number(input) || null; + } - // This function sets the current locale. If - // no arguments are passed in, it will simply return the current global - // locale key. - numeral.locale = function(key) { - if (key) { - options.currentLocale = key.toLowerCase(); + return new Numeral(input, value); + }; + + // version number + numeral.version = VERSION; + + // compare numeral object + numeral.isNumeral = function (obj) { + return obj instanceof Numeral; + }; + + // helper functions + numeral._ = _ = { + // formats numbers separators, decimals places, signs, abbreviations + numberToFormat: function (value, format, roundingFunction) { + var locale = locales[numeral.options.currentLocale], + negP = false, + optDec = false, + leadingCount = 0, + abbr = "", + trillion = 1000000000000, + billion = 1000000000, + million = 1000000, + thousand = 1000, + decimal = "", + neg = false, + abbrForce, // force abbreviation + abs, + min, + max, + power, + int, + precision, + signed, + thousands, + output; + + // make sure we never format a null value + value = value || 0; + + abs = Math.abs(value); + + // see if we should use parentheses for negative number or if we should prefix with a sign + // if both are present we default to parentheses + if (numeral._.includes(format, "(")) { + negP = true; + format = format.replace(/[\(|\)]/g, ""); + } else if ( + numeral._.includes(format, "+") || + numeral._.includes(format, "-") + ) { + signed = numeral._.includes(format, "+") + ? format.indexOf("+") + : value < 0 + ? format.indexOf("-") + : -1; + format = format.replace(/[\+|\-]/g, ""); + } + + // see if abbreviation is wanted + if (numeral._.includes(format, "a")) { + abbrForce = format.match(/a(k|m|b|t)?/); + + abbrForce = abbrForce ? abbrForce[1] : false; + + // check for space before abbreviation + if (numeral._.includes(format, " a")) { + abbr = " "; } - return options.currentLocale; - }; - - // This function provides access to the loaded locale data. If - // no arguments are passed in, it will simply return the current - // global locale object. - numeral.localeData = function(key) { - if (!key) { - return locales[options.currentLocale]; + format = format.replace(new RegExp(abbr + "a[kmbt]?"), ""); + + if ((abs >= trillion && !abbrForce) || abbrForce === "t") { + // trillion + abbr += locale.abbreviations.trillion; + value = value / trillion; + } else if ( + (abs < trillion && abs >= billion && !abbrForce) || + abbrForce === "b" + ) { + // billion + abbr += locale.abbreviations.billion; + value = value / billion; + } else if ( + (abs < billion && abs >= million && !abbrForce) || + abbrForce === "m" + ) { + // million + abbr += locale.abbreviations.million; + value = value / million; + } else if ( + (abs < million && abs >= thousand && !abbrForce) || + abbrForce === "k" + ) { + // thousand + abbr += locale.abbreviations.thousand; + value = value / thousand; } - - key = key.toLowerCase(); - - if (!locales[key]) { - throw new Error('Unknown locale : ' + key); + } + + // check for optional decimals + if (numeral._.includes(format, "[.]")) { + optDec = true; + format = format.replace("[.]", "."); + } + + // break number and format + int = value.toString().split(".")[0]; + precision = format.split(".")[1]; + thousands = format.indexOf(","); + leadingCount = (format.split(".")[0].split(",")[0].match(/0/g) || []) + .length; + + if (precision) { + if (numeral._.includes(precision, "[")) { + precision = precision.replace("]", ""); + precision = precision.split("["); + decimal = numeral._.toFixed( + value, + precision[0].length + precision[1].length, + roundingFunction, + precision[1].length + ); + } else { + decimal = numeral._.toFixed( + value, + precision.length, + roundingFunction + ); } - return locales[key]; - }; + int = decimal.split(".")[0]; - numeral.reset = function() { - for (var property in defaults) { - options[property] = defaults[property]; + if (numeral._.includes(decimal, ".")) { + decimal = locale.delimiters.decimal + decimal.split(".")[1]; + } else { + decimal = ""; } - }; - - numeral.zeroFormat = function(format) { - options.zeroFormat = typeof(format) === 'string' ? format : null; - }; - - numeral.nullFormat = function (format) { - options.nullFormat = typeof(format) === 'string' ? format : null; - }; - - numeral.defaultFormat = function(format) { - options.defaultFormat = typeof(format) === 'string' ? format : '0.0'; - }; - - numeral.register = function(type, name, format) { - name = name.toLowerCase(); - if (this[type + 's'][name]) { - throw new TypeError(name + ' ' + type + ' already registered.'); + if (optDec && Number(decimal.slice(1)) === 0) { + decimal = ""; } - - this[type + 's'][name] = format; - - return format; - }; - - - numeral.validate = function(val, culture) { - var _decimalSep, - _thousandSep, - _currSymbol, - _valArray, - _abbrObj, - _thousandRegEx, - localeData, - temp; - - //coerce val to string - if (typeof val !== 'string') { - val += ''; - - if (console.warn) { - console.warn('Numeral.js: Value is not string. It has been co-erced to: ', val); - } + } else { + int = numeral._.toFixed(value, 0, roundingFunction); + } + + // check abbreviation again after rounding + if ( + abbr && + !abbrForce && + Number(int) >= 1000 && + abbr !== locale.abbreviations.trillion + ) { + int = String(Number(int) / 1000); + + switch (abbr.trim()) { + case locale.abbreviations.thousand: + abbr = " " + locale.abbreviations.million; + break; + case locale.abbreviations.million: + abbr = " " + locale.abbreviations.billion; + break; + case locale.abbreviations.billion: + abbr = " " + locale.abbreviations.trillion; + break; } + } - //trim whitespaces from either sides - val = val.trim(); + // format number + if (numeral._.includes(int, "-")) { + int = int.slice(1); + neg = true; + } - //if val is just digits return true - if (!!val.match(/^\d+$/)) { - return true; + if (int.length < leadingCount) { + for (var i = leadingCount - int.length; i > 0; i--) { + int = "0" + int; } - - //if val is empty return false - if (val === '') { - return false; + } + + if (thousands > -1) { + int = int + .toString() + .replace( + /(\d)(?=(\d{3})+(?!\d))/g, + "$1" + locale.delimiters.thousands + ); + } + + if (format.indexOf(".") === 0) { + int = ""; + } + + output = int + decimal + (abbr ? abbr : ""); + + if (negP) { + output = (negP && neg ? "(" : "") + output + (negP && neg ? ")" : ""); + } else { + if (signed >= 0) { + output = + signed === 0 + ? (neg ? "-" : "+") + output + : output + (neg ? "-" : "+"); + } else if (neg) { + output = "-" + output; } - - //get the decimal and thousands separator from numeral.localeData - try { - //check if the culture is understood by numeral. if not, default it to current locale - localeData = numeral.localeData(culture); - } catch (e) { - localeData = numeral.localeData(numeral.locale()); + } + + return output; + }, + // unformats numbers separators, decimals places, signs, abbreviations + stringToNumber: function (string) { + var locale = locales[options.currentLocale], + stringOriginal = string, + abbreviations = { + thousand: 3, + million: 6, + billion: 9, + trillion: 12, + }, + abbreviation, + value, + i, + regexp; + + if (options.zeroFormat && string === options.zeroFormat) { + value = 0; + } else if ( + (options.nullFormat && string === options.nullFormat) || + !string.replace(/[^0-9]+/g, "").length + ) { + value = null; + } else { + value = 1; + + if (locale.delimiters.decimal !== ".") { + string = string + .replace(/\./g, "") + .replace(locale.delimiters.decimal, "."); } - //setup the delimiters and currency symbol based on culture/locale - _currSymbol = localeData.currency.symbol; - _abbrObj = localeData.abbreviations; - _decimalSep = localeData.delimiters.decimal; - if (localeData.delimiters.thousands === '.') { - _thousandSep = '\\.'; - } else { - _thousandSep = localeData.delimiters.thousands; + for (abbreviation in abbreviations) { + regexp = new RegExp( + "[^a-zA-Z]" + + locale.abbreviations[abbreviation] + + "(?:\\)|(\\" + + locale.currency.symbol + + ")?(?:\\))?)?$" + ); + + if (stringOriginal.match(regexp)) { + value *= Math.pow(10, abbreviations[abbreviation]); + break; + } } - // validating currency symbol - temp = val.match(/^[^\d]+/); - if (temp !== null) { - val = val.substr(1); - if (temp[0] !== _currSymbol) { - return false; - } + // check for negative number + value *= + (string.split("-").length + + Math.min( + string.split("(").length - 1, + string.split(")").length - 1 + )) % + 2 + ? 1 + : -1; + + // remove non numbers + string = string.replace(/[^0-9\.]+/g, ""); + + value *= Number(string); + } + + return value; + }, + isNaN: function (value) { + return typeof value === "number" && isNaN(value); + }, + includes: function (string, search) { + return string.indexOf(search) !== -1; + }, + insert: function (string, subString, start) { + return string.slice(0, start) + subString + string.slice(start); + }, + reduce: function (array, callback /*, initialValue*/) { + if (this === null) { + throw new TypeError( + "Array.prototype.reduce called on null or undefined" + ); + } + + if (typeof callback !== "function") { + throw new TypeError(callback + " is not a function"); + } + + var t = Object(array), + len = t.length >>> 0, + k = 0, + value; + + if (arguments.length === 3) { + value = arguments[2]; + } else { + while (k < len && !(k in t)) { + k++; } - //validating abbreviation symbol - temp = val.match(/[^\d]+$/); - if (temp !== null) { - val = val.slice(0, -1); - if (temp[0] !== _abbrObj.thousand && temp[0] !== _abbrObj.million && temp[0] !== _abbrObj.billion && temp[0] !== _abbrObj.trillion) { - return false; - } + if (k >= len) { + throw new TypeError("Reduce of empty array with no initial value"); } - _thousandRegEx = new RegExp(_thousandSep + '{2}'); - - if (!val.match(/[^\d.,]/g)) { - _valArray = val.split(_decimalSep); - if (_valArray.length > 2) { - return false; - } else { - if (_valArray.length < 2) { - return ( !! _valArray[0].match(/^\d+.*\d$/) && !_valArray[0].match(_thousandRegEx)); - } else { - if (_valArray[0].length === 1) { - return ( !! _valArray[0].match(/^\d+$/) && !_valArray[0].match(_thousandRegEx) && !! _valArray[1].match(/^\d+$/)); - } else { - return ( !! _valArray[0].match(/^\d+.*\d$/) && !_valArray[0].match(_thousandRegEx) && !! _valArray[1].match(/^\d+$/)); - } - } - } + value = t[k++]; + } + for (; k < len; k++) { + if (k in t) { + value = callback(value, t[k], k, t); } + } + return value; + }, + /** + * Computes the multiplier necessary to make x >= 1, + * effectively eliminating miscalculations caused by + * finite precision. + */ + multiplier: function (x) { + var parts = x.toString().split("."); + + return parts.length < 2 ? 1 : Math.pow(10, parts[1].length); + }, + /** + * Given a variable number of arguments, returns the maximum + * multiplier that must be used to normalize an operation involving + * all of them. + */ + correctionFactor: function () { + var args = Array.prototype.slice.call(arguments); + + return args.reduce(function (accum, next) { + var mn = _.multiplier(next); + return accum > mn ? accum : mn; + }, 1); + }, + /** + * Implementation of toFixed() that treats floats more like decimals + * + * Fixes binary rounding issues (eg. (0.615).toFixed(2) === '0.61') that present + * problems for accounting- and finance-related software. + */ + toFixed: function (value, maxDecimals, roundingFunction, optionals) { + var splitValue = value.toString().split("."), + minDecimals = maxDecimals - (optionals || 0), + boundedPrecision, + optionalsRegExp, + power, + output; + + // Use the smallest precision value possible to avoid errors from floating point representation + if (splitValue.length === 2) { + boundedPrecision = Math.min( + Math.max(splitValue[1].length, minDecimals), + maxDecimals + ); + } else { + boundedPrecision = minDecimals; + } + + power = Math.pow(10, boundedPrecision); + + // Multiply up by precision, round accurately, then divide and use native toFixed(): + output = ( + roundingFunction(value + "e+" + boundedPrecision) / power + ).toFixed(boundedPrecision); + + if (optionals > maxDecimals - boundedPrecision) { + optionalsRegExp = new RegExp( + "\\.?0{1," + (optionals - (maxDecimals - boundedPrecision)) + "}$" + ); + output = output.replace(optionalsRegExp, ""); + } + + return output; + }, + }; + + // avaliable options + numeral.options = options; + + // avaliable formats + numeral.formats = formats; + + // avaliable formats + numeral.locales = locales; + + // This function sets the current locale. If + // no arguments are passed in, it will simply return the current global + // locale key. + numeral.locale = function (key) { + if (key) { + options.currentLocale = key.toLowerCase(); + } - return false; - }; + return options.currentLocale; + }; + // This function provides access to the loaded locale data. If + // no arguments are passed in, it will simply return the current + // global locale object. + numeral.localeData = function (key) { + if (!key) { + return locales[options.currentLocale]; + } - /************************************ - Numeral Prototype - ************************************/ + key = key.toLowerCase(); - numeral.fn = Numeral.prototype = { - clone: function() { - return numeral(this); - }, - format: function(inputString, roundingFunction) { - var value = this._value, - format = inputString || options.defaultFormat, - kind, - output, - formatFunction; + if (!locales[key]) { + throw new Error("Unknown locale : " + key); + } - // make sure we have a roundingFunction - roundingFunction = roundingFunction || Math.round; + return locales[key]; + }; - // format based on value - if (value === 0 && options.zeroFormat !== null) { - output = options.zeroFormat; - } else if (value === null && options.nullFormat !== null) { - output = options.nullFormat; - } else { - for (kind in formats) { - if (format.match(formats[kind].regexps.format)) { - formatFunction = formats[kind].format; + numeral.reset = function () { + for (var property in defaults) { + options[property] = defaults[property]; + } + }; - break; - } - } + numeral.zeroFormat = function (format) { + options.zeroFormat = typeof format === "string" ? format : null; + }; - formatFunction = formatFunction || numeral._.numberToFormat; + numeral.nullFormat = function (format) { + options.nullFormat = typeof format === "string" ? format : null; + }; - output = formatFunction(value, format, roundingFunction); - } + numeral.defaultFormat = function (format) { + options.defaultFormat = typeof format === "string" ? format : "0.0"; + }; - return output; - }, - value: function() { - return this._value; - }, - input: function() { - return this._input; - }, - set: function(value) { - this._value = Number(value); + numeral.register = function (type, name, format) { + name = name.toLowerCase(); - return this; - }, - add: function(value) { - var corrFactor = _.correctionFactor.call(null, this._value, value); + if (this[type + "s"][name]) { + throw new TypeError(name + " " + type + " already registered."); + } - function cback(accum, curr, currI, O) { - return accum + Math.round(corrFactor * curr); - } + this[type + "s"][name] = format; + + return format; + }; + + numeral.validate = function (val, culture) { + var _decimalSep, + _thousandSep, + _currSymbol, + _valArray, + _abbrObj, + _thousandRegEx, + localeData, + temp; + + //coerce val to string + if (typeof val !== "string") { + val += ""; + + if (console.warn) { + console.warn( + "Numeral.js: Value is not string. It has been co-erced to: ", + val + ); + } + } - this._value = _.reduce([this._value, value], cback, 0) / corrFactor; + //trim whitespaces from either sides + val = val.trim(); - return this; - }, - subtract: function(value) { - var corrFactor = _.correctionFactor.call(null, this._value, value); + //if val is just digits return true + if (!!val.match(/^\d+$/)) { + return true; + } - function cback(accum, curr, currI, O) { - return accum - Math.round(corrFactor * curr); - } + //if val is empty return false + if (val === "") { + return false; + } - this._value = _.reduce([value], cback, Math.round(this._value * corrFactor)) / corrFactor; + //get the decimal and thousands separator from numeral.localeData + try { + //check if the culture is understood by numeral. if not, default it to current locale + localeData = numeral.localeData(culture); + } catch (e) { + localeData = numeral.localeData(numeral.locale()); + } - return this; - }, - multiply: function(value) { - function cback(accum, curr, currI, O) { - var corrFactor = _.correctionFactor(accum, curr); - return Math.round(accum * corrFactor) * Math.round(curr * corrFactor) / Math.round(corrFactor * corrFactor); - } + //setup the delimiters and currency symbol based on culture/locale + _currSymbol = localeData.currency.symbol; + _abbrObj = localeData.abbreviations; + _decimalSep = localeData.delimiters.decimal; + if (localeData.delimiters.thousands === ".") { + _thousandSep = "\\."; + } else { + _thousandSep = localeData.delimiters.thousands; + } - this._value = _.reduce([this._value, value], cback, 1); + // validating currency symbol + temp = val.match(/^[^\d]+/); + if (temp !== null) { + val = val.substr(1); + if (temp[0] !== _currSymbol) { + return false; + } + } - return this; - }, - divide: function(value) { - function cback(accum, curr, currI, O) { - var corrFactor = _.correctionFactor(accum, curr); - return Math.round(accum * corrFactor) / Math.round(curr * corrFactor); - } + //validating abbreviation symbol + temp = val.match(/[^\d]+$/); + if (temp !== null) { + val = val.slice(0, -1); + if ( + temp[0] !== _abbrObj.thousand && + temp[0] !== _abbrObj.million && + temp[0] !== _abbrObj.billion && + temp[0] !== _abbrObj.trillion + ) { + return false; + } + } - this._value = _.reduce([this._value, value], cback); + _thousandRegEx = new RegExp(_thousandSep + "{2}"); - return this; - }, - difference: function(value) { - return Math.abs(numeral(this._value).subtract(value).value()); + if (!val.match(/[^\d.,]/g)) { + _valArray = val.split(_decimalSep); + if (_valArray.length > 2) { + return false; + } else { + if (_valArray.length < 2) { + return ( + !!_valArray[0].match(/^\d+.*\d$/) && + !_valArray[0].match(_thousandRegEx) + ); + } else { + if (_valArray[0].length === 1) { + return ( + !!_valArray[0].match(/^\d+$/) && + !_valArray[0].match(_thousandRegEx) && + !!_valArray[1].match(/^\d+$/) + ); + } else { + return ( + !!_valArray[0].match(/^\d+.*\d$/) && + !_valArray[0].match(_thousandRegEx) && + !!_valArray[1].match(/^\d+$/) + ); + } } - }; + } + } - /************************************ - Default Locale && Format + return false; + }; + + /************************************ + Numeral Prototype ************************************/ - numeral.register('locale', 'en', { - delimiters: { - thousands: ',', - decimal: '.' - }, - abbreviations: { - thousand: 'k', - million: 'm', - billion: 'b', - trillion: 't' - }, - ordinal: function(number) { - var b = number % 10; - return (~~(number % 100 / 10) === 1) ? 'th' : - (b === 1) ? 'st' : - (b === 2) ? 'nd' : - (b === 3) ? 'rd' : 'th'; - }, - currency: { - symbol: '$' + numeral.fn = Numeral.prototype = { + clone: function () { + return numeral(this); + }, + format: function (inputString, roundingFunction) { + var value = this._value, + format = inputString || options.defaultFormat, + kind, + output, + formatFunction; + + // make sure we have a roundingFunction + roundingFunction = roundingFunction || Math.round; + + // format based on value + if (value === 0 && options.zeroFormat !== null) { + output = options.zeroFormat; + } else if (value === null && options.nullFormat !== null) { + output = options.nullFormat; + } else { + for (kind in formats) { + if (format.match(formats[kind].regexps.format)) { + formatFunction = formats[kind].format; + + break; + } } - }); - - - -(function() { - numeral.register('format', 'bps', { - regexps: { - format: /(BPS)/, - unformat: /(BPS)/ - }, - format: function(value, format, roundingFunction) { - var space = numeral._.includes(format, ' BPS') ? ' ' : '', - output; - - value = value * 10000; - - // check for space before BPS - format = format.replace(/\s?BPS/, ''); - - output = numeral._.numberToFormat(value, format, roundingFunction); - - if (numeral._.includes(output, ')')) { - output = output.split(''); - - output.splice(-1, 0, space + 'BPS'); - - output = output.join(''); - } else { - output = output + space + 'BPS'; - } - - return output; - }, - unformat: function(string) { - return +(numeral._.stringToNumber(string) * 0.0001).toFixed(15); - } - }); -})(); - - -(function() { - var decimal = { - base: 1000, - suffixes: ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] - }, - binary = { - base: 1024, - suffixes: ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'] - }; - - var allSuffixes = decimal.suffixes.concat(binary.suffixes.filter(function (item) { - return decimal.suffixes.indexOf(item) < 0; - })); - var unformatRegex = allSuffixes.join('|'); - // Allow support for BPS (http://www.investopedia.com/terms/b/basispoint.asp) - unformatRegex = '(' + unformatRegex.replace('B', 'B(?!PS)') + ')'; - - numeral.register('format', 'bytes', { - regexps: { - format: /([0\s]i?b)/, - unformat: new RegExp(unformatRegex) - }, - format: function(value, format, roundingFunction) { - var output, - bytes = numeral._.includes(format, 'ib') ? binary : decimal, - suffix = numeral._.includes(format, ' b') || numeral._.includes(format, ' ib') ? ' ' : '', - power, - min, - max; - - // check for space before - format = format.replace(/\s?i?b/, ''); - - for (power = 0; power <= bytes.suffixes.length; power++) { - min = Math.pow(bytes.base, power); - max = Math.pow(bytes.base, power + 1); - - if (value === null || value === 0 || value >= min && value < max) { - suffix += bytes.suffixes[power]; - - if (min > 0) { - value = value / min; - } - - break; - } - } - - output = numeral._.numberToFormat(value, format, roundingFunction); - - return output + suffix; - }, - unformat: function(string) { - var value = numeral._.stringToNumber(string), - power, - bytesMultiplier; - if (value) { - for (power = decimal.suffixes.length - 1; power >= 0; power--) { - if (numeral._.includes(string, decimal.suffixes[power])) { - bytesMultiplier = Math.pow(decimal.base, power); - - break; - } - - if (numeral._.includes(string, binary.suffixes[power])) { - bytesMultiplier = Math.pow(binary.base, power); + formatFunction = formatFunction || numeral._.numberToFormat; + + output = formatFunction(value, format, roundingFunction); + } + + return output; + }, + value: function () { + return this._value; + }, + input: function () { + return this._input; + }, + set: function (value) { + this._value = Number(value); + + return this; + }, + add: function (value) { + var corrFactor = _.correctionFactor.call(null, this._value, value); + + function cback(accum, curr, currI, O) { + return accum + Math.round(corrFactor * curr); + } + + this._value = _.reduce([this._value, value], cback, 0) / corrFactor; + + return this; + }, + subtract: function (value) { + var corrFactor = _.correctionFactor.call(null, this._value, value); + + function cback(accum, curr, currI, O) { + return accum - Math.round(corrFactor * curr); + } + + this._value = + _.reduce([value], cback, Math.round(this._value * corrFactor)) / + corrFactor; + + return this; + }, + multiply: function (value) { + function cback(accum, curr, currI, O) { + var corrFactor = _.correctionFactor(accum, curr); + return ( + (Math.round(accum * corrFactor) * Math.round(curr * corrFactor)) / + Math.round(corrFactor * corrFactor) + ); + } + + this._value = _.reduce([this._value, value], cback, 1); + + return this; + }, + divide: function (value) { + function cback(accum, curr, currI, O) { + var corrFactor = _.correctionFactor(accum, curr); + return Math.round(accum * corrFactor) / Math.round(curr * corrFactor); + } + + this._value = _.reduce([this._value, value], cback); + + return this; + }, + difference: function (value) { + return Math.abs(numeral(this._value).subtract(value).value()); + }, + }; + + /************************************ + Default Locale && Format + ************************************/ - break; - } - } + numeral.register("locale", "en", { + delimiters: { + thousands: ",", + decimal: ".", + }, + abbreviations: { + thousand: "k", + million: "m", + billion: "b", + trillion: "t", + }, + ordinal: function (number) { + var b = number % 10; + return ~~((number % 100) / 10) === 1 + ? "th" + : b === 1 + ? "st" + : b === 2 + ? "nd" + : b === 3 + ? "rd" + : "th"; + }, + currency: { + symbol: "$", + }, + }); + + (function () { + numeral.register("format", "bps", { + regexps: { + format: /(BPS)/, + unformat: /(BPS)/, + }, + format: function (value, format, roundingFunction) { + var space = numeral._.includes(format, " BPS") ? " " : "", + output; + + value = value * 10000; + + // check for space before BPS + format = format.replace(/\s?BPS/, ""); + + output = numeral._.numberToFormat(value, format, roundingFunction); + + if (numeral._.includes(output, ")")) { + output = output.split(""); + + output.splice(-1, 0, space + "BPS"); + + output = output.join(""); + } else { + output = output + space + "BPS"; + } - value *= (bytesMultiplier || 1); + return output; + }, + unformat: function (string) { + return +(numeral._.stringToNumber(string) * 0.0001).toFixed(15); + }, + }); + })(); + + (function () { + var decimal = { + base: 1000, + suffixes: ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"], + }, + binary = { + base: 1024, + suffixes: ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"], + }; + + var allSuffixes = decimal.suffixes.concat( + binary.suffixes.filter(function (item) { + return decimal.suffixes.indexOf(item) < 0; + }) + ); + var unformatRegex = allSuffixes.join("|"); + // Allow support for BPS (http://www.investopedia.com/terms/b/basispoint.asp) + unformatRegex = "(" + unformatRegex.replace("B", "B(?!PS)") + ")"; + + numeral.register("format", "bytes", { + regexps: { + format: /([0\s]i?b)/, + unformat: new RegExp(unformatRegex), + }, + format: function (value, format, roundingFunction) { + var output, + bytes = numeral._.includes(format, "ib") ? binary : decimal, + suffix = + numeral._.includes(format, " b") || + numeral._.includes(format, " ib") + ? " " + : "", + power, + min, + max; + + // check for space before + format = format.replace(/\s?i?b/, ""); + + for (power = 0; power <= bytes.suffixes.length; power++) { + min = Math.pow(bytes.base, power); + max = Math.pow(bytes.base, power + 1); + + if (value === null || value === 0 || (value >= min && value < max)) { + suffix += bytes.suffixes[power]; + + if (min > 0) { + value = value / min; } - return value; + break; + } } - }); -})(); - -(function() { - numeral.register('format', 'currency', { - regexps: { - format: /(\$)/ - }, - format: function(value, format, roundingFunction) { - var locale = numeral.locales[numeral.options.currentLocale], - symbols = { - before: format.match(/^([\+|\-|\(|\s|\$]*)/)[0], - after: format.match(/([\+|\-|\)|\s|\$]*)$/)[0] - }, - output, - symbol, - i; + output = numeral._.numberToFormat(value, format, roundingFunction); - // strip format of spaces and $ - format = format.replace(/\s?\$\s?/, ''); + return output + suffix; + }, + unformat: function (string) { + var value = numeral._.stringToNumber(string), + power, + bytesMultiplier; - // format the number - output = numeral._.numberToFormat(value, format, roundingFunction); + if (value) { + for (power = decimal.suffixes.length - 1; power >= 0; power--) { + if (numeral._.includes(string, decimal.suffixes[power])) { + bytesMultiplier = Math.pow(decimal.base, power); - // update the before and after based on value - if (value >= 0) { - symbols.before = symbols.before.replace(/[\-\(]/, ''); - symbols.after = symbols.after.replace(/[\-\)]/, ''); - } else if (value < 0 && (!numeral._.includes(symbols.before, '-') && !numeral._.includes(symbols.before, '('))) { - symbols.before = '-' + symbols.before; + break; } - // loop through each before symbol - for (i = 0; i < symbols.before.length; i++) { - symbol = symbols.before[i]; - - switch (symbol) { - case '$': - output = numeral._.insert(output, locale.currency.symbol, i); - break; - case ' ': - output = numeral._.insert(output, ' ', i + locale.currency.symbol.length - 1); - break; - } - } + if (numeral._.includes(string, binary.suffixes[power])) { + bytesMultiplier = Math.pow(binary.base, power); - // loop through each after symbol - for (i = symbols.after.length - 1; i >= 0; i--) { - symbol = symbols.after[i]; - - switch (symbol) { - case '$': - output = i === symbols.after.length - 1 ? output + locale.currency.symbol : numeral._.insert(output, locale.currency.symbol, -(symbols.after.length - (1 + i))); - break; - case ' ': - output = i === symbols.after.length - 1 ? output + ' ' : numeral._.insert(output, ' ', -(symbols.after.length - (1 + i) + locale.currency.symbol.length - 1)); - break; - } + break; } + } - - return output; + value *= bytesMultiplier || 1; } - }); -})(); - -(function() { - numeral.register('format', 'exponential', { - regexps: { - format: /(e\+|e-)/, - unformat: /(e\+|e-)/ - }, - format: function(value, format, roundingFunction) { - var output, - exponential = typeof value === 'number' && !numeral._.isNaN(value) ? value.toExponential() : '0e+0', - parts = exponential.split('e'); - - format = format.replace(/e[\+|\-]{1}0/, ''); - - output = numeral._.numberToFormat(Number(parts[0]), format, roundingFunction); - - return output + 'e' + parts[1]; - }, - unformat: function(string) { - var parts = numeral._.includes(string, 'e+') ? string.split('e+') : string.split('e-'), - value = Number(parts[0]), - power = Number(parts[1]); + return value; + }, + }); + })(); + + (function () { + numeral.register("format", "currency", { + regexps: { + format: /(\$)/, + }, + format: function (value, format, roundingFunction) { + var locale = numeral.locales[numeral.options.currentLocale], + symbols = { + before: format.match(/^([\+|\-|\(|\s|\$]*)/)[0], + after: format.match(/([\+|\-|\)|\s|\$]*)$/)[0], + }, + output, + symbol, + i; + + // strip format of spaces and $ + format = format.replace(/\s?\$\s?/, ""); + + // format the number + output = numeral._.numberToFormat(value, format, roundingFunction); + + // update the before and after based on value + if (value >= 0) { + symbols.before = symbols.before.replace(/[\-\(]/, ""); + symbols.after = symbols.after.replace(/[\-\)]/, ""); + } else if ( + value < 0 && + !numeral._.includes(symbols.before, "-") && + !numeral._.includes(symbols.before, "(") + ) { + symbols.before = "-" + symbols.before; + } - power = numeral._.includes(string, 'e-') ? power *= -1 : power; + // loop through each before symbol + for (i = 0; i < symbols.before.length; i++) { + symbol = symbols.before[i]; - function cback(accum, curr, currI, O) { - var corrFactor = numeral._.correctionFactor(accum, curr), - num = (accum * corrFactor) * (curr * corrFactor) / (corrFactor * corrFactor); - return num; - } + switch (symbol) { + case "$": + output = numeral._.insert(output, locale.currency.symbol, i); + break; + case " ": + output = numeral._.insert( + output, + " ", + i + locale.currency.symbol.length - 1 + ); + break; + } + } - return numeral._.reduce([value, Math.pow(10, power)], cback, 1); + // loop through each after symbol + for (i = symbols.after.length - 1; i >= 0; i--) { + symbol = symbols.after[i]; + + switch (symbol) { + case "$": + output = + i === symbols.after.length - 1 + ? output + locale.currency.symbol + : numeral._.insert( + output, + locale.currency.symbol, + -(symbols.after.length - (1 + i)) + ); + break; + case " ": + output = + i === symbols.after.length - 1 + ? output + " " + : numeral._.insert( + output, + " ", + -( + symbols.after.length - + (1 + i) + + locale.currency.symbol.length - + 1 + ) + ); + break; + } } + + return output; + }, }); -})(); + })(); + + (function () { + numeral.register("format", "exponential", { + regexps: { + format: /(e\+|e-)/, + unformat: /(e\+|e-)/, + }, + format: function (value, format, roundingFunction) { + var output, + exponential = + typeof value === "number" && !numeral._.isNaN(value) + ? value.toExponential() + : "0e+0", + parts = exponential.split("e"); + + format = format.replace(/e[\+|\-]{1}0/, ""); + + output = numeral._.numberToFormat( + Number(parts[0]), + format, + roundingFunction + ); + + return output + "e" + parts[1]; + }, + unformat: function (string) { + var parts = numeral._.includes(string, "e+") + ? string.split("e+") + : string.split("e-"), + value = Number(parts[0]), + power = Number(parts[1]); + + power = numeral._.includes(string, "e-") ? (power *= -1) : power; + + function cback(accum, curr, currI, O) { + var corrFactor = numeral._.correctionFactor(accum, curr), + num = + (accum * corrFactor * (curr * corrFactor)) / + (corrFactor * corrFactor); + return num; + } + return numeral._.reduce([value, Math.pow(10, power)], cback, 1); + }, + }); + })(); -(function() { - numeral.register('format', 'ordinal', { - regexps: { - format: /(o)/ - }, - format: function(value, format, roundingFunction) { - var locale = numeral.locales[numeral.options.currentLocale], - output, - ordinal = numeral._.includes(format, ' o') ? ' ' : ''; + (function () { + numeral.register("format", "ordinal", { + regexps: { + format: /(o)/, + }, + format: function (value, format, roundingFunction) { + var locale = numeral.locales[numeral.options.currentLocale], + output, + ordinal = numeral._.includes(format, " o") ? " " : ""; - // check for space before - format = format.replace(/\s?o/, ''); + // check for space before + format = format.replace(/\s?o/, ""); - ordinal += locale.ordinal(value); + ordinal += locale.ordinal(value); - output = numeral._.numberToFormat(value, format, roundingFunction); + output = numeral._.numberToFormat(value, format, roundingFunction); - return output + ordinal; - } + return output + ordinal; + }, }); -})(); - - -(function() { - numeral.register('format', 'percentage', { - regexps: { - format: /(%)/, - unformat: /(%)/ - }, - format: function(value, format, roundingFunction) { - var space = numeral._.includes(format, ' %') ? ' ' : '', - output; - - if (numeral.options.scalePercentBy100) { - value = value * 100; - } + })(); + + (function () { + numeral.register("format", "percentage", { + regexps: { + format: /(%)/, + unformat: /(%)/, + }, + format: function (value, format, roundingFunction) { + var space = numeral._.includes(format, " %") ? " " : "", + output; + + if (numeral.options.scalePercentBy100) { + value = value * 100; + } - // check for space before % - format = format.replace(/\s?\%/, ''); + // check for space before % + format = format.replace(/\s?\%/, ""); - output = numeral._.numberToFormat(value, format, roundingFunction); + output = numeral._.numberToFormat(value, format, roundingFunction); - if (numeral._.includes(output, ')')) { - output = output.split(''); + if (numeral._.includes(output, ")")) { + output = output.split(""); - output.splice(-1, 0, space + '%'); + output.splice(-1, 0, space + "%"); - output = output.join(''); - } else { - output = output + space + '%'; - } + output = output.join(""); + } else { + output = output + space + "%"; + } - return output; - }, - unformat: function(string) { - var number = numeral._.stringToNumber(string); - if (numeral.options.scalePercentBy100) { - return number * 0.01; - } - return number; + return output; + }, + unformat: function (string) { + var number = numeral._.stringToNumber(string); + if (numeral.options.scalePercentBy100) { + return number * 0.01; } + return number; + }, }); -})(); - - -(function() { - numeral.register('format', 'time', { - regexps: { - format: /(:)/, - unformat: /(:)/ - }, - format: function(value, format, roundingFunction) { - var hours = Math.floor(value / 60 / 60), - minutes = Math.floor((value - (hours * 60 * 60)) / 60), - seconds = Math.round(value - (hours * 60 * 60) - (minutes * 60)); - - return hours + ':' + (minutes < 10 ? '0' + minutes : minutes) + ':' + (seconds < 10 ? '0' + seconds : seconds); - }, - unformat: function(string) { - var timeArray = string.split(':'), - seconds = 0; - - // turn hours and minutes into seconds and add them all up - if (timeArray.length === 3) { - // hours - seconds = seconds + (Number(timeArray[0]) * 60 * 60); - // minutes - seconds = seconds + (Number(timeArray[1]) * 60); - // seconds - seconds = seconds + Number(timeArray[2]); - } else if (timeArray.length === 2) { - // minutes - seconds = seconds + (Number(timeArray[0]) * 60); - // seconds - seconds = seconds + Number(timeArray[1]); - } - return Number(seconds); + })(); + + (function () { + numeral.register("format", "time", { + regexps: { + format: /(:)/, + unformat: /(:)/, + }, + format: function (value, format, roundingFunction) { + var hours = Math.floor(value / 60 / 60), + minutes = Math.floor((value - hours * 60 * 60) / 60), + seconds = Math.round(value - hours * 60 * 60 - minutes * 60); + + return ( + hours + + ":" + + (minutes < 10 ? "0" + minutes : minutes) + + ":" + + (seconds < 10 ? "0" + seconds : seconds) + ); + }, + unformat: function (string) { + var timeArray = string.split(":"), + seconds = 0; + + // turn hours and minutes into seconds and add them all up + if (timeArray.length === 3) { + // hours + seconds = seconds + Number(timeArray[0]) * 60 * 60; + // minutes + seconds = seconds + Number(timeArray[1]) * 60; + // seconds + seconds = seconds + Number(timeArray[2]); + } else if (timeArray.length === 2) { + // minutes + seconds = seconds + Number(timeArray[0]) * 60; + // seconds + seconds = seconds + Number(timeArray[1]); } + return Number(seconds); + }, }); -})(); + })(); -return numeral; -})); + return numeral; +});