Created
March 14, 2012 15:11
-
-
Save GerHobbelt/2037124 to your computer and use it in GitHub Desktop.
locale semi-agnostic string to float conversion [JavaScript]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Editor backup files | |
*.bak | |
*~ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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)); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> € | |
<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ä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ü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> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This won't work for '1.233'
Is: 1233,
expected: 1.233