Number.toLocaleString() with custom separators - javascript

I need to format a number in JavaScript with separators that may be defined at runtime.
The combination of thousand and decimal separator may not match a specific locale.
Is there a way to provide the thousand and decimal separator in JavaScript toLocaleString()? or to use NumberFormat explicitly with values I define?
I see examples using locale codes, and some using other values ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString ) but these don't cover my use case.

One option is to format to a string with known separators, and then do a find/replace with the unknown separators.
function formatNum(num, separator, fraction) {
var str = num.toLocaleString('en-US');
str = str.replace(/\./, fraction);
str = str.replace(/,/g, separator);
return str;
}
formatNum(12342.2, "a", "x");
//12a342x2

The original answer on this page won't work if a comma is used as the decimal separator (the parameter fraction). That's problematic, because comma is used as the decimal separator widely e.g. in Europe (Spain, France, Norway, Czechia, Denmark...).
In order to make it work, the replacement can be done in two steps instead using an intermediate placeholder for the fraction symbol:
function formatNum(num, separator, fraction) {
return num
.toLocaleString('en-US');
.replace(/\./, "<fraction>")
.replace(/,/g, separator)
.replace(/<fraction>/, fraction);
}
formatNum(12342.2, " ", ",");
//12 342,2

Related

How to round of prices with comma's instead of dots?

In The Netherlands we use comma's in numbers where in other countries dots would be used. For example we use 39,99 and in other countries 39.99.
In a feed with prices we would have prices with such comma use, but I'm having trouble using those as numbers and rounding them by two digits behind the comma (or behind the dot really).
var num1 = "39,1234";
var num = parseInt(num1);
var n = num.toFixed(2);
console.log(n);
Here is such a number. I would like it to result in 39,12. They way I was thinking is then first use it as a string. Then turn that string into a number and use toFixed to round it of to two digets. But it results in 39,00 instead of 39,12.
Perhaps I'm thinking wrong and I should use some other way to make 39,1234 to be seen as 39.1234 so that it is rounded correctly as a number?
How can I used 39,1234 as a number 39,1234 instead of a string? So that I wouldn't have to go through a feed and replace commas by dots first in all my prices?
Edit: Regex version
Earlier I didn't realize that OP originally wanted it back to the format "xx,xx". This is a more elegant solution:
var num1 = "39,1234";
let n = num1.replace(/(?<=,\d{2})(\d*)$/,"");
console.log(n); //32,12
Regex explanation:
(?<=,\d){2} begins a lookbehind match for , followed by digits \d, 2 of them {2}. Lookbehind matches are not replaced.
(\d*)$ when we've found the lookbehind pattern, we match more digits \d, all * of them, till we reach end of string $. This is the match that will get replaced.
Original Solution
What you want is:
var num1 = "39,1234";
var n = parseFloat(num1.replace(",",".")).toFixed(2);
console.log(n); //39.12
// replaces it back to ",", but now it's a string!
n = n.replace(".",",")
console.log(n); //39,12
Explanation:
First replace "," with "." with replace()
Convert to float (not integer) with parseFloat()
Set to 2 decimal places with .toFixed(2)
Replace "." with ",". But now it's a string!
Note: this will not work if the currency value contains . as a thousandth separator. e.g. "40.200,1576". If that's the case, add another line num1 = num1.replace(".","") to strip out the separator before passing it to the parseFloat(...) line.
Try this
comdecimal= num1.replace(".","")
alert(comdecimal);
dotdecimal= comdecimal.replace(",",".")
alert(dotdecimal);
dotdecimal = Math.round(dotdecimal* 100) / 100;
alert(dotdecimal);
Since you're working with currency, I'd recommend using JS ES6 designated NumberFormat feature. Your code should look like this and be easily reused:
const formatter = new Intl.NumberFormat('nl-NL', {
style: 'currency',
currency: 'EUR',
minimumFractionDigits: 2
});
console.log(formatter.format('145,53'.replace(',','.')));
//"€ 145,53"

Javascript timestamp formatting with regular expression?

how do i format a string of 2014-09-10 10:07:02 into something like this:
2014,09,10,10,07,02
Thanks!
Nice and simple.
var str = "2014-09-10 10:07:02";
var newstr = str.replace(/[ :-]/g, ',');
console.log(newstr);
Based on the assumption that you want to get rid of everything but the digits, an alternative is to inverse the regex to exclude everything but digits. This is, in effect, a white-listing approach as compared to the previously posted black-listing approach.
var dateTimeString = "2016-11-23 02:00:00";
var regex = /[^0-9]+/g; // Alternatively (credit zerkms): /\D+/g
var reformattedDateTimeString = dateTimeString.replace(regex, ',');
Note the + which has the effect of replacing groups of characters (e.g. two spaces would be replaced by only a single comma).
Also note that if you intend to use the strings as digits (e.g. via parseInt), numbers with a leading zero are interpreted within JavaScript as being base-8.

Check for numeric value with optional commas javascript

I need to check a value if it is numeric and optionally contains commas.
I tried
var input=3433;
var pattern=/^[1-9]\d{0,2}(\.\d{3})*(,\d+)?$/;
pattern.test(input);
but it always gave me false;
I don't want to use $.isNumeric as it does not check for commas.
Assuming you're using the comma as a thousands separator, the easiest way to do this is to just remove the commas when converting:
var num = +str.replace(/,/g, '');
if (!isNaN(num)) {
// It's a valid number
}
If your locale uses . as the thousands separator and , as a decimal point (as your regex seems to suggest), since JavaScript always uses them the other way around, we have more to change in the string first:
var num = +str.replace(/\./g, '').replace(/,/g, ".");
if (!isNaN(num)) {
// It's a valid number
}
I must process in different ways strings and string-numbers.
So I must test if a string is a string-number (not a valid number), using the locale convention.
My rude solution is:
var num = +str.replace(/\./g, '').replace(/,/g, '');
if (!isNaN(num))...
This works with USA, EUR locales. The control about 'valid number' is done after, car I wanna send detailed WARNING/ERROR messages to user.
Your sample var input is not matched by your regex because of the dot.
You could do:
var input=3433;
var pattern=/^[1-9]\d{0,2}(\.?\d{3})*(,\d+)?$/;
// the dot is optional __^
pattern.test(input);
This regex will match:
123
1234
1.234
123,45
1234,567
1.234,56
1.234.567,89

Javascript numeric input (regex) validation rules

I'm a bit stuck here.
With regards to the input of accounting data, the analyst requested a specific set of rules on the input of decimal data in text boxes.
Since I have not studied regular expressions at this point, and because I have very strict deadlines to attend with each a lot of work, I request your help.
The rules are (on blur):
IE8+ compatible;
Set default at 2 digits behind the comma;
Disallow other characters than ".", "," and numeric characters;
If there are multiple separators in the returned number, only keep the last one.
Explanation:
Employees may have different regional settings, and comma / dot may be used as either decimal or thousands separator.
In case an employee copy - pastes both the thousand and the decimal separator, it has to be ignored.
What I've done so far, but doesn't fulfill the requirements:
http://jsfiddle.net/NxFHL/1/
$('#test_rules.numeric').on('blur', function(){
var myString = $('#test_rules.numeric').val();
myString = parseFloat(myString.replace(/[^\d.-]/g, ''));
myString = toFixed(myString, 2);
console.log(myString);
});
function toFixed(value, precision) {
var power = Math.pow(10, precision || 0);
return
String(Math.round(value * power) / power);
}
The regular expression used doesn't work correctly as it only accepts dot, not comma.
Also I am not sure about how I should make it so that only the last separator stays (so that the thousands separator gets ignored).
Try this function:
function parseInputNum(val) {
var sep = val.lastIndexOf('.') > val.lastIndexOf(',')? '.' : ',';
var arr = val.replace(new RegExp('[^\\d'+sep+']+', 'g'), '')
.match(new RegExp('(\\d+(?:['+sep+']\\d+|))$'));
return arr? arr[1].replace(/[,]/g, '.') : false;
}
You can use this pattern:
^(?:[1-9](?:[0-9]{0,2}(?:([.,])[0-9]{3})?(?:\1[0-9]{3})*|[0-9]*)|0)(?!\1)[.,][0-9]{2}$
This pattern will check numbers like:
123,45
12,45
0.45
123,456,789.12
1234.56
123.456.789,12
but not numbers like:
12.23.45,12
012,345,678,91
1234,567.89
123,456,78
To convert the string into a number you must remove the thousand delimiter before. This can easily be done since the delimiter (if present) is in the capturing group 1. You must probably too replace the , by the . if it is used as decimal separator.

Regular expression to strip thousand separator from numeral string?

