Reputation: 21
I am using javascript and I've seen some ways to convert a currency to a number, but not one that is flexible to understand multiple input formats (decimal separator changes based on the user preference).
Let me show what I mean:
Some possible inputs (String or Number):
Output (Number):
Upvotes: 1
Views: 151
Reputation: 79
For this I Found this Solutions lets try
let tests = [
"1.000,50",
"$1.000,50",
"1,000.50",
"$1,000.50",
1000.50,
"-$1,000.50"
]
for (let index = 0; index < tests.length; index++) {
const element = tests[index];
if(typeof(element)== 'string'){
)
let numstr= element.replace(",", "");
if(isNaN(numstr[0])){
numstr = numstr.slice(1)
if(isNaN(numstr[0])){
numstr = numstr.slice(1)
numstr = parseFloat(numstr)
tests[index] = numstr
}else{
numstr = parseFloat(numstr)
tests[index] = numstr
}
}else{
/* numstr = numstr.slice(1) */
numstr = parseFloat(numstr)
tests[index] = numstr
}
}
}
console.log(tests)
output : [1.0005, 1.0005, 1000.5, 1000.5, 1000.5, 1000.5]
Upvotes: 0
Reputation: 76953
In the snippet below I'm copying the String that you have, ignoring $ and, if it's . or , then I'm ignoring it unless it's at the end of the String.
let tests = [
"1.000,50",
"$1.000,50",
"1,000.50",
"$1,000.50",
1000.50,
"-$1,000.50"
]
console.log(tests.map(item => {
if (!isNaN(item)) return item;
let newItem = "";
for (let index = 0; index < item.length; index++) {
if (item[index] !== "$") {
let dotcomma = [".", ","].indexOf(item[index]);
if ((dotcomma >= 0) && (index >= item.length - 3)) {
newItem += ".";
} else if (dotcomma < 0) {
newItem += item[index];
}
}
}
return parseFloat(newItem);
}));
Upvotes: 0
Reputation: 48713
You can check if the input is a number or a string. If it is a number, return it immediately. If it is a string, detect the number format and replace characters as necessary, and return the converted number.
const inputs = [
"1.000,50",
"$1.000,50",
"1,000.50",
"$1,000.50",
1000.50,
"-$1,000.50",
"-1,000.50",
10005e-1
];
const expected = 1000.50;
const convert = (input) => {
if (typeof input === 'number') return input; // Pass-through
if (typeof input !== 'string')
throw new Error(`Expected number or string for '${input}' (${typeof input})`);
const stripped = input.replace(/[^\d.,-]/g, '')
return stripped.slice(-3).includes(',')
? +stripped.replace(/\./g, '').replace(/,/g, '.') // e.g. French format
: +stripped.replace(/\,/g, ''); // e.g. US format
};
// true
console.log(inputs.every(input => {
const actual = convert(input);
console.log(`${input} -> ${actual}`);
return Math.abs(Math.abs(actual) - expected) < 0.000001;
}));
.as-console-wrapper { top: 0; max-height: 100% !important; }
Here is a more-robust solution that checks for NaN
as well:
const inputs = [
"1.000,50",
"$1.000,50",
"1,000.50",
"$1,000.50",
1000.50
];
const expected = 1000.50;
const stripNonNumericCharacters = (input) => input.replace(/[^\d.,-]/g, '');
const isFrenchFormat = (stripped) => stripped.slice(-3).includes(',');
const convertToNumber = (stripped, frenchFormat) => {
return frenchFormat
? parseFloat(stripped.replace(/\./g, '').replace(/,/g, '.'))
: parseFloat(stripped.replace(/,/g, ''));
};
const convert = (input) => {
if (typeof input === 'number') return input; // Pass-through
if (typeof input !== 'string')
throw new Error(`Expected number or string for '${input}' (${typeof input})`);
const stripped = stripNonNumericCharacters(input);
const frenchFormat = isFrenchFormat(stripped);
const parsed = convertToNumber(stripped, frenchFormat);
if (isNaN(parsed)) {
throw new Error(`Invalid number format for '${input}'`);
}
return parsed;
};
// true
console.log(inputs.map(convert).every(actual => Math.abs(actual - expected) < 0.000001));
.as-console-wrapper { top: 0; max-height: 100% !important; }
Upvotes: 2