DateTime comparison fails in Rails - ruby-on-rails

For some reason, the comparison always fail, please check this out from Rails console :
irb(main):021:0> #game.game_date.class
=> ActiveSupport::TimeWithZone
irb(main):026:0> #game.game_date
=> Tue, 19 Feb 2013 23:15:00 UTC +00:00
irb(main):022:0> #game.game_date.to_datetime
=> Tue, 19 Feb 2013 23:15:00 +0000
irb(main):019:0> DateTime.now
=> Tue, 19 Feb 2013 23:48:38 +0330
irb(main):020:0> #game.game_date.to_datetime > DateTime.now
=> true
How come that the comparison is always wrong? I tried this as well:
#game.game_date.to_time > Time.now.to_tim
The result was true as well , while it's obvious that it is supposed to be false since 23:48 > 23:15:00.
Please note that i'm using ruby ruby 1.9.3p0 under ubuntu and Rails 3.1
Any help would be highly appreciated

You have a problem with the TimeZone:
irb(main):022:0> #game.game_date.to_datetime
=> Tue, 19 Feb 2013 23:15:00 +0000
irb(main):019:0> DateTime.now
=> Tue, 19 Feb 2013 23:48:38 +0330
You see, your game_date attribute has a +0000 TimeZone, when DateTime.now has a +0330
Try this:
#game.game_date.to_datetime > Time.zone.now

It worked to me this way, anyways not sure if it is the best way but at least working the way I'm expecting it :
#game.game_date.to_datetime > Time.now.to_datetime.change(:offset => "+0000")

Related

strftime(%Z) returns wrong result

I have this date
date = Mon, 15 Aug 2016 13:00:00 UTC +00:00
which is ActiveSupport::TimeWithZone class
Then, I need to get the time in time zone "Fiji"
start_in_time_zone = date.in_time_zone("Fiji")
This returns Tue, 16 Aug 2016 01:00:00 +12 +12:00
Then, I need to present the date with the name of the time zone, so
time_zone_abbr = start_in_time_zone.strftime("%Z")
It should return "FJT"
but returns "+12"
Any idea why?
I am using ruby 2.3.7 and rails 4.2.7
UPDATE
If I do
start_in_time_zone = date.in_time_zone("Madrid")
it returns
"CEST"
UPDATE 2
I have tried to see where the problem is by setting different time.
date=Time.utc(2018, 07, 25, 20, 30, 45)
date.class #=> Time
date.in_time_zone("Madrid") #=> Wed, 25 Jul 2018 22:30:45 CEST +02:00
date.in_time_zone("Fiji") #=> Thu, 26 Jul 2018 08:30:45 +12 +12:00
date.in_time_zone("EST") #=> Wed, 25 Jul 2018 15:30:45 EST -05:00
Sadly, it seems there is no 'FJT' abbreviation assigned to 'Fiji' in timezone data used by Rails. Also, support for those abbreviations seems patchy regarding Pacific timezones.
irb(main):002:0> DateTime.now.in_time_zone('Samoa').strftime('%Z')
=> "+13"
irb(main):003:0> DateTime.now.in_time_zone('Midway Island').strftime('%Z')
=> "SST"
irb(main):004:0> DateTime.now.in_time_zone('Samoa').strftime('%Z')
=> "+13"
irb(main):005:0> DateTime.now.in_time_zone('Tokelau Is.').strftime('%Z')
=> "+13"
irb(main):006:0> DateTime.now.in_time_zone('Wellington').strftime('%Z')
=> "NZST"
UTC offset is displayed as fallback. If it's any help, remember that full name and additional information can be retrieved with .time_zone.tzinfo on ActiveSupport::TimeWithZone objects. 'FJ' code is recognized by TZInfo::Country.
irb(main):056:0> TZInfo::Country.get('FJ')
=> #<TZInfo::Country: FJ>
irb(main):057:0> TZInfo::Country.get('FJ').zone_info
=> [#<TZInfo::CountryTimezone: Pacific/Fiji>]

Ruby date skips a date on local console

I see this in my Rails console
[7] pry(main)> Date.today
=> Sat, 16 Sep 2017
[8] pry(main)> Date.tomorrow
=> Mon, 18 Sep 2017
What could be the reason for missing a date (17 Sep)?

Different result between Date.yesterday and Date.today.prev_day and 1.day.ago in RoR

I am currently getting different results depend on which command I use to get the previous day. The only correct answer is Date.today.prev_day.
I can understand why 1.day.ago and Date.yesterday might be different based on time zones, but I would expect normalized results from the two Date calls.
irb(main):026:0> Date.today.prev_day
=> Thu, 02 Mar 2017
irb(main):027:0> Date.yesterday
=> Fri, 03 Mar 2017
irb(main):028:0> 1.day.ago
=> Fri, 03 Mar 2017 02:45:05 UTC +00:00
Why am I getting different results with these three commands?
It works as I would expect:
2.2.3 :007 > Rails.version
=> "4.2.6"
2.2.3 :002 > Date.today
=> Sun, 05 Mar 2017
2.2.3 :003 > Date.today.prev_day
=> Sat, 04 Mar 2017
2.2.3 :004 > Date.yesterday
=> Sun, 05 Mar 2017
2.2.3 :005 > 1.day.ago
=> Sun, 05 Mar 2017 00:10:13 UTC +00:00
I would start by checking the result of Date.today, i.e. is the issue in the today method or in the prev_day method. I would also check that the method hasn't been overridden somehow. You can do something like the following:
Date.today.method(:prev_day).source_location
Which returns nil for me.

How do get a random DateTime rounded to beginning of hour in Rails?

Basically I'd like to get a random datetime within the last year:
rand(1.year).ago #=> Sun, 22 Sep 2013 18:37:44 UTC +00:00 (example)
But how do I go about specifying or limiting this to times on the hour? For example:
Sun, 22 Sep 2013 18:00:00 UTC +00:00
Sat, 02 Nov 2013 10:00:00 UTC +00:00
Fri, 12 Apr 2013 21:00:00 UTC +00:00
I finally found what I was looking for. #Stoic's answer is very good but I found this available method (http://api.rubyonrails.org/classes/DateTime.html):
rand(1.year).ago.beginning_of_hour
Does exactly the same thing but looks neater and prevents you from having to write your own function.
Rounding datetime to the nearest hour in Rails would be
(DateTime.now + 30.minutes).beginning_of_hour
Not the answer to the actual question, but it does answer the title of the question (which is how i got here).
Try this:
def random_time_to_nearest_hour
time = rand(1.year).ago
time - time.sec - 60 * time.min
end
Examples:
[1] pry(main)> random_time_to_nearest_hour
=> Sun, 28 Apr 2013 16:00:00 UTC +00:00
[2] pry(main)> random_time_to_nearest_hour
=> Sat, 08 Jun 2013 15:00:00 UTC +00:00
[3] pry(main)> random_time_to_nearest_hour
=> Thu, 22 Aug 2013 23:00:00 UTC +00:00
[4] pry(main)> random_time_to_nearest_hour
=> Tue, 29 Jan 2013 14:00:00 UTC +00:00
[5] pry(main)> random_time_to_nearest_hour
=> Tue, 13 Aug 2013 06:00:00 UTC +00:00
[6] pry(main)> random_time_to_nearest_hour
=> Mon, 03 Jun 2013 08:00:00 UTC +00:00
[7] pry(main)>
Note that, this method will always floor down to the nearest hour, but since you are anyways generating a random time, it wont matter if this time is getting floor'ed down or getting round'ed. :)

Is Rails time broken for midnight?

Let's look at the date:
1.9.2p320 :008 > Date.today
=> Wed, 03 Oct 2012
1.9.2p320 :009 > Time.now
=> 2012-10-03 22:32:55 -0400
Now, given that when is midnight?
1.9.2p320 :005 > Date.today.midnight
=> Wed, 03 Oct 2012 00:00:00 UTC +00:00
Makes sense. But what about yesterday?
1.9.2p320 :006 > Date.yesterday.midnight
=> Wed, 03 Oct 2012 00:00:00 UTC +00:00
Uh, that doesn't quite make sense. Midnight today is the same as midnight yesterday? You can't be serious!
1.9.2p320 :026 > Date.today.midnight == Date.yesterday.midnight
=> true
1.9.2p320 :033 > 1.day.ago.midnight == Date.yesterday.midnight
=> true
1.9.2p320 :034 > 1.day.ago.midnight == Date.today.midnight
=> true
Oh, you are serious. What about tomorrow?
1.9.2p320 :007 > Date.tomorrow.midnight
=> Fri, 05 Oct 2012 00:00:00 UTC +00:00
Wait, if midnight today is 00:00 on the 3rd, and midnight yesterday is 00:00 on the 3th, but midnight tomorrow is 00:00 on the 5th, where's 00:00 on the 4th?
Here it is:
1.9.2p320 :010 > 0.days.ago
=> Thu, 04 Oct 2012 02:34:58 UTC +00:00
1.9.2p320 :011 > 0.days.ago.midnight
=> Thu, 04 Oct 2012 00:00:00 UTC +00:00
but isn't zero days ago today? Apparently not.
Is it me, or is this not at all internally consistent? It seem to me that Date.today should be the same as 0.days.ago.
I understand that days.ago is actually using the Time object, and that this is a time zone issue:
1.9.2p320 :030 > Date.today
=> Wed, 03 Oct 2012
1.9.2p320 :021 > Time.now
=> 2012-10-03 22:40:09 -0400
1.9.2p320 :023 > 0.days.ago
=> Thu, 04 Oct 2012 02:40:22 UTC +00:00
1.9.2p320 :022 > Time.zone.now
=> Thu, 04 Oct 2012 02:40:14 UTC +00:00
But it seems as though, given that these are convenience functions, it's kind of mean to throw a timezone assumption into one convenience function and not throw it into another convenience function, both of which, by all accounts, mean the same thing.
Even setting that aside, it doesn't seem to explain the fact that Date.today.midnight == Date.yesterday.midnight, which is– quite simply– barking mad.
Since I know that I can't be the first to have been bitten by this, I ask what am I missing?
Rails will base relative date calculations such as yesterday, tomorrow, and midnight off of Date.current which will attempt to use the configured Time.zone: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/date/calculations.rb#L46
Since your Time.zone is set to UTC, you won't get the same results as calculations based off Date.today, which will use your computer's clock time, unless you're actually sitting in UTC time.
So, if the time difference between you and UTC is greater than the time to midnight, Date.yesterday and Date.today actually return the same date!
Try setting your Rails time zone with Time.zone = 'Eastern Time (US & Canada)' or whatever time zone you're in and retry your examples.
rossta identified the culprit. You may have better luck with Time.now.to_date and specifying the time zone if necessary:
> Time.now.in_time_zone("Asia/Tokyo")
=> Thu, 04 Oct 2012 12:54:43 JST +09:00
> Time.now.in_time_zone("Asia/Tokyo").to_date.midnight
=> Thu, 04 Oct 2012 00:00:00 JST +09:00
Time.now.in_time_zone("Asia/Tokyo").to_date.yesterday.midnight
=> Wed, 03 Oct 2012 00:00:00 JST +09:00
> Time.zone = "America/Los_Angeles"
=> "America/Los_Angeles"
> Time.now.in_time_zone
=> Wed, 03 Oct 2012 20:55:35 PDT -07:00
> Time.now.to_date # using the system time
=> Wed, 03 Oct 2012
> Time.now.to_date.midnight
=> Wed, 03 Oct 2012 00:00:00 PDT -07:00
> Time.now.to_date.yesterday.midnight
=> Tue, 02 Oct 2012 00:00:00 PDT -07:00

Resources