-
Notifications
You must be signed in to change notification settings - Fork 603
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
Support relative time #205
Comments
I have a fresh implementation with unit tests in https://github.com/ichernev/moment-cldr. I can morph it into a pull request in the future :) |
OK, so we talked with @rxaviers and sort-of decided on part of the API. For relative duration: ... globalize.relativeDuration(value, unit);
globalize.relativeDuration(date, unit);
globalize.relativeDuration({from: date, to: date}, unit); Where
Also absolute duration: globalize.absoluteDuration(value, unit, [{length: length}]);
globalize.absoluteDuration(date, unit, [{length: length}]);
globalize.absoluteDruation({from: date, to: date}, unit, [{length: length}]); Where length is |
For relative duration, is the unit argument always required? I don't think it should, so that it can pick the closest unit, like GitHub does on these comments here. "21 hours ago", "2 days ago", based on the "to" and "from" dates, without any unit. Also, can you provide one or two examples for each of the six suggested methods? That would help a lot understanding the details here without having to ask to many questions. |
It is possible to auto pick, but then you might want to control that - cutoff points and range of units. So if we choose that we'd better also have the low level unit interface. |
Usually, hard problems can be divided into smaller and simpler problems for easier resolution. But, defining the edges or the roles of the involved entities are sometimes not an easy task. Globalize is an i18n library. So, the way I see it is: Globalize should focus on the i18n part of the problem. It should allow user-code not to worry about the i18n difficulties. In the other hand, it should minimize implementing anything else, so we don't restrict our usage, ie. the greater the chances Globalize can be used for different use cases. In the last meeting, @ichernev and I have discussed about this API and came up with the above, which is: let's implement here the low level interface (or the i18n interface). On my initial conception of this API, I have also mimic'ed twitter api and rails code, which returns an approximate result. Each interface uses a different algorithm for the approximation. Talking with @ichernev, he showed me some other complex cases that moment.js experienced. So, it turned out that taking care of the approximating should be made by a separate entity/code. |
Is it possible to implement a simple approximation, while offering the low-level methods as an alternative for anyone who needs custom cutoff points and range of units? |
All simple implementations fall short for some "obvious" cases, and there would be people in the future reporting those bugs and you having to fix them. I'm right now fixing moment's implementation because it was half an year off for dates from 30 years ago (using a very simple and straight forward approach). Now that we know what would go wrong with the simple approach, saying in the docs "well this doesn't actually work", isn't very cool :) But if you think its helpful we can have those methods. |
Well, my perspective is from the maintenance of this tiny jQuery plugin (for whatever reason it depends on jQuery): https://github.com/jzaefferer/jquery-prettydate/blob/master/jquery.prettydate.js#L146 This is pretty simple and I never had any complaints about the approximation. It makes sense that moment is used much more and therefore ends up with more people finding issues. Its just that I feel like the whole point of relative time is to provide the approximation, without it it seems useless to me. If we end up with moment providing a solid implementation, while using Globalize for the low-level stuff, that's probably fine. Your call. |
Ok, so what about something like this: globalize._relativeDuration(value, unit); // 5 days -> 5 days. 1 day -> tomorrow, 365 days -> 365 days
globalize.relativeDuration(value, input_unit); // input_unit defaults to ms, 5 days -> 5 days. 365 days -> 1 year
globalize.relativeDuration(date); // defaults to {from: now, to date}
globalize.relativeDuration({from: from, to: to}); // auto picking of unit |
May I propose a slight change? .formatRelativeDate( date, options ); // defaults to {from: now, to: date}
.formatRelativeDate({ from: from, to: to }, options ); Examples: .formatRelativeDate( inTwoDays ); // in 2 days
.formatRelativeDate( twoDaysAgo ); // 2 days ago
.formatRelativeDate( twoDaysAgo, { unit: "hour" }); // 48 hours ago
.formatRelativeDate( twoDaysAgo, { unit: "hour", tense: null }); // 48 hours
fromToValue = { from: twoMonthsAgo, to: oneMonthAgo };
.formatRelativeDate( fromToValue ); // 1 month
.formatRelativeDate( fromToValue, { unit: "week" }); // 5 weeks
.formatRelativeDate( fromToValue, { unit: "day" }); // 30 days
.formatRelativeDate( fromToValue, { unit: "day", tense: "past" }); // 30 days ago Options:
What do you think? PS: The "yesterday" vs. "1 day ago" problem: Can be solved by letting users hack locale data to suite their needs if they need anything different than the default. For example, if user needs If user needs "yesterday" on parts of his app and "1 day ago" on others, user can always load two different locales. for example, the default The "Tue" vs. "Next Tue" problem: Again, let user tweak locale data if he needs anything different than the default. If the case, we can help them submit fixes to CLDR. |
My proposal was the simplest one that would have unit auto-detection and raw api. If we want to go the extra mile and put form (only for absolute time), unit and tense, then its more work / and features. I guess jquery never had a strive for minimalism, so that's fine with me too. It means moment will be a very thin wrapper. I guess we also need (in lieu of the other two methods): globalize.relativeDuration(value, input_unit, options); @jzaefferer what do you think? |
Why would you think that? As for the proposals, I find all of them rather poorly named. Sticking everything into a single method doesn't make a good API. How about at least two separate methods? As for the options @rxaviers suggested: Tense and form options look like they could be combined - why do you suggest that |
Any name idea?
Because, there is no CLDR data for different forms on present or future tense. |
We'll actually have 2 methods: .formatDuration(value, [input_unit], [options]); // relative/absolute come from options
.formatRelativeDate(date, [options]);
.formatRelativeDate({from: date, to: date}, [options]); The raw one can be achieved by: .formatDuration(value, input_unit, {unit: input_unit}); We might have relative and absolute methods separately: .formatRelativeDuration(...);
.formatAbsoluteDuration(...); Not sure if we need the absolute date format. But in general I think relative/absolute is better outside of options (separate methods) because they have different use case. |
Naming is hard. I'm also kinda confused with the function names we currently have vs. what to expect from them. For me, duration, relative time, time distance, time span all means the same stuff. They are all synonymous. So, having two functions: duration vs. relative date together confuses. Because, it's hard to tell what the difference between them is. I vote for I vote for |
Is it correct the |
Format unit us for absolute duration (2s). Format duration is for relative duration (in 2 seconds) |
Expanding the examples... (description updated accordingly) formatDuration .formatDuration( value[, options] );
.formatDuration( inTwoDays ); // in 2 days
.formatDuration( twoDaysAgo ); // 2 days ago
.formatDuration( twoDaysAgo, { unit: "hour" }); // 48 hours ago
.formatDuration({ from: christmas2001, to: newyear2002 }, { unit: "day" }); // in 7 days Value: Date instance, or object with Options:
formatUnit (which we'll implement as a separate issue #252) .formatUnit( value, unit[, options] ); // 1 month
.formatUnit( 1, "month" ); // 1 month
.formatUnit( 5, "week" ); // 5 weeks
.formatUnit( 30, "day" ); // 30 days
.formatUnit( 30, "day", { form: "narrow" }); // 30d Value: Number Unit: String, eg. "month", "day", etc. Options:
|
@ichernev, perhaps, we could start implementing formatDuration by requiring the unit option. In a subsequent step, we could implement the auto-guess unit thing or even rethink whether or not we should include it. What do you think? |
@jzaefferer |
Isn't Anyway, this API looks good to me. |
|
Exactly, inflections and other complex stuff about languages doesn't allow "+" operations in i18n. |
I think we need to put the low-level functionality (just nice interface on top of cldr data) in cldr.js itself. For example The higher level API (like auto-detecting the unit, subtracting dates and such) should go in globalize. In that light two methods |
To properly format a unit, pluralization is required. That would mean cldr.js should support pluralization too, which is quite complex. |
Isn't pluralization data part of cldr data? If yes I guess it should go in cldr, or at least be able to be in with a plugin. I agree its hard to implement but its also very low-level, and well defined. So I think it should go in a separate lib, that goes in hand with cldr.js. |
Nope. It's part of the Globalize's pluralization module (borrowing the plural rule parsing from santhoshtr/CLDRPluralRuleParser), which hasn't been landed on master yet (but will)... Cldr.js facilitates CLDR (data) access/manipulation. Globalize, i18n. Comparing them to a filesystem, I would say cldr.js would grab the bytes of an mp3 file from the disc, Globalize would decode and play it. So, as long as an operation is part of making the access of a CLDR data easier, I think it's very clear it should be in cldr.js. Although, any operation that interprets the data somehow, I think it should be in an i18n library. Do you think it makes sense? |
A minor update to the API: Renaming |
Closing this issue in favor of a clean #391, which contains what has been discussed in here. |
Support relative times:
API
Examples:
Value: Date instance, or object with
from
andto
keys and Date instance values. When there's only one argument, it's consideredto
andfrom
defaults to now (new Date()
).Options:
Returns:
(analogous for future)
CLDR
Relative time fields can be found on /dateFields.json.
Other
References:
The text was updated successfully, but these errors were encountered: