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.
Related
Using macOS with BigSur version 11.4.
A file name on my mac called: второй
If i copy and paste the file name to chrome console and print "второй".charCodeAt(5) - 1080
Is Safari: "второй".charCodeAt(5) - 1081
This causes some discrepancies in my app.
Is there a way to handle this so both browsers will act the same?
There are (at least) two ways to write that word in Unicode: второй (as in your question), which uses a и (U+0438) followed by the combining character for the mark (U+0306); and второй, which uses a single code point (U+0439) that is the combination of those (й). The one using a separate letter and combining mark is in normalization form D ("canonical decomposed," in which separate code points with combining marks are used where possible), and the one using the combined code point is in normalization form C ("canonical composed," in which combined code points are used where possible).
So for whatever reason, on Safari your string (in form D) is getting normalized to form C, but not on Chrome.
To ensure you're dealing with the same sequence of code points, you can normalize the string using the normalize method (ES2015+). It defaults to NFC, but you can pass it "NFD" if you want NFD:
const original = "второй";
console.log("original:", original.length, original.charCodeAt(5));
const nfc = original.normalize(); // Defaults to "NFC"
console.log("NFC:", nfc.length, nfc.charCodeAt(5));
const nfd = nfc.normalize("NFD");
console.log("NFD:", nfd.length, nfd.charCodeAt(5));
Note that charCodeAt works in UTF-16 code units, not code points (post on my blog about the difference), although it happens that in your example all of the code points are represented by a single code unit. You can use codePointAt to look at code points instead, although (again) in this particular case it doesn't make a difference.
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)
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.
Sometimes I see in a view source page ( html view source) this code:
if (JSON.stringify(["\u2028\u2029"]) === '["\u2028\u2029"]') JSON.stringify = function (a) {
var b = /\u2028/g,
c = /\u2029/g;
return function (d, e, f) {
var g = a.call(this, d, e, f);
if (g) {
if (-1 < g.indexOf('\u2028')) g = g.replace(b, '\\u2028');
if (-1 < g.indexOf('\u2029')) g = g.replace(c, '\\u2029');
}
return g;
};
}(JSON.stringify);
What is the problem with JSON.stringify(["\u2028\u2029"]) that it needs to be checked ?
Additional info :
JSON.stringify(["\u2028\u2029"]) value is "["
"]"
'["\u2028\u2029"]' value is also "["
"]"
I thought it might be a security feature. FileFormat.info for 2028 and 2029 have a banner stating
Do not use this character in domain names. Browsers are blacklisting it because of the potential for phishing.
But it turns out that the line and paragraph separators \u2028 and \u2029 respectively are treated as a new line in ES5 JavaScript.
From http://www.thespanner.co.uk/2011/07/25/the-json-specification-is-now-wrong/
\u2028 and \u2029 characters that can break entire JSON feeds since the string will contain a new line and the JavaScript parser will bail out
So you are seeing a patch for JSON.stringify. Also see Node.js JavaScript-stringify
Edit: Yes, modern browsers' built-in JSON object should take care of this correctly. I can't find any links to the actual source to back this up though. The Chromium code search doesn't mention any bugs that would warrant adding this workaround manually. It looks like Firefox 3.5 was the first version to have native JSON support, not entirely bug-free though. IE8 supports it too. So it is likely a now unnecessary patch, assuming browsers have implemented the specification correctly.
After reading both answers , here is the Simple visual explanation :
doing this
alert(JSON.stringify({"a":"sddd\u2028sssss"})) // can cause problems
will alert :
While changing the trouble maker to something else ( for example from \u to \1u)
will alert :
Now , let's invoke the function from my original Q ,
Lets try this alert(JSON.stringify({"a":"sddd\u2028sssss"})) again :
result :
and now , everybody's happy.
\u2028 and \u2029 are invisible Unicode line and paragraph separator characters. Natively JSON.stringify method converts these codes to their symbolic representation (as JavaScript automatically does in the strings), resulting in "["
"]". The code you have provided does not let JSON to convert the codes to symbols and preserves their \uXXXX representation in the output string, i.e. returning "["\u2028\u2029"]".
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,
}
}
//