Skip to content
This repository has been archived by the owner on Jan 25, 2022. It is now read-only.

units to consider when selecting the unit #7

Closed
zbraniecki opened this issue Jun 10, 2016 · 11 comments
Closed

units to consider when selecting the unit #7

zbraniecki opened this issue Jun 10, 2016 · 11 comments

Comments

@zbraniecki
Copy link
Member

zbraniecki commented Jun 10, 2016

Currently, the spec is considering "all" units possible when trying to determine the correct one - seconds, minutes, hours, days, weeks, months, quarters, years.

We still have more units to consider like "last Tuesday", and I can see users wanting to skip "quarters" or calculate only up to days, so - seconds, minutes, hours, normally, but nothing above days (so "4500 days ago").

It seems like a simple solution would be to allow people to pass the list of units to consider:

let x = new Intl.RelativeTimeFormat(locales, {
  unit: 'best fit',
  units: ['second', 'minute', 'hour', 'day']
});

Then, if you want to add weekdays or quarters, you'd just list it as one of the units.

Does it sound realistic?

@caridy
Copy link
Collaborator

caridy commented Jun 10, 2016

We have bigger problems as described in #6, which might prevent us from using bestfit.

@rxaviers
Copy link
Member

We have bigger problems as described in #6, which might prevent us from using bestfit.

Will eventually be solved by #13 API updates. Should we resume this? :)

@caridy
Copy link
Collaborator

caridy commented Mar 17, 2017

@rxaviers yes, we can resume this.

I have been thinking about this one in the context of #7, and I think we can get away with removing best fit entirely, and let the user to do the computations if what they provided is a relative distance in ms. The computation is straight forward, and we can remain as a very low level API.

@zbraniecki
Copy link
Member Author

I'm afraid that removing bestFit would cause the user to have to create a new RTF object for each unit he'd like to format against.

Alternatively, we could have a base algorithm and let users provide a custom one, sth like:

new RelativeTimeFormat('en', {
  unit: 'bestFit',
  bestFit: function(x) {
    ...
    return 'second';
  }
});

@caridy
Copy link
Collaborator

caridy commented Mar 19, 2017

I'm afraid that removing bestFit would cause the user to have to create a new RTF object for each unit he'd like to format against.

That should not be a problem. In fact most apps that I have been will provide abstraction layers for Intl stuff since they want to control the locale, and other settings. Look at formatjs, momentjs, etc.

Alternatively, we could have a base algorithm and let users provide a custom one, sth like:

Even though this is not in ECMAScript (e.g.: Array.prototype.filter() is an example), I feel that if they pass the value x, and we call that with value x seems like a little weird. They could calculate that before passing x, and provide the unit directly as part of the creation process.

@rxaviers
Copy link
Member

With respect to bestFit... On Globalize, we chose to go with a very simple API initially that doesn't include bestFit. Therefore, in order for developers to do bestFit on their own, they actually need to instantiate several formatters (one for each unit). Not that this is a problem, but it's something to keep in mind, because it would be the case in here as well. For example, devs would have to do something like this:

let secondFmt = new Intl.RelativeTimeFormat(locales, {unit: 'second'});
let minuteFmt = new Intl.RelativeTimeFormat(locales, {unit: 'minute'});
...
let yearFmt = new Intl.RelativeTimeFormat(locales, {unit: 'year'});

function bestFitFmt(date) {
  switch(bestFitCalcs(date)) {
    case 'second': return secondFmt(date);
    case 'minute': return minuteFmt(date);
    ...
    default: return yearFmt(date);
  };
}

@zbraniecki
Copy link
Member Author

zbraniecki commented Mar 20, 2017

I believe that this conversation is relevant to both, RelativeTimeFormat and UnitFormat, which faces similar challenges.

I would say that having to create all formatters, every time you want to use it is a bad API design.
I struggle to see a use case where someone would want to just get the second unit fromatter, and not the minute and others.

I understand that we aim to focus on building low level blocks and then letting libraries use them, but I don't think that we should take it to the point where the API itself is unusable without a wrapper.

So, so far we discussed either going for a sensible "bestFit" and allow people to override it, either by specifying units (so that you can achieve what @rxaviers suggests - just say units: ['seconds'] and you have a seconds formatter) or by providing a bestFit function argument, or a dumbed down scenario where the user has to, every time, create all formatters for a given unit type to use the API.

Here's a third way. We create a stateful object not for a unit, but for a category, like digital, length etc., and then pass two arguments to the formatter:

let rtf = new Intl.RelatveTimeFormat('en', {
  category: 'duration'
});

rtf.format(2, 'second');
rtf.format(-10, 'minute');

This would do three things:

  1. Make the API realistically usable - users would be able to create a formatter and then use some logic to pick the right unit and value (which will always be calculated together) for the format call.
  2. Cache in the right place. The perf prize on creating a new formatter, negotiating languages for it etc. would be balanced.
  3. Opens up a forward compatible way to add bestFit later.

@rxaviers
Copy link
Member

@zbraniecki I like where this is going. It's only not immediately clear to me what {category: 'duration'} does in RelativeTimeFormat, since it's already about Time. Did you mean category for UnitFormat instead?

@zbraniecki
Copy link
Member Author

Oh, yes, sorry! :) For relativetimeformat, we don't need it, but we will for UnitFormat.

So, the updated proposal:

let rtf = new Intl.RelatveTimeFormat('en');

rtf.format(2, 'second');
rtf.format(-10, 'minute');

@rxaviers
Copy link
Member

@zbraniecki this API is closer to ICU http://icu-project.org/apiref/icu4j/com/ibm/icu/text/RelativeDateTimeFormatter.html.

Note that on ICU, they call RelativeUnit what we're calling type numeric, and AbsoluteUnit what we're calling type text.

@caridy
Copy link
Collaborator

caridy commented Jun 27, 2017

since we don't support best-fit anymore, this issue is not longer needed.

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

No branches or pull requests

3 participants