-
Notifications
You must be signed in to change notification settings - Fork 18
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
Fields Source of Truth #2
Comments
Maybe we could have an upper and lower field, like, {
lower: "second",
upper: "hour"
} Then, the hour, minute, and second are displayed, and all other fields from the Temporal.Duration are ignored. The default values would be {
lower: "second",
upper: undefined
} and the behavior would be to set "upper" to the largest nonzero field in the Temporal.DurationFormat. Thoughts? |
Using upper and lower fields is a great idea, because the user can specify any continuous set of fields to format the duration. However, this idea has the following problems:
|
Good point. Actually, we need to add another two fields for hiding zero value fields and rounding the smallest field
Both of those options should be determine by the user (we can give them default values if the user did not set their values) because in some formatting widths (such as Narrow), some users do not prefer to hide the zero-valued fields. And in another formatting widths (such as Wide), some users prefer to hide the zero-valued fields. |
I don't understand. Can you elaborate? For hiding internal zeros: you can technically do this by formatting manually using Intl.NumberFormat with Intl.ListFormat. var hf = new Intl.NumberFormat(undefined, { style: "unit", unit: "hour" });
var sf = new Intl.NumberFormat(undefined, { style: "unit", unit: "second" });
var lf = new Intl.ListFormat();
lf.format([hf.format(1), sf.format(50)])
// "1 hr and 50 sec" The new API is first and foremost for handling the new Temporal.Duration type, and also to enable the numeric format in #1 and generally make this more discoverable and easier to use. Is hiding an internal zero a common enough case to put into the new API? |
I think we will have two fields Therefore, the user can swap the fields without making errors
Also, the user can specify a start point or an endpoint start point
end point
|
Some discussion from the champions call today:
|
Related: tc39/proposal-temporal#533 |
What was the motivation for adopting this smallestUnit/largestUnit option? For me, the dash-separated (or ideally, array, as in #3) seems both more intuitive/readable (I immediately know what it means when reading the code) as well as expressive (as it permits gaps). What were the disadvantages found with this model? Will there be too many fields, making it annoying to write them all out? (I hypothesize that the number of fields displayed will rarely be more than 4.) |
So I talked with @younies today and reached the following conclusions:
@sffc @littledan do you agree? |
I understand the ergonomics of Compare const d = Temporal.Duration.from({days: 40}, {disambiguation: 'balance'});
new Intl.DurationFormat('en-US', {fields: ['month','day']}).format(d);
// ^ returns: 1 month and 10 days
new Intl.DurationFormat('en-US', {largestUnit: 'month', smallestUnit: 'day'}).format(d);
// ^ returns: 1 month, 1 week and 3 days Surely both are fine but I imagine some people will want to use the first value which is not possible using |
@piuccio that example is incorrect per-se because duration doesn't balance |
Oh I see, I was assuming that:
In light of the decision to not support arithmetic, what should be the behavior of? Intl.DurationFormat('en', {fields: ['month']}).format({minutes: 30});
// maybe throw a RangeError?
Intl.DurationFormat('en', {largestUnit: 'month', smallestUnit: 'day'}).format({hours: 23});
// is this:
// a) a RangeError too
// b) '0 days', or '1 day' when round:true Ignoring for a moment the week/month/year problem, I actually think that
which likely no one will prefer over |
Great point. It agree with this and also agree that cases like these make the
Currently, according the the spec, mismatches like these are ignored silently, however I agree that this is generally a bad idea. Once we finalize the decision in this thread, I'd be more than happy to discuss the issue you raised in more detail (since the choice we take here might very well affect our options). We should discuss the three cases:
|
To lay out my prefered design for the option bag:
On the question of resolving a Temporal.Duration where the fields are out of bounds of the Intl.DurationFormat largest and smallest units: I think there are a few options.
Examples:
Note that option 1 also has the side-effect of allowing you to hide zero-valued fields in the middle of the duration, for which @younies has repeatedly advocated. It would essentially make smallestUnit and largestUnit settings for where to start and end the zero-fill. |
Was there already a discussion on eliminating completely both const d = Temporal.Duration.from({ seconds: 3640 });
const f = new Intl.DurationFormat('en-US');
f.format(d);
// ^ 3640 seconds
f.format(d.balance({ largestUnit: 'minute' }));
// ^ 60 minutes and 40 seconds
f.format(d.balance({ largestUnit: 'hour' }));
// ^ 1 hour and 40 seconds
f.format(d.balance({ largestUnit: 'hour', smallestUnit: 'minute' }));
// ^ 1 hour and 0.667 minutes
f.format(d.balance({ largestUnit: 'hour', smallestUnit: 'minute' }).round());
// ^ 1 hour and 1 minute
f.format(d.balance({ largestUnit: 'hour', smallestUnit: 'minute' }).getLargestUnit());
// ^ 1 hour
f.format(d.balance({ smallestUnit: 'day' }));
// ^ 0.04 days
f.format(d.balance({ smallestUnit: 'day' }).round()).format();
// ^ 0 days
// Note that we would still need an option for showing 0 values:
const withZero = new Intl.DurationFormat('en-US', { useZeroValues: true });
f.format(d.balance({ largestUnit: 'hour' }));
// ^ 1 hour, 0 minutes and 40 seconds Basically having balancing and choosing units inside temporal duration, and duration formatter is simply converting a duration to plain text. Arguably this approach resembles what's done in It could also be argued that this approach removes all overlaps with Temporal.Duration (and a dependency on it) since all examples above can be converted with a plain object looking like The The other advantage is that DurationFormat will never throw a RangeError which sounds counterintuitive when you try to format what otherwise is a perfectly valid duration. |
We decided in #10 to not have arithmetic in Intl.DurationFormat. Given that decision, the only real purpose for largestUnit/smallestUnit on Intl.DurationFormat is to control the display of zero-valued fields. |
We narrow the discussion to the following issue #32 |
Your draft API says,
In other words, you have fields from both the Temporal.Duration and the options bag. Why do you need them in both places?
It appears that Temporal.Duration will return 0 for a field that was not set in the constructor. Is it okay to hide all leading and trailing fields whose value is 0? So for example, if you do,
then you get an hours+minutes format? Or are there cases in which you want to retain the zeroes in the leading and trailing fields?
The text was updated successfully, but these errors were encountered: