Humanizing dates

Hello!

What would be the easiest way to pick up a Date or DateTime object and
“humanize” them, like:

  • Next wednesday
  • Last friday
  • 10 hours ago
  • Next month

Is there a Ruby library, gem or Rails plugin that helps on assembling
such
phrases from date/datetime information?

Could someone put me on the right direciton?

Thanks!

Marcelo.

distance_of_time_in_wordshttp://rails-doc.org/rails/ActionView/Helpers/DateHelper/distance_of_time_in_wordsmight
be like what you’re looking for (from
ActionView::Helpers::DateHelper).

Cheers,
James Brooks
Good Dog Design

On Thu, Aug 7, 2008 at 9:54 AM, Marcelo de Moraes S.
<[email protected]

Thanks a lot!

This solves almost all of my specs.

One thing that I’m trying to figure out,though, is, given a date, output
something like:

“Last wednesday” or “Next friday”…

Would you know a solution from the top of your head?

Marcelo.

I don’t know of something that works that way around, that you might
have to
code yourself. Perhaps you could get inspiration from a gem called
chronic
(which does the reverse of what you want, e.g. It can take a string
“next
wednesday” and calculate a date)… Maybe it can do the reverse, I’ve
never
checked :slight_smile:

Cheers,
James Brooks
Good Dog Design

On Thu, Aug 7, 2008 at 11:08 AM, Marcelo de Moraes S. <

I saw this and hacked up some code: 4363’s gists · GitHub

You should be able to put that in your lib/ folder in your app, do
require ‘proximity’ in your config/environment.rb file and then you
can call date.to_words. The same code could be applied to Time as well
afaik.

Thanks James, I will do that.

Clever and simple solution, perfect.

The issue with date/time is that things can get ambiguous and complex.
The
solution provided before could work to some extent and were similar but
much
more complex and while I could add code to support the use-case, I’m
just so
glad you did and shared it! Thanks a lot!

Marcelo.

Hey Philip,

I think that, for weekday names, you have to keep you have to take into
account the week (7 days).

For example, let’s say we have a Date object that “A” represents
11/08/2008
and another one “B” that represents 18/08/2008. Both are mondays.

Now, we have a Date object that represents today - 07/08/2008.

If you load Ryan’s code and do this:

A.to_words

The following will happen:

  1. Is this date the same as today (Date.today)? If so, output “Today”;
  2. Is this date the same as yesterday (Date.today-1)? If so, output
    “Yesterday”;
  3. Is this date included in the set = {today - 7 (one week ago) …
    yesterday} - this will essentially create an array that has date objects
    from one week ago until yesterday. If the date is included in this
    array,
    and as we have considered it to be “last week” and as we know that the
    date
    is not yesterday, nor the current date nor tomorrow, we can say this
    date
    was the last “weekday”.
  4. Applies the same logic as above, but inverted (one week from now).

Now, things get a little more complicated. For example, the next test
says:

elsif ((Date.today + 8)…(Date.today + 14)).include?(self)
“Two #{self.strftime(”%A")}s away"

What does that mean? From what I could understand, the test checks if
the
Date object being converted is in a period of time that starts one week

  • 1
    from now ( ss ) and ends two weeks - 1 from now. Considering we have the
    following date object: 14/08/2008 and today is today’s date
    (07/08/2008):

today + 8 = 15/08/2008
today + 14 = 21/08/2008

S M Tu W Th F S S M Tu W Th { F S S M Tu W Th } F S S …
| |
|
Today 14/08/2008 |

21/08/2008

This test wouldn’t catch our date object, but the previous one would do
(Next #{weekday}).

But one important point is that he seems to build upon last the previous
tests, so I think the order is important, and also explains the odd
offsets
he does in the checks, the code “considers” something like “hey, if this
date is not tomorrow then I can omit tomorrow from the next check…”.

Calculations with Dates are confusing, at least to me. That’s how I
could
interpret Ryan’s code, and I’m sure it is not a complete view yet. I
don’t
know if there’s a pattern for such thing or any way to simplify this
code,
that’s with Ryan!

Please, correct me if I’m wrong!

Marcelo.

I tried simplifying the code this morning, first it would check to see
if the date was today, if so just print today, then it would check if
the date is less than today and if so run all the checks for dates
less than today, else run all the checks for dates greater than today.
I think I updated the gist (can’t check, on train writing emails
offline) and there’s a person called lachie who forked it which may
make the code a bit cleaner for you.

That is neat. I don’t have anything real to contribute other than for
some odd reason I was talking about this issue last night with my wife
(not ruby, but the date thing).

Let’s say it’s Thursday.

Is “next saturday” in two days? Or in nine? We decided it was nine.
“this saturday” is in two days. But we agreed that “the next
saturday” is in two days.

So, when you say “next saturday” which do you mean? :slight_smile:

Maybe it’s just us and the folks around us that gets confused by that,
but it’s something to consider.

-philip

Cool. Just checked it out. I’m glad my post turned out into something
useful
for the community :slight_smile:

Also, I would like to note that this could be used together with the
distance_in_time_in_words. Even though they appear to be similar, they
fit
in different use cases. I can see that distance_in_time_in_words tries
do be
more general and count in days/months and years, not weeks, also it
doesn’t
print weekdays. But it is useful for building more granular historical
data,
like “less than 1 hour ago”, and Ryan’s to_word more useful for schedule
and
calendar use-cases.

Cheers,

Marcelo.

I just read Philip’s post and I realised that Date.today +
1…Date.today + 7 says “Next ”, instead of "This …
interesting point. I’ve updated the gist again:

It will now display “this coming Friday” for example of it’s within
the range of 6 days from today. This should mean that it’ll say “this
coming Thursday” for thursday next week, and “next Friday” for the
friday that follows.