Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal for stage 0 #1

Open
3 tasks
rxaviers opened this issue Feb 19, 2015 · 18 comments
Open
3 tasks

Proposal for stage 0 #1

rxaviers opened this issue Feb 19, 2015 · 18 comments

Comments

@rxaviers
Copy link
Owner

Goal

Poll for discussion.

Sidenotes raised in this discussion - needs action to be taken

  • Currency options way too repetitive.
  • Add support for rounding to 5 cents coins (e.g., pattern 0.05).
  • Abbreviated display mode.
@rxaviers
Copy link
Owner Author

For the record, an initial discussion has already happened in this thread of javascript-globalization@googlegroups.com mailing list.

@rxaviers
Copy link
Owner Author

@rwaldron, FWIW I also think the currency arguments of new Intl.NumberFormat("en", {style:"currency", currency: "JPY", currencyDisplay: "symbol"}).format(9); // "¥9" is way too repetitive. I think there's space for improvements.

@rxaviers
Copy link
Owner Author

@ehoogerbeets, @caridy, I'm confused why you believe my proposed round option would restrict the formatter in any way? This option gives users the choice to change the default rounding method, which is always the half-even independent of the chosen locale.

Rounding methods like half-up, half-down, or any other different methods cannot be selected by the API, neither per locale basis, neither per formatting style basis (e.g., formatting numbers vs. formatting currencies vs. etc).

Please, correct me if I'm wrong.

All the locale-differences are kept unchanged with or without my proposed round option. For example, (a) the digit where the rounding takes place using minumumFractionDigits, or maximumFractionDigits, or minumumSignificantDigits and maximumSignificantDigits is kept unchanged; (b) the currency-dependent-digit where the rounding takes place (e.g., USD has 2 decimal digits, JPY has 0 decimal digits, CLF has 4 decimal digits, etc) is kept unchanged, (c) the fact some currencies have roundings based on available coins is unchanged with or without my proposed round option.

The point is: if you want to use half-up (i.e., Math.ceil) on your roundings, how do you do it? Again, the formatter always rounds whether or not you like it.

@rxaviers
Copy link
Owner Author

@caridy,

new Intl.NumberFormat('en', {style: 'currency', currency: 'usd'}).format(100.223455879) // "$100.223” in chrome and "$100.22” in firefox
new Intl.NumberFormat('fr', {style: 'currency', currency: 'eur'}).format(100.125500009) // "100,126 €” in chrome and “100,13 €” in firefox

On chrome, the three digits result is an implementation bug. Ecma-402 says on 11.1.1.1 If s is "currency", then let mxfdDefault be max(mnfd, cDigits);. So, 2 should be used.

@rxaviers
Copy link
Owner Author

@nciric ☝️ FYI

@rxaviers
Copy link
Owner Author

@ehoogerbeets,

Also note that in some countries such as Australia, they have done away with the smaller coins like pennies, so currencies are often rounded to the smallest coin when dealing with cash rather than electronic amounts. This is called "Swedish rounding" as it used to be used in Sweden. In the Australian example, the smallest coin is 5 cents, so the rounding is a little more complicated than rounding to a particular decimal point. Take a look at http://en.wikipedia.org/wiki/Swedish_rounding

UTS#35 Rounding has rules for that. Rounding currencies per 5 cents coins is really easy using a pattern like "0.05".

  • Globalize supports such rounding.
  • They are not used in any CLDR data, I don't know why? For example, en-AU's currencyFormats-numberSystem-latn/standard could simply be "¤#,##0.05" (instead of "¤#,##0.00") (cc @srl295, @JCEmmons)
  • They are not specified by Ecma-402. (cc @rwaldron)

@caridy
Copy link

caridy commented Feb 19, 2015

Ok, let me re-iterate my position:

  1. we should have a clear separation between what formatting is, and what number manipulation is. IMO, manipulating a number (e.g.: ceil, floor, truncation, etc) is in the realm of mathematical operations with numbers, and should be universal thru an imperative form under Math. In the other hand, applying formatting rules, like rounding currency to 0.05 for a particular locale based on their currency denomination, which belongs to Intl.
  2. It seems that we are all aware of the confusing and redundancy of the current ways of formatting to currency, and we can probably simplify it by introducing a new API for currency as proposed by @rwaldron (via email). I will be in favor of that, probably as a path forward for this proposal.
  3. I will like to see more about real use-cases where we want to format a number (non-currency form) and apply specific formatting rules per locale.

@rxaviers
Copy link
Owner Author

  1. I will like to see more about real use-cases where we want to format a number (non-currency form) and apply specific formatting rules per locale.

Can you clarify what do you consider to be a specific formatting rules?

@steveluscher
Copy link

