Skip to content

Instantly share code, notes, and snippets.

@esquinas
Last active October 3, 2016 11:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save esquinas/94c6c97a4559183087d66ba3538eb79c to your computer and use it in GitHub Desktop.
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.
// 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, &thinsp; 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