Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Date.yesterday == Date.today

#6410

Using Ruby 1.9.2p0 and Rails 3.0.3 rails console:

Date.yesterday == Date.today
=> true

This returned false with Rails 2.3.8

Date.tomorrow works correctly.

Reported by ericp (at activestate) · February 11th, 2011 @ 02:24 AM

State: committed
Milestone: none
Assigned to: Josh Kalderimis Josh Kalderimis
Importance: Medium

Activity

  1. Josh Kalderimis
    Josh Kalderimis
    • Tag changed from date yesterday today and tomorrow to active_support, core_ext

    I cannot replicate this issue on 3-0-stable branch using 1.9.2p136.

    This may of been a ruby bug, can you try a different ruby 1.9 patch level and see if you still get incorrect results.

    February 11th, 2011 @ 03:16 PM

  2. ericp (at activestate)
    ericp (at activestate)

    Bug not observed with
    Ruby 1.9.2p0 && Rails 3.0.4

    February 11th, 2011 @ 07:49 PM

  3. Jon Atack
    Jon Atack

    Like ericp
    I cannot replicate this issue with Ruby 1.9.2p0 and Rails 3.04.

    February 11th, 2011 @ 11:34 PM

  4. ouzo
    ouzo

    ruby-1.9.2-p0 :002 > Date.yesterday == Date.today
    => false

    ruby 1.9.2p0 (2010-08-18 revision 29036) [i686-linux]
    Rails 3.0.3

    February 11th, 2011 @ 11:42 PM

  5. Josh Kalderimis
    Josh Kalderimis
    • State changed from new to open
    • Assigned user set to Josh Kalderimis
    • Importance changed from to Low

    I am still doubting its a rails issue.

    Date.yesterday is very simple code and I don't see rails overriding any date equality methods.

    Have you tried updating your ruby patch version?

    February 13th, 2011 @ 12:56 PM

  6. Josh Kalderimis
    Josh Kalderimis
    • State changed from open to needs-more-info

    February 13th, 2011 @ 01:59 PM

  7. Andrew White
    Andrew White

    This is a subtle one - Date.yesterday uses Date.current which will use the time zone whereas Date.today doesn't. If you set your time zone to one where it's tomorrow already (e.g. Europe/Berlin as I type this) then you can get Date.today == Date.yesterday:

    >> Time.zone = "Europe/London"
    => "Europe/London"
    >> Date.today == Date.yesterday
    => false
    
    >> Time.zone = "Europe/Berlin"
    => "Europe/Berlin"
    >> Date.today == Date.yesterday
    => true
    

    Using Date.current == Date.yesterday works as expected.

    February 13th, 2011 @ 11:55 PM

  8. Josh Kalderimis
    Josh Kalderimis
    • State changed from needs-more-info to verified
    • Importance changed from Low to Medium

    Hey Andrew,

    Thank you for looking into this further.

    It seems its a little bit more complicated than that. In AS date/calculations you will see:

    # Returns a new Date representing the date 1 day ago (i.e. yesterday's date).
    def yesterday
      ::Date.current.yesterday
    end
    
    # Returns Time.zone.today when config.time_zone is set, otherwise just returns Date.today.
    def current
      ::Time.zone_default ? ::Time.zone.today : ::Date.today
    end
    

    What you will notice is current uses zone_default which means even if you change Time.zone it will have no effect on current eg.

    :060 > ::Time.zone_default = nil => nil :061 > Time.zone = "Pacific/Honolulu" => "Pacific/Honolulu" :062 > Date.today => Mon, 14 Feb 2011 :063 > Date.yesterday => Sun, 13 Feb 2011 :064 > Date.today == Date.yesterday => false

    I am based in Amsterdam, so today and yesterday are both correct, which shouldn't be the case as I have changed my timezone.

    You are right that Date.today doesn't use timezone aware methods, this is part of the problem, the other part is that Date.current uses Time.zone_default and not Time.zone if it is available. A Rails Railtie sets zone_default on initialization, so this is why most people do not experience any issues.

    José suggested I get in contact with the creator of the tz_info gem as he added most of this code to Rails, so I will update this ticket when I have some more info.

    Thanks for reporting this issue Ericp, and thanks Andrew for figuring out the issue.

    Josh

    February 14th, 2011 @ 10:33 AM

  9. Andrew White
    Andrew White

    Setting the timezone does have an effect - the ternary operator is just checking for the presence of zone_default but actually uses Time.zone for the calculation, e.g:

    >> Time.zone = "Europe/London"
    => "Europe/London"
    >> Date.current
    => Mon, 14 Feb 2011
    >> Date.today
    => Mon, 14 Feb 2011
    >> Date.yesterday
    => Sun, 13 Feb 2011
    >> Time.zone = "Pacific/Kiritimati"
    => "Pacific/Kiritimati"
    >> Date.current
    => Tue, 15 Feb 2011
    >> Date.today
    => Mon, 14 Feb 2011
    >> Date.yesterday
    => Mon, 14 Feb 2011
    

    The bug only exhibits itself when the timezone you've set is far enough away from the local time to be in a different day. Pacific/Honolulu is only 10 hours behind UTC, so was in today if you did the test in the preceding half an hour to posting your message.

    February 14th, 2011 @ 11:18 AM

  10. Josh Kalderimis
    Josh Kalderimis

    Hi Andrew,

    You are right that in a normal app setup current would return the current specified zone. But if you are using ActiveSupport and do not set zone_default (which is done in a Railtie) then setting Time.zone would do nothing. So both of our examples are correct.

    Although I need to confirm this, I think two changes need to occur, Date.current should check Time.zone and not Time.zone_default, and Date.today needs to be overridden to use use timezones.

    Josh

    February 14th, 2011 @ 11:54 AM

  11. Andrew White
    Andrew White

    Yes, it's probably safer to test Time.zone - however I don't think we should mess with Date.today as we don't mess with Time.now, e.g:

    >> Time.zone = "Europe/Berlin"
    => "Europe/Berlin"
    >> Time.now
    => Mon Feb 14 12:20:32 +0000 2011
    >> Time.current
    => Mon, 14 Feb 2011 13:20:37 CET +01:00
    

    We probably should just add some documentation on using Time.current and Date.current instead of Time.now and Date.today if you're messing around with time zones.

    February 14th, 2011 @ 12:23 PM

  12. Jeremy Kemper
    Jeremy Kemper

    +1 to checking Time.zone. Otherwise, agree that this is a docs issue.

    February 14th, 2011 @ 09:56 PM

  13. Repository
    Repository
    • State changed from verified to committed

    (from [9ba0c7e2164e726b45955a87dfd1173bc4e9fa78]) updated Time, Date and DateTime current methods in AS to use Time.zone and not Time.zone_default.

    [#6410 Date.yesterday == Date.today state:committed] https://github.com/rails/rails/commit/9ba0c7e2164e726b45955a87dfd11...

    February 28th, 2011 @ 10:07 PM

  14. Repository
    Repository

    (from [0f8d2794f229175447163d2b5e16d94d2cee5468]) updated Time, Date and DateTime current methods in AS to use Time.zone and not Time.zone_default.

    [#6410 Date.yesterday == Date.today state:committed] https://github.com/rails/rails/commit/0f8d2794f229175447163d2b5e16d...

    February 28th, 2011 @ 10:08 PM

  15. Robert Pankowecki
    Robert Pankowecki

    Thanks for the clarification. I find to be totally unintuitive that we need to use Date.yesterday, Date.current and Date.tomorrow. "Today" seems to be a very good fit between "yesterday" and "tomorrow". I guess that lot of people would expect that... I guess we will have to live with that.

    March 31st, 2011 @ 09:18 AM

  16. Josh Kalderimis
    Josh Kalderimis

    Hi Robert,

    I do agree with you that its a bit confusing that you need to use Date.current with Date.yesterday instead of Date.today, but the general rule of thumb is Rails does not change how Ruby methods work, which Date.today is. All we can do is add better documentation and make sure people are aware of the subtle difference.

    Thanks,

    Josh

    March 31st, 2011 @ 09:41 AM