I have strings which contains thousand separators, however no string-to-number function wants to consume it correctly (using JavaScript). I'm thinking about "preparing" the string by stripping all thousand separators, leaving anything else untoched and letting Number/parseInt/parseFloat functions (I'm satisfied with their behavious otherwise) to decide the rest. But it seems what i have no idea which RegExp can do that!
Better ideas are welcome too!
UPDATE:
Sorry, answers enlightened me how badly formulated question it is. What i'm triyng to achieve is: 1) to strip thousand separators only if any, but 2) to not disturb original string much so i will get NaNs in the cases of invalid numerals.
MORE UPDATE:
JavaScript is limited to English locale for parsing, so lets assume thousand separator is ',' for simplicity (naturally, it never matches decimal separator in any locale, so changing to any other locale should not pose a problem)
Now, on parsing functions:
parseFloat('1023.95BARGAIN BYTES!') // parseXXX functions just "gives up" on invalid chars and returns 1023.95
Number('1023.95BARGAIN BYTES!') // while Number constructor behaves "strictly" and will return NaN
Sometimes I use rhw loose one, sometimes strict. I want to figure out the best approach for preparing string for both functions.
On validity of numerals:
'1,023.99' is perfectly well-formed English number, and stripping all commas will lead to correct result.
'1,0,2,3.99' is broken, however generic comma stripping will give '1023.99' which is unlikely to be a correct result.
welp, I'll venture to throw my suggestion into the pot:
Note: Revised
stringWithNumbers = stringwithNumbers.replace(/(\d+),(?=\d{3}(\D|$))/g, "$1");
should turn
1,234,567.12
1,023.99
1,0,2,3.99
the dang thing costs $1,205!!
95,5,0,432
12345,0000
1,2345
into:
1234567.12
1023.99
1,0,2,3.99
the dang thing costs $1205!!
95,5,0432
12345,0000
1,2345
I hope that's useful!
EDIT:
There is an additional alteration that may be necessary, but is not without side effects:
(\b\d{1,3}),(?=\d{3}(\D|$))
This changes the "one or more" quantifier (+) for the first set of digits into a "one to three" quantifier ({1,3}) and adds a "word-boundary" assertion before it. It will prevent replacements like 1234,123 ==> 1234123. However, it will also prevent a replacement that might be desired (if it is preceded by a letter or underscore), such as A123,789 or _1,555 (which will remain unchanged).
A simple num.replace(/,/g, '') should be sufficient I think.
Depends on what your thousand separator is
myString = myString.replace(/[ ,]/g, "");
would remove spaces and commas.
This should work for you
var decimalCharacter = ".",
regex = new RegExp("[\\d" + decimalCharacter + "]+", "g"),
num = "10,0000,000,000.999";
+num.match(regex).join("");
To confirm that a numeral-string is well-formed, use:
/^(\d*|\d{1,3}(,\d{3})+)($|[^\d])/.test(numeral_string)
which will return true if the numeral-string is either (1) just a sequence of zero or more digits, or (2) a sequence of digits with a comma before each set of three digits, or (3) either of the above followed by a non-digit character and who knows what else. (Case #3 is for floats, as well as your "BARGAIN BYTES!" examples.)
Once you've confirmed that, use:
numeral_string.replace(/,/g, '')
which will return a copy of the numeral-string with all commas excised.
You can use s.replaceAll("(\\W)(?=\\d{3})","");
This regex gets all alpha-numeric character with 3 characters after it.
Strings like 4.444.444.444,00 € will be 4444444444,00 €
I have used the following in a commercial setting, and it has worked often:
numberStr = numberStr.replace(/[. ,](\d\d\d\D|\d\d\d$)/g,'$1');
In the above example, thousands can be marked with a decimal, a comma, or a space.
In some cases ( like a price of 1000,5 Euros) the above doesn't work. If you need something more robust, this should work 100% of the time:
//convert a comma or space used as the cent placeholder to a decimal
$priceStr = $priceStr.replace(/[, ](\d\d$)/,'.$1');
$priceStr = $priceStr.replace(/[, ](\d$)/,'.$1');
//capture cents
var $hasCentsRegex = /[.]\d\d?$/;
if($hasCentsRegex.test($priceStr)) {
var $matchArray = $priceStr.match(/(.*)([.]\d\d?$)/);
var $priceBeforeCents = $matchArray[1];
var $cents = $matchArray[2];
} else{
var $priceBeforeCents = $priceStr;
var $cents = "";
}
//remove decimals, commas and whitespace from the pre-cent portion
$priceBeforeCents = $priceBeforeCents.replace(/[.\s,]/g,'');
//re-create the price by adding back the cents
$priceStr = $priceBeforeCents + $cents;

Categories