andrewplummer / Sugar

A Javascript library for working with native objects.
https://sugarjs.com/
MIT License
4.54k stars 305 forks source link

Support for generalized form of Date.relative() #500

Closed jessicard closed 9 years ago

jessicard commented 9 years ago

I'd like to be able to provide an arbitrary amount of time (probably in milliseconds) to a Sugar function and have it return a human-readable string for it. Sort of like relative, but without it being tightly coupled to today's date.

For example:

var oneDayInMilliseconds = 86400000,
    oneWeekInMilliseconds = 604800000;

console.log(humanizedAmountOfTime(oneDayInMilliseconds)); // This would output "1 day"
console.log(humanizedAmountOfTime(oneWeekInMilliseconds)); // This would output "1 week"

Right now, to hack this in, I'm using a few Sugar functions and a regex to pull out the relative bit:

({
  humanizedAmountOfTime: function(milliseconds) {
    return new Date().rewind(milliseconds).relative().replace(new RegExp(" ago$"), "");
  }
});
jakeboxer commented 9 years ago

Yes please :pray:

maxluster commented 9 years ago

+1

Slayer95 commented 9 years ago

+1

andrewplummer commented 9 years ago

This exists! http://sugarjs.com/api/Number/duration

Slayer95 commented 9 years ago

Cool! For some reason I couldn't find it in the docs...

andrewplummer commented 9 years ago

ok, will close this for now

Earl-Brown commented 8 years ago

Maybe this could be aliased into Date as ".relativeTo(otherDate)"? so

  Date.create("yesterday").relativeTo("today") 
  ===
  (Date.create("yesterday").millisecondsUntil("today")).duration()
andrewplummer commented 8 years ago

Hm, that's an interesting idea. It might be simpler on the relative method itself, as I'm always hesitant to add another method, however if it accepts strings it would be difficult to disambiguate from the locale code which is also an optional argument.

In the meantime, the method millisecondsUntil is actually not necessary (and kind of useless itself as a method, but exists for completion) as you can simply use the - operator:

(Date.create('today') - Date.create('yesterday')).duration();
andrewplummer commented 8 years ago

I should also note that these 2 methods are potentially not the same in meaning. The duration method is something of an approximation as years, months, and even days are not exact definitions when it comes to milliseconds. Therefore contextual meaning is lost when converting them into a number and back again.

relative, however, is aware of this context, and instead walks the date when dealing with these vague, higher order units. This results in a much more accurate result. For example, you would still get 1 month ago if it was March 2nd and the date was February 2nd. Converting into a number and using duration however would result in 29 days as numbers don't contain this context, so the average definition of "1 month" would have to be used. Actually, this really should have been mentioned as part of the answer to @jessicard as well.

Given this, I think it would be better to avoid duration altogether for what you're suggesting. As mentioned, I would prefer not to add another method, but only being able to accept a date wouldn't allow that sweet string syntax... Also having too many floating arguments might lead to confusion. So I think I actually am leaning toward your idea of relativeTo. The syntax is straightforward and readable, and it exposes functionality that otherwise wouldn't be accessible.

andrewplummer commented 8 years ago

Also, relativeTo would still require the same flexibility that relative has, including allowing other locales and being able to control the format, so the method signature I think would have to be: relativeTo(date, [fn], [localeCode]), where date is required and the others are optional, just like relative.