Consider the table:
create_table :entries do |table|
table.integer :amount
table.date :worked_at
end
Now consider the model:
class Entry < ActiveRecord::Base
scope :recent, lambda {
start_at = Date.today.beginning_of_week
end_at = Date.today.end_of_week
where(worked_at: start_at..end_at)
}
Great? Cool. Now to ask Rubo cop...
C: Rails/Date: Do not use Date.today without zone. Use Time.zone.today instead.
start_at = Date.today.beginning_of_week
^^^^^
wat. I mean I realize I can turn off this cop, but it's actually really nice when it's applied to Time and DateTime.
What do you mean saying "to be less performant"?
It's just telling you that it is dangerous to use Date.today without time zone specified because it can lead to undesirable results (today's date is different in different time zones, isn't it?).
No. More importantly it's not telling me to say that because the message reads:
Use Time.zone.today instead.
@krainboltgreene What @palkan meant was "the date for 'this instant, now' is different in different places." Quick example: when it's 8 AM Monday 8 June here in Singapore, it's 1 AM Monday 8 June in London (because DST is in effect; otherwise the difference is 8 hours), and 5 PM Sunday 7 June in Seattle (again, with DST in effect). So "today" _can_ have different meanings for a user of an online app sitting in one location than from another user in another place, and code that doesn't take that into account will, at best, confuse and annoy the users not in the same time zone as the app is hosted in.
Is that clearer?
Yes, I know what @palkan is saying, but there's a reason Date doesn't define .zone. Timezones don't matter when the lowest level you care about is a day.
The explanations from @palkan & @jdickey seem clear enough to this random reader from the internet. I suggest closing the issue.
WAT.
How does this seem "clear"? It's literally telling me to do the wrong thing.
Date.today returns "today" in the timezone of your server, not the client's timezone. They can be different days. Therefore, your Entry.recent can give results from the wrong week, from the client's perspective. (It will seem correct to you, if you are in the same timezone as your server.)
If you have unit tests on Entry.recent, this gem may expose the bug: https://github.com/alindeman/zonebie
I sincerely hope my explanation helps. Please expand on your point of view if you disagree. Timezones are hard.
If I say I'm flying to new york on the 15th, from Russia, I don't specify Russia's timezone on the 15th.
There's a reason there's no such thing as Date.zone.
Timezones are not hard, quit soundbyting.
Alright, I'll try to explain it where I think you are getting confused, using your example.
Let's say you are taking a flight from Russia to New York on July 12th, 2015 in Russia. Let's say your server is located in Colorado. Sadly, it's not July 12th in Colorado, as Russia is one day ahead (kinda). If you ask for Date.today.beginning_of_week you will not get the 12th, you will get the 5th, because the date in Colorado is actually the 11th.
On the contrary, if you are in New York, your app will probably work because the timezones aren't too different. Though it will break around 12-2 am on a Sunday due to the same issues I mentioned.
I get everything about this. I'm writing a system surrounding it. My system
works just fine, because the 15th in CST is the same as the 15th in GMT.
The issue you're describing _is not a result of not using Time.zone, but
rather clearly a disjoint between the User input and the server logic_.
There's a reason Date.zone doesn't exist, it's because date data doesn't
care about anything related to the hours.
What I can't get that I'm having this conversation.
15th in CST is the same as the 15th in GMT
This is true for 18 hours of the day.
ActiveSupport::TimeZone::MAPPING.values.map do |zone|
Time.zone = zone
Date.today
end.uniq # => [Wed, 15 Jul 2015]
Wacky.
24.times.map do |hour|
time = Time.local(2015, 1, 1, hour, 0, 0)
Timecop.travel(time)
ActiveSupport::TimeZone::MAPPING.values.map do |zone|
Time.zone = zone
Date.today
end
end.flatten.uniq # => [Thu, 01 Jan 2015]
That's just weird!
Arguments about Dates and Zones aside, this rule just simply shouldn't apply to dates. It's wrong, it's proposed solution is less correct than using Date, and actually causes issues when you _do_ switch to a Time.zone while having a date column.
_It will cause issues_.
Date.today doesn't support timezones. That's the bug in Entry.recent and the two examples you just posted.
ActiveSupport::TimeZone::MAPPING.values.map do |zone|
Time.zone = zone
Time.zone.today
end.uniq # => [Wed, 15 Jul 2015, Thu, 16 Jul 2015]
No shit once you include zones it freaks out, what do you not get?
Rubocop is garbage.
Rubocop is garbage.
If you say so it must be true. Feel free to create something better.
@krainboltgreene Active Support of course has the notion of TZ for dates. An idiomatic Rails application writes Date.current to produce a date for today _according to the application TZ_. The uniform interface going through Time.zone is a valid alternative.
Most helpful comment
Rubocop is garbage.