Last active
October 3, 2016 11:37
-
-
Save esquinas/94c6c97a4559183087d66ba3538eb79c to your computer and use it in GitHub Desktop.
ISO (SI) & APA style number formatting are used here to make a fail-safe, unambiguous way to render numbers for international and multicultural contexts.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Number.formatISOAPA returns a correctly SI+APA formatted number. | |
// (SI, System Internationale) ISO 31-0 & APA style EXPLANATION: | |
// <https://en.wikipedia.org/wiki/ISO_31-0#Numbers> | |
// ISO 31-0: The decimal sign is either the comma on the line | |
// or the point on the line. Both "1,33" & "1.33" are valid. | |
// ISO 31-0: Do not use "." nor "," for thousand separators. | |
// Both "1,000.00" "1.000,00" are INVALID. | |
// ISO 31-0: For numbers whose magnitude is less than 1, the decimal | |
// sign should be preceded by a zero. "0.5" instead of ".5" | |
// APA style: Psychologically, there is no need to group numbers with | |
// just 4 figures (i.e. are less than "10 000.00"). | |
// "9999.99" and "2016" instead of "9 999.99" or "2 016". | |
// Usage: | |
// var num = 12345.6; | |
// English system: `num.formatISOAPA(2, "english");` | |
// returns => "12 345.60" | |
// French system: `num.formatISOAPA(2, "french");` | |
// returns => "12 345,60" | |
// English with ruby-like thousands separator: | |
// `num.formatISOAPA(2, ".", "_");` | |
// returns => "12_345.60" | |
Number.prototype.formatISOAPA = function(decimalPrecision, | |
decimalMark, | |
thousandsSeparator) { | |
"use strict"; | |
// Sanitize input. | |
var n = (this + "").replace(/[^0-9+Ee.]/g, ""); | |
// The dash or the minus sign is the default negative mark. | |
var neg; | |
if (this < 0) { | |
neg = "-"; | |
} else { | |
neg = ""; | |
} | |
n = (!isFinite(+n)) ? 0 : +n; | |
// Zero is the default decimal precision. | |
var pre; | |
if (!isFinite(+decimalPrecision)) { | |
pre = 0; | |
} else { | |
pre = Math.abs(decimalPrecision); | |
} | |
// The dot is the default decimal mark. Comma is OK. | |
var dec; | |
// User can enter "," as the desired decimalMark, but also: | |
// "FRENCH", "es_sp", "comma", "coma", or alternatively: | |
// "English standard", "en", "dot", "point" or "pt". | |
var decMarkCommaPatt = /^es|^fr|^com|\,/i; | |
var decMarkDotPatt = /^en|^do?t|^p\w*t|\./i; | |
if ((typeof decimalMark === "undefined") || | |
(decMarkDotPatt.test(decimalMark))) { | |
dec = "."; | |
} else if (decMarkCommaPatt.test(decimalMark)) { | |
dec = ","; | |
} else { | |
dec = decimalMark; | |
} | |
// The space is the default thousands separator. | |
// Underscores are OK. For HTML output,   is even better! | |
var ths = (typeof thousandsSeparator === "undefined") ? " " : | |
thousandsSeparator; | |
var parts = ""; | |
parts = (pre ? n.toFixed(pre) : "" + Math.round(n)).split("."); | |
if (parts[0].length > 4) { | |
parts[0] = parts[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, ths); | |
} | |
if ((parts[1] || "").length < pre) { | |
parts[1] = parts[1] || ""; | |
parts[1] += new Array(pre - parts[1].length + 1).join("0"); | |
} | |
return neg + parts.join(dec); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment