This project is archived and is in readonly mode.

#6410 ✓committed
ericp (at activestate)

Date.yesterday == Date.today

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

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.

Comments and changes to this ticket

  • Josh Kalderimis

    Josh Kalderimis February 11th, 2011 @ 03:16 PM

    • 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.

  • ericp (at activestate)

    ericp (at activestate) February 11th, 2011 @ 07:49 PM

    Bug not observed with
    Ruby 1.9.2p0 && Rails 3.0.4

  • Jon Atack

    Jon Atack February 11th, 2011 @ 11:34 PM

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

  • ouzo

    ouzo February 11th, 2011 @ 11:42 PM

    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

  • Josh Kalderimis

    Josh Kalderimis February 13th, 2011 @ 12:56 PM

    • 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?

  • Josh Kalderimis

    Josh Kalderimis February 13th, 2011 @ 01:59 PM

    • State changed from “open” to “needs-more-info”
  • Andrew White

    Andrew White February 13th, 2011 @ 11:55 PM

    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.

  • Josh Kalderimis

    Josh Kalderimis February 14th, 2011 @ 10:33 AM

    • 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

  • Andrew White

    Andrew White February 14th, 2011 @ 11:18 AM

    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.

  • Josh Kalderimis

    Josh Kalderimis February 14th, 2011 @ 11:54 AM

    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

  • Andrew White

    Andrew White February 14th, 2011 @ 12:23 PM

    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.

  • Jeremy Kemper

    Jeremy Kemper February 14th, 2011 @ 09:56 PM

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

  • Repository

    Repository February 28th, 2011 @ 10:07 PM

    • 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 state:committed] https://github.com/rails/rails/commit/9ba0c7e2164e726b45955a87dfd11...

  • Repository

    Repository February 28th, 2011 @ 10:08 PM

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

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

  • Robert Pankowecki

    Robert Pankowecki March 31st, 2011 @ 09:18 AM

    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.

  • Josh Kalderimis

    Josh Kalderimis March 31st, 2011 @ 09:41 AM

    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

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