Skip to content

Instantly share code, notes, and snippets.

@GerHobbelt
Created March 14, 2012 15:11
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save GerHobbelt/2037124 to your computer and use it in GitHub Desktop.
Save GerHobbelt/2037124 to your computer and use it in GitHub Desktop.
locale semi-agnostic string to float conversion [JavaScript]
# Editor backup files
*.bak
*~
// parseFloat() but now locale aware and trying to be locale agnostic
//
// put in closure to cache intel which you don't want to calc each time
// you convert a string --> float
function StrToFloat() {
var decimal_point = (1.1).toLocaleString().substr(1,1);
var K_separator = (5000).toLocaleString().substr(1,1);
if (K_separator === '0')
K_separator = (decimal_point === '.' ? ',' : '.');
return function(str) {
switch (typeof(str)) {
case 'float':
case 'integer':
return str;
default:
str = '' + str; // force str to be string type
str = str.match(/[0-9.,eE-]+/);
if (str)
str = str[0];
else
return Number.NaN; // VERY illegal number format
var kp = str.indexOf(',');
var dp = str.indexOf('.');
var kpl = str.lastIndexOf(',');
var dpl = str.lastIndexOf('.');
// can we be 'locale agnostic'? We can if both markers are in the input:
if (kp > 0 && dp > 0) {
if (kp < dp) {
// e.g.: 1,000.00
if (kpl > dpl || dpl > dp)
return Number.NaN; // VERY illegal number format
str = str.replace(/,/g, '');
} else {
// e.g.: 1.000,00
if (kpl < dpl || kpl > kp)
return Number.NaN; // VERY illegal number format
str = str.replace(/\./g, '').replace(',', '.');
}
} else {
// only one of 'em in there: must we use the detected 'current' locale
// or can we 'heuristically determine' what's right here?
// We can do the latter if we have either:
// - only up to 2 digits following the only separator
// - more than 3 digits following the only separator
// - one separator only and the number starts with it, e.g. '.45'
//
// When we have only 3 digits following the last and only sep, we assume the separator
// to be a 'thousands marker'.
// We COULD fall back to the current locale, but than the ambiguous items receive
// different treatment on a possibly incorrect locale setting (e.g. my machines are all
// US/metric configured while I live in the Netherlands, but I /despise/ Dutch MS Excel,
// for example. Riding the 'locale aware' ticket would definitely screw up my [ambiguous]
// numbers. I believe it's better to be consistently wrong than semi-randomly correct.
//
// examples: 1.000 : 5,00 : 2,999.95 : 2,998 : 7.50 : 0,1791634 : 0.1791634 : .45 : ,32
if (dp >= 0 && kp < 0) {
// .45, ....
if (dp !== 0 && (dpl > dp || str.substr(dp + 1).match(/^[0-9]{3}\b/)))
str = str.replace(/\./g, '');
} else if (kp >= 0 && dp < 0) {
// ,32; ....
if (kp !== 0 && (kpl > kp || str.substr(kp + 1).match(/^[0-9]{3}\b/)))
str = str.replace(/,/g, '');
else
str = str.replace(',', '.');
} else if (kp < 0 && dp < 0) {
// integer value
} else {
// VERY illegal format, such as '.456,678'
return Number.NaN;
}
}
// now str has parseFloat() compliant format with US decimal point
// only (iff it has a decimal fraction at all).
return parseFloat(str);
}
};
}
$$('.chooseout a').addEvent('click', function(e) {
e.stop();
var cvt = StrToFloat();
console.log('examples: 1.000 : ', cvt('1.000'));
console.log('examples: 1.000.000 : ', cvt('1.000.000'));
console.log('examples (India/US): 1.00.000 : ', cvt('1.00.000'));
console.log('examples: 5,00 : ', cvt('5,00'));
console.log('examples: 2,999.95 : ', cvt('2,999.95'));
console.log('examples: 2,999.995 : ', cvt('2,999.995'));
console.log('examples: 2.999,95 : ', cvt('2.999,95'));
console.log('examples: 2.999,995 : ', cvt('2.999,995'));
console.log('examples: 2,998 : ', cvt('2,998'));
console.log('examples: 2,999,998 : ', cvt('2,999,998'));
console.log('examples (India): 2,99,998 : ', cvt('2,99,998'));
console.log('examples: 7.50 : ', cvt('7.50'));
console.log('examples: 0,1791634 : ', cvt('0,1791634'));
console.log('examples: 0.1791634 : ', cvt('0.1791634'));
console.log('examples: .45 : ', cvt('.45'));
console.log('examples: ,32 : ', cvt(',32'));
console.log('examples: .450 : ', cvt('.450'));
console.log('examples: ,320 : ', cvt(',320'));
console.log('examples FLOAT: 3.1415 : ', cvt(3.1415));
console.log('examples INT: 1234 : ', cvt(1234));
console.log('examples: 1 EUR : ', cvt('1 EUR'));
console.log('examples BAD: bla : ', cvt('bla'));
console.log('examples BAD: .456,678 : ', cvt('.456,678'));
console.log('examples BAD: ,456.678 : ', cvt(',456.678'));
console.log('examples BAD: .123.456,678 : ', cvt('.123.456,678'));
console.log('examples BAD: ,123,456.678 : ', cvt(',123,456.678'));
console.log('examples BAD: .456,678.456 : ', cvt('.456,678.456'));
console.log('examples BAD: ,456.678,456 : ', cvt(',456.678,456'));
console.log('examples BAD: 1.456,678.456 : ', cvt('1.456,678.456'));
console.log('examples BAD: 1,456.678,456 : ', cvt('1,456.678,456'));
var preis_str = $('getContent').getElement('.article_price b').get('text');
// BTW: NEVER do a toInt() as you'll lose the fractional part in the price.
var preis = cvt(preis_str);
var spreis_set = $$(".gespreis");
var summe = spreis_set[0].get('text');
summe = cvt(summe);
summe += preis;
console.log('summe: ', summe);
spreis_set.each(function(el) {
el.set('text', summe.toFixed(2));
});
});
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootools.js"></script>
</head>
<body>
<div id="getContent">
<div class="article_price">
Preis: <b>99,66</b> &euro;
<span>auch mit elektronischer Zeitschaltuhr</span>
</div>
</div>
<div class="chooseout">
<a class="btn-2011 rsblue" href="javascript:void(0);">
<span class="btn-2011-glass"></span>In den Warenkorb
</a>
</div>
<div id="warentext" >
<p>Leider ist dieser Artikel unverk&auml;uflich denn sie existiert nur
virtuell.</p>
<p>Dennoch freuen wir uns sehr, dass Du bereit warst, die immense
Summe von <span class="gespreis">0</span> Euro f&uuml;r diese
Produkte zu bezahlen.
Falls Du Dich jetzt fragst: Was soll ich mit den
<span class="gespreis">0</span> Euro anfangen, von denen ich mich
bereits verabschiedet habe, gibt es einen Vorschlag: SPENDEN</p>
</div>
<script type="text/javascript" src="cvt.js"></script>
</body>
</html>
@jHabjanMXP
Copy link

This won't work for '1.233'
Is: 1233,
expected: 1.233

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment