Detecting number format culture settings - javascript

I have a webpage that needs to take numeric input, this part is easy enough with some combination of parseFloat, isNaN and (for displaying the values back to the user) toFixed. The problem is that Javascript seems to be completely ignorant of culture here. Some cultures use a decimal comma instead of a decimal point, but Javascript bulks at this.
Supporting the decimal comma isn't too much trouble, I can just replace a comma with a decimal point before parsing the users input and I can do the reverse before displaying the result to the user. My question is, is there a way for Javascript to know the users culture settings? I only care about the decimal separator, so for now I have no interest in other complications like thousands separators or currency.
Is there a reliable (client side) way to detect whether a visitor is using the decimal comma rather than the decimal point?
Update
In case anybody else wants it (or if anybody can see a flaw - other than not working in Chrome, as noted - or a better way), I ended up doing this:
var useComma = (0.1).toLocaleString().indexOf(",") > 0;
Now useComma will be true if the user has comma set as their decimal separator

I think that trying to detect the user's locale may not actually help that much. If your Web Application is in English language, a user might actually use English-style formatting (e.g. 1.3) even though in their own culture it would be formatted differently (1,3 for fr-FR or es-ES)! And who would blame them?
You could try and be smart and use the solution proposed by Alex K, and/or take into account the accept-language header, the locales matching your localizations (if any) and even GeoIP for a best guess. But to reduce confusion you may want to give your user cues whenever you expect them to enter numerals or dates or other locale-sensitive data.... Display a default value or an example next to the fields, formatted using the same locale as you will be using to parse user input.
If you believe it gives you better user experience to be flexible, you could use a fallback technique and try the formats you expect the most.

How about
var decimalChar = (0.1).toLocaleString().charAt(1);
Edit, this appears not to work in chrome Internationalization(Number formatting "num.toLocaleString()") not working for chrome

function browser_i18n() {
var o1 = new Intl.NumberFormat().resolvedOptions();
var o2 = new Intl.DateTimeFormat().resolvedOptions();
var o3 = new Intl.NumberFormat().formatToParts( 123456.789 );
return {
locale: o1.locale,
sign: o1.signDisplay,
group: o1.useGrouping,
timeZone: o2.timeZone,
calendar: o2.calendar,
thousands: o3[ 1 ].value,
decimals: o3[ 3 ].value,
}
}
//

Related

Kotlin JavaScript Date.now() return type

I was wondering why the Kotlin JavaScript Date class returns a Double for the getTime function. According to the documentation, the getTime function should return the number of milliseconds since 1 January 1970 00:00:00 UTC.
I know that JS doesn't have a 64 bit numeric representation, but since Kotlin emulates Longs I feel like the value returned by Date.now() and Date().getTime() should be a Long. At the very least it would make more sense to return an Int.
Is there any reason that it returns a Double instead of a whole number?
There are two separate reasons for that: consistency and performance.
But before I get into that please note that you can easily get the desired behavior via extensions, e.g.:
inline val Date.time get() = getTime().toLong()
println(Date().time) // 1522757176433
Consistency. As you can see in the Date documentation page, it an external class. Which means it just describes an existing JavaScript API. Is it a good design decision to reuse it as it? Maybe not. But it has a benefit of being familiar to the JS folks. Changing the return type of a single function ruins that and makes the whole API quite inconsistent.
Performance. It is possible hide the original getTime and create a helper function instead. But keep in mind that in order to emulate Long Kotlin creates an object with 2 Number's. Creation, comparison, binary operations, storage - emulated Long's perform a lot worse than native JS Numbers.
Summing up. Changing the return type would make the API inconsistent and inefficient. If you value semantics over performance, just write a few helper functions.
P.S. I think the Date API will be redesigned at some point to make it possible to use it in multiplatform projects. But that's another story.
In kotlin use Date().time .It will return the long Values you will get whole number
val s= Date().time
print(s)
for example
val date = "01-02-2018 07:05:00.999"
val fmt = SimpleDateFormat("MM-dd-yyyy HH:mm:ss.S") //parse date based your format
var myDate: Date? = null
try {
myDate = fmt.parse(date)
} catch (e: ParseException) {
e.printStackTrace()
}
println(myDate)
val timestamp = myDate!!.time //timestamp values in long only not double
println(timestamp)

toFixed() Simple use/explanation in text field

I've avoided asking this question here as I know many have in the past. I've spent some time during the last few days trying to find a solution/figure out how the toFixed() method works. I've read a lot of questions on this site and tutorials on others but I'm still not getting it.
I have several text fields with the class, ".entry". A dollar amount is supposed to go here. When people type the following (examples):
1.2
5
6.35
8.
I need them to change to:
1.20
5.00
6.35
8.00
In other words, add the trailing zeros. I know this is accomplished through the toFixed() method but I'm completely at a loss. I can't get it to work.
I have a script I found that totals all the text fields in a DIV elsewhere on the page and I notice that it uses the toFixed() method:
$("#total").html(sum.toFixed(2).replace(/(^\d{1,3}|\d{3})(?=(?:\d{3})+(?:$|\.))/g, '$1,'));
}
I tried using that same code here so the zeros could display in the text field:
$('.entry').keyup(function(){
var str = this.value.replace(/(^\d{1,3}|\d{3})(?=(?:\d{3})+(?:$|\.))/g, '$1');
if (str!=this.value) this.value = str;
});
It doesn't work.
I'm new to Jquery and Javascript so I realize I'm probably missing something obvious. Most of the tutorials I've read set the variable in the code and then use "document.write" to display the variable with the correct number of zeros:
Example:
document.write( 1.1.toFixed(2) + '<br>' );
But this isn't what I'm looking for. I need it to show up in the text field.
Thanks in advance!
A few things:
Use the change event instead of keyup. If you use keyup, the text wil change every time the user tries to type something, which is an annoying user experience.
Consider using an input of type number with a step of 0.1.
With those in mind, I'd do something like this:
$('.entry').change(function(){
// parse the typed value as a floating point number
var num = parseFloat(this.value);
// ensure there are two decimal places
this.value = num.toFixed(2);
});
Note that if the user types something with more than two decimal places, the value will be rounded.
Example: http://jsfiddle.net/jndt1e02/

Is there a way to get the decimal and thousands separator in ECMAscript Internationalization API?

I'm trying to use the new Javascript internationalization API, and would like to know if there is a way to get the decimal and thousands (grouping) separator for a Intl.NumberFormat instance?
There is a resolvedOptions method on the object, but that does not provide the symbols.
In case anybody's wondering, then for en-US, these would be a comma , and period ., such as in 1,000.00.
If nothing else, as a trick solution (that doesn't pass the Turkey Test; see comment), you can use the output of toLocaleString() to determine information about number formatting in a locale. For the current locale, for example:
var decimalSeparator =
(12345.6789).toLocaleString().match(/345(.*)67/)[1];
var thousandSeparator =
(12345.6789).toLocaleString().match(/12(.*)345/)[1];
var numberOfDecimals =
(12345.6789).toLocaleString().match(/345(\D*)(\d+)$/)[2].length;
The same trick can be used for currency formatting, using e.g. (12345.6789).toLocaleString("en-GB", { style: "currency" }).
I'm afraid ECMA-402 standard does not define the API that let you access separators. There is also another problem - at the moment the adoption of ECMA-402 is not as wide as we wish.
Therefore for the time being, if I were you I would look to something like CLDR JSON bindings or iLib which apparently provides these information through LocaleInfo's getDecimalSeparator() and getGroupingSeparator() functions.
BTW. iLib seems to use CLDR as a source of information.

Parse twitter-cldr-js formatted number back into integer or float?

Is there any easy way to do reverse of:
// include twitter_cldr/es.js
var fmt = new TwitterCldr.DecimalFormatter();
fmt.format(1337); // "1.337"
i.e. parse "1.337" back to integer with value of 1337?
The solution should work for any twitter-cldr-js supported locale.
I am not looking for parseInt / parseFloat, as it does not handle all possible locales.
After two days of trial & error I've found it impossible to do this using twitter-cldr-js and turned to Globalize instead, which does the job very neatly.

How to format numbers using JavaScript?

I want to format number using javascript as below:
10.00=10,00
1,000.00=1.000,00
Every browser supports Number.prototype.toLocaleString(), a method intended to return a localized string from a number. However, the specification defines it as follows:
Produces a string value that represents the value of the Number formatted according to the conventions of the host environment's current locale. This function is implementation-dependent, and it is permissible, but not encouraged, for it to return the same thing as toString.
Implementation-dependant means that it's up to the vendor how the result will look, and results in interoperability issues.
Internet Explorer (IE 5.5 to IE 9) comes closest to what you want and formats the number in a currency style - thousands separator and fixed at 2 decimal places.
Firefox (2+) formats the number with a thousands separator and decimal places but only if applicable.
Opera, Chrome & Safari output the same as toString() -- no thousands separator, decimal place only if required.
Solution
I came up with the following code (based on an old answer of mine) to try and normalize the results to work like Internet Explorer's method:
(function (old) {
var dec = 0.12 .toLocaleString().charAt(1),
tho = dec === "." ? "," : ".";
if (1000 .toLocaleString() !== "1,000.00") {
Number.prototype.toLocaleString = function () {
var neg = this < 0,
f = this.toFixed(2).slice(+neg);
return (neg ? "-" : "")
+ f.slice(0,-3).replace(/(?=(?!^)(?:\d{3})+(?!\d))/g, tho)
+ dec + f.slice(-2);
}
}
})(Number.prototype.toLocaleString);
This will use the browser's built-in localization if it's available, whilst gracefully degrading to the browser's default locale in other cases.
Working demo: http://jsfiddle.net/R4DKn/49/
I know this solution using NumberFormat but it is necessary to convert the values to string.
https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/NumberFormat
// Remove commas
number = "10,000.00".replace(/,/g, '');
// Create a NumberFormat type object
var formatter = new Intl.NumberFormat('de-DE', {
minimumFractionDigits: 2
});
// Apply format
console.log(formatter.format(number));
output:10.000,00
Javascript doesn't provide this functionality itself, but there are a number of third-party functions around which can do what you want.
Note, whichever method you use, you should be careful to only use the resulting string for display purposes -- it won't be a valid number value in Javascript after you've converted the decimal point to a comma.
The quickest solution I can offer is to use the number_format() function written by the phpJS people. They've implemented Javascript versions of a load of commonly-used PHP functions, including number_format(), and this function will do exactly what you want.
See the link here: http://phpjs.org/functions/number_format
I wouldn't bother about taking the whole phpJS library (a lot of it is of questionable value anyway), but just grab the 20-odd line function shown on the page linked above and paste it into your app.
If you want a more flexible solution, there are a number of JS functions around which simulate the printf() function from C. There is already a good question on SO covers this. See here: JavaScript equivalent to printf/string.format
Hope that helps.

Categories