This project is archived and is in readonly mode.

#720 ✓resolved
Clemens Kofler

past? and future? methods for easier Date/Time comparisons

Reported by Clemens Kofler | July 29th, 2008 @ 04:09 PM

In date/time related methods, I often found myself writing stuff like

class Article
  def published?
    published_at && published_at < Time.now
  end
end

To facilitate this, I usually patched the Date/DateTime/Time classes with three methods (copying examples from the tests):

# dates:
t1, t2, t3, t4, t5 = Date.yesterday, Date.today, Date.tomorrow, 2.minutes.ago, 2.minutes.from_now

t1.past? # => true
t2.today? # => true
t3.future? # => true
t4.today? # => true
t5.today? # => true

# times/datetimes:
t1, t2 = 2.minutes.ago, 2.minutes.from_now

t1.past? # => true
t2.future? # => true
t1.today? # => true
t2.today? # => true

The same works for DateTime and Time - of course with them it's doesn't only compare the date but the whole (Date)Time.

With this, the example I mentioned at the beginning would look like this:

class Article
  def published?
    published_at && published_at.past? 
    # or !published_at.future? if you care about a single second ;-)
  end
end

IMO, this is a lot cleaner. Of course, I'm open for feedback, especially regarding the naming of the methods and the inclusion of Time#today? (I included it for consistency).

In short, this patch

  • adds three methods, past?, today? and future? to the Date, DateTime and Time class,
  • adds tests for all these methods,
  • and removes some white space from all 6 files I worked on.

Let me hear what you think.

Comments and changes to this ticket

  • Clemens Kofler
  • RSL

    RSL July 29th, 2008 @ 04:18 PM

    Ginormous amounts of +1. Tremendously useful shortcut here. I might suggest making Time#past? and DateTime#past? actually the same as !future? [or >= Time.now] since I can't think of an instance where the past? would be negatively affected by including the current second but I can think of the converse. This might just be me missing something though. ;)

  • Clemens Kofler

    Clemens Kofler July 29th, 2008 @ 04:24 PM

    Yeah, I've thought about that (to DRY it up, among other things) but I'm not sure if that would be a good idea since it kinda violates the principle of least surprise. If something is 1.second.from_now or 1.second.ago it's future or past and not yet/not any more present. That's why I implemented it this way - it leaves the programmer with the responsibility of using the one solution that seems to fit best.

  • Clemens Kofler

    Clemens Kofler July 29th, 2008 @ 05:01 PM

    Added a new version where I use DateTime#now instead of Time#now.to_datetime.

    Thanks to Tarmo Tänav for the hint.

  • José Valim
  • Alex MacCaw
  • Geoff Buesing

    Geoff Buesing July 30th, 2008 @ 01:20 PM

    • Assigned user set to “Geoff Buesing”
    • Tag changed from activesupport, core_ext, date, datetime, enhancement, patch, tested, time to activesupport, core_ext, date, datetime, enhancement, patch, tested, time, verified

    Useful stuff. A few things before this is ready:

    1. #today? should compare with ::Date.current, which will return Time.zone.today if config.time_zone is set, or Date.today, if it's not set. With this change, #today? will return true or false depending on the current Time.zone, which is expected and appropriate behavior (e.g., 11pm Jul 30 CDT is simultaneous with midnight Jul 31 EDT.)

    2. we'll need TimeWithZone implementations for #past? and #future?, because TWZ#method_missing won't give the correct results. The TWZ implementations should be as simple as:

    # implementations for TimeWithZone
    def past?
      utc.past?
    end
    
    def future?
      utc.future?
    end
    

    3. the tests should be a bit more thorough. Ideally, they'd stub out Time.now/Date.current to a specific value, and test the edges around that (i.e., one second/one day before and after the stubbed out time/date.)

  • Geoff Buesing

    Geoff Buesing July 30th, 2008 @ 01:22 PM

    What's up, Lighthouse, you say above that I added a "verified" tag, but I didn't...

  • Clemens Kofler

    Clemens Kofler July 30th, 2008 @ 01:54 PM

    Geoff: Thanks for the feedback. I realized this morning that I missed the timezone stuff but I had appointments so I couldn't fix it right away. I'll work on it as soon as I'm home. Thanks for the info on how to implement it.

    Regarding the verified tag: I added it without leaving an additional comment after I had 3 x "+1" and it seems that Lighthouse then automatically adds it to the next user who leaves a comment. -> blame Rick! ;-)

  • José Valim

    José Valim July 30th, 2008 @ 06:33 PM

    I also have "yesterday?" on some of my projects.

    Maybe that fits the patch also?

  • Jeremy Kemper

    Jeremy Kemper July 30th, 2008 @ 06:48 PM

    • State changed from “new” to “open”
    • Milestone cleared.
  • Clemens Kofler

    Clemens Kofler July 30th, 2008 @ 06:52 PM

    José:

    Not sure there. I only added the today? method because I've used it in one project where I needed one-day lotteries and I've used it in PHP before for pretty much the same purpose. I think the really valuable methods are past? and future? (hence today? isn't even included in the title of this ticket).

    Where would you use the yesterday? method?

  • José Valim

    José Valim July 30th, 2008 @ 07:08 PM

    I have an application that is calendar based. I'm showing the dates as expected (11 July, 2008), but when it comes to today or yesterday, I'm showing "Today" or "Yesterday" instead of the date because it's more readable.

    You can check it at www.pagestacker.com.

  • Clemens Kofler

    Clemens Kofler July 30th, 2008 @ 10:09 PM

    Ok, that makes sense. But if we'd add yesterday? we'd have to add tomorrow? as well for the sake of completeness. Granted, it's not a big thing but it makes this whole thing way bigger than I originally intended! ;-)

  • Brady Bouchard

    Brady Bouchard July 31st, 2008 @ 05:34 AM

    Sticking to past? and future? seems like the best way to go here. The basic functionality you're going for is checking if something with a published_at date should show up as published, which is hella useful for a ton of projects. tomorrow? and yesterday?, not so much.

    I think you've got a good thing going as is.

  • DHH

    DHH September 10th, 2008 @ 06:34 AM

    I really like this. Would be great to get wrapped up per gbuessing's comments.

  • Clemens Kofler

    Clemens Kofler September 10th, 2008 @ 02:59 PM

    I'd totally forgotten about this ticket. Here's the ticket including the stuff Geoff suggested.

  • Geoff Buesing

    Geoff Buesing September 11th, 2008 @ 12:39 AM

    Clemens, thanks for the updated patch. This looks good, one small thing -- in TimeWithZone#today?, you'll want to call this method on #time instead of #utc, given that the date values of the utc time may be different than the local time (the local time that gives the correct date values for the TWZ).

    Also, I notice that the diff file is a compilation of twelve separate commits -- might make sense to flatten those into just one commit.

  • Clemens Kofler

    Clemens Kofler September 11th, 2008 @ 11:53 AM

    I've packaged the commits as one - here's the new patch. Unfortunately, I don't really understand the thing with the #today? method - maybe you could fix that one, if you don't mind?

  • Geoff Buesing

    Geoff Buesing September 12th, 2008 @ 12:29 AM

    No problem, I can fix #today?. Thanks for pulling this into one commit.

  • Repository

    Repository September 15th, 2008 @ 04:57 AM

    • State changed from “open” to “resolved”

    (from [cce7ae54663243a224e9871f1aac2388842b0c3a]) Add thorough tests for Time-object #past?, #future? and #today. Fix TimeWithZone #today? to use #time instead of #utc for date comparison. Update changelog. [#720 state:resolved] http://github.com/rails/rails/co...

  • Ryan Bigg

    Ryan Bigg October 9th, 2010 @ 10:00 PM

    • Tag cleared.

    Automatic cleanup of spam.

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Referenced by

Pages