2

I'm finding an equivalent to Java's DecimalFormat in JavaScript. I would like to format given numeric values with given decimal pattern like

"#,###.00"
"###.##"
"#,###.##"
"$#,##0.00"
"###,###.00"
"$###,###.00"
"###,###.###"
"####,####.000"

Has there any way to achieve it?

Gufran Hasan
  • 8,910
  • 7
  • 38
  • 51
Cataclysm
  • 7,592
  • 21
  • 74
  • 123

2 Answers2

1

Part 1 - formatting

I would recommend using the Intl.NumberFormat natively supported in javascript, although it may not be supported by older browsers. Looks like IE11 has it, but not android.

So if you wanted to support US Dollars you would simply use something like this

var dollarFormat = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' });
var amountInDollars = dollarFormat.format(123456.123);
// amountInDollars = "$123,456.12"

But this also rounds up for you, for example

var roundedDollars = dollarFormat.format(555.555);
// roundedDollars = "$555.56";

For the numeric cases just use a different formatter. The default 'en-US' adds commas, a decimal before fractional numbers, and limits to 3 fractional numbers. But this is configurable.

var numberFormat = new Intl.NumberFormat('en-US');
var formatted = numberFormat.format(123456.123456);
// formatted = "123,456.123"
var numberFormat2decimals = new Intl.NumberFormat('en-US', { maximumFractionDigits: 2 });
var formatted2 = numberFormat2decimals.format(123456.123456);
// formatted2 = "123,456.12"

You can set maximum and minimum for fraction, integer, and significant digits, and this also supports international formats. Since it's native javascript, I think it's a good way to go if your platforms support it.

MDN is an excellent reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat

Part 2 - the 0's

To achieve the 0's in your formats you'll have to modify the value before passing to the formatter. If you require a minimum fractional amount, you're fine for things like .00, the currency formatter will do that by default. If you've got fractal numbers you don't want, just use Math.trun() to truncate the values.

var num = Math.trun(1234.1234);
// num = 1234

Now to change something like 12345 to 12340 we'll have to remove some of the numeric value. We can find out much by converting to a string, pulling the last character, and converting back.

var num = 123456.12345;
var wholeNum = Math.trunc(num);
// wholeNum = 123456;
var toRemove = Number.parseInt(wholeNum.toString().slice(-1), 10);
// toRemove = 6
// slice(-1) gives us the right-most character of a string.
// Notice the ', 10' at the end, this is important to indicate which number base to use for parseInt. 
var wholeNumEnding0 = wholeNum - toRemove;
// wholeNumEnding0 = 123450

Hopefully that's what you're looking to accomplish? I didn't perform any rounding here.

Community
  • 1
  • 1
abenbot
  • 51
  • 6
  • Thank you. Very good points to start create byself for equivalent with [Java's Decimal Format](https://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html). I didn't found any plugin to satisfy `#` , `0` and sub-patterns with `;` yet. – Cataclysm May 09 '18 at 01:49
  • Can you elaborate on what you're trying to do with `#`, `0`, and `;`? I assumed `#` were numeric values passed into a formatter and `0` was forcing a 0 at a position in the output. I'm not too familiar with Java's DecimalFormat.. If I get time I'll look it up to get a better idea of what you're trying to accomplish. – abenbot May 09 '18 at 18:15
  • Me too , I need this in rush. So I made a webservice method in server-side to handle. This was just a hot-fix to satisfy current needs and no buggy contents on urgent situation. But I hope I can try to implement at client-side itself with JQuery or JavaScript. – Cataclysm May 10 '18 at 01:56
  • Btw , I think this is not Java's. Microsoft Excel also use these patterns at currency or decimal formatting. And JasperSoft Studio too. I think there has some standards about these patterns. – Cataclysm May 10 '18 at 01:59
  • Ah, I see. So I completely messed up on what I thought the 0's were for.. and my answer doesn't accept the patterns you're proposing. I believe it can solve your needs, but it may be a significant effort to directly support those patterns with this. – abenbot May 10 '18 at 03:27
  • If you list your use-cases, I'm happy to help show how to achieve them. Or are those patterns all of your use cases? So if the grouping separator is left out of the pattern, no commas should appear in the result? Otherwise I think I understand the rest. – abenbot May 10 '18 at 03:29
  • I'm really appreciated for your helps. `#` **A digit, leading zeroes are omitted** , `0` **A digit - always displayed, even if number has less digits (then 0 is displayed)**. [Here](http://tutorials.jenkov.com/java-internationalization/decimalformat.html) you can see the some example outputs with given inputs and see more explanations at *Number Format Pattern Syntax* section.Or you can test them in Microsoft Excel as **[This](https://stackoverflow.com/questions/319438/basic-excel-currency-format-with-apache-poi#27277918)** answer described. Thanks – Cataclysm May 10 '18 at 03:58
0

Note: I typed this at speed, excuse any mistakes, there might be better ways to do it too.

If you don't want to rely on a library, you could do something like the following:

var number = 100000.00000000000012422;

function FormatNumber(no){

  no = no.toFixed(2);
  no = no.toString().split('.');

  var p1 = no[0];

  p1 = p1.substring(0, p1.length - 3) + ',' + p1.substring(p1.length - 3);

  no = p1 + '.' + no[1];

  console.log(no);

}

FormatNumber(number);

The FormatNumber function takes a number as a parameter (you would probably want to expand that to include e.g. decimal places). It converts the number to the required decimal places, the turns it into a string and splits it by the decimal separator '.'.

The next step is to add a thousands separator three characters from the back, then it's just a matter of joining the remaining characters back together.

JSFiddle

If you wanted to get a ',' every 3 characters you could write a little more 'complex' formatter, something along the lines of the following:

  no = no.toFixed(2);
  no = no.toString().split('.');

  var p1 = no[0];

  var arr = [];

  arr = p1.split("").reverse().join("").match(/[\s\S]{1,3}/g) || [];
  arr = arr.reverse();

  p1 = "";

  for(var i = 0; i < arr.length; i++){
    p1 += arr[i].split("").reverse().join("");
        if(i != arr.length - 1){
           p1 += ',';
        }
  }


  no = p1 + '.' + no[1];

This method splits the number into an array by each number, reverses the array as we need to start from the end of the string to get accurate result.

Then we iterate the array of strings with 3 or less values by splitting the number into an array again, reversing it and joining back together and then appending to p1. If it's the last item, it doesn't add a comma.

Lastly we take the decimal and append to built string.

JSFiddle

Adrian
  • 8,271
  • 2
  • 26
  • 43