I came here by way of seeing @ericf's Intl talk at React.js Conf. We chatted, yesterday afternoon, about our use case for rounding options in Intl.NumberFormat, and he suggested that I bring it up here.

I work on a product used by people who can follow other people. Follower counts can climb high enough that we must abbreviate them. When abbreviating them, we have two requirements:

  1. Show no more than 3 digits, and no more than one decimal place
  2. Never overstate the follower count

Adding an abbreviationThreshold option and combining it with the maximumSignificantDigits and maximumFractionDigits options would constitute a slam dunk for requirement 1. To satisfy the second, I need to be able to specify a rounding method.

I invite you to comment on this proposal for an abbreviation API in NumberFormat. I'll inline a couple of the examples here:

var number = 7654321;
console.log(new Intl.NumberFormat('en-US', {
  abbreviationThreshold: 1e6,
  abbreviationRoundingMethod: Intl.NumberFormat.ROUND_DOWN,
  maximumFractionDigits: 1,
  maximumSignificantDigits: 3,
}).format(number));
// → 7.6M
console.log(new Intl.NumberFormat('ja-JP', {
  abbreviationThreshold: 1e6,
  abbreviationRoundingMethod: Intl.NumberFormat.ROUND_DOWN,
  maximumFractionDigits: 1,
  maximumSignificantDigits: 3
}).format(number));
// → 765万

According to the usual rules of Math.round, the English number would have been rounded to 7.7 – an overstatement of our follower count. By being able to specify a rounding mode, we can prevent this.

Also, note that in some locales, such as ja-JP, it's not typical to use the ‘millions’ abbreviation, but instead to talk about ‘765 ten thousands.’ Rolling abbreviation options and rounding control into Intl.NumberFormat would make these feats of formatting possible with a really elegant API.

If you haven't already clicked through to the proposal, here's a link straight to an explanation of the proposed rounding modes (based on prior art from java.math).

@rxaviers
Copy link
Owner Author

@ericf, thanks for the referral/direction.

@steveluscher, thanks for sharing your use case, where you need to specify a rounding mode.

abbreviationRoundingMethod

I'm assuming the proposed round option is exactly what you need.

Intl.NumberFormat.ROUND_*

About the possible rounding values... (a) Rounding functions belong to the Math realm, therefore the preferred object is Math instead of Intl.NumberFormat.fns (anyone can correct me if I'm wrong), (b) I'm not sure Math provides all the options you describe. @rwaldron, can provide his thoughts about it...

abbreviationThreshold

You need to be able to specify an abbreviated display mode (to keep track of this, I've added it to the above description as one more sidenote that need action to be taken).

The code logic that handles the threshold switch (example below) could live in user land.

output = value < threshold ? normalFormatter( value ) : abbreviatedFormatter( value );

@rwaldron
Copy link
Contributor

@rxaviers yes, the ROUND_ bits shouldn't belong to the Intl.* API, since they are a generalized Math capability. I've added some comments to @steveluscher's proposal: https://gist.github.com/steveluscher/4b54e08aa1e0536b7cb9#comment-1400186 I think the roundingModes addition has value on it's own and would push for inclusion in the first round of standard library modules to be defined for ES7

@bsrdjan
Copy link

bsrdjan commented Sep 18, 2015

@caridy

We should have a clear separation between what formatting is, and what number manipulation is. IMO, manipulating a number (e.g.: ceil, floor, truncation, etc) is in the realm of mathematical operations with numbers, and should be universal thru an imperative form under Math...

Looking into this example:

Intl.NumberFormat('en').format(1.1119) // yields
"1.1112"

It looks to me that the rounding is already done, changing the supplied number.

I would appreciate having these features:

  1. Being able configure rounding (truncating ...)
  2. Have the maximumIntegerDigits option
  3. A feature to "unformat" the number to JS native number

@caridy
Copy link

caridy commented Sep 19, 2015

@bsrdjan that's not the result I'm getting, this is what I get in FF and Chrome:

Intl.NumberFormat('en').format(1.1119)
"1.112"

@bsrdjan
Copy link

bsrdjan commented Sep 21, 2015

sorry, correct, mistake in my post, is 1.112 indeed.

@smoholkar
Copy link

@rxaviers came across your proposal for different rounding methods for Intl. -
How are you currently handling this with Intl?

@caridy
Copy link

caridy commented Apr 10, 2017

@smoholkar no, this proposal hasn't get any traction.

@smoholkar
Copy link

smoholkar commented Apr 10, 2017

@caridy oh. That's a good proposal actually. Hope we get that feature in future soon.

@bsrdjan
Copy link

bsrdjan commented Apr 10, 2017

It would be very useful feature of Intl.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants