Reputation: 33775
I have a method in my Post
model that looks like this:
def self.num_posted_x_days_ago(n)
start_date = Time.now.midnight - n.day
end_date = Time.now.midnight - (n+1).day
where(created_at: start_date..end_date).count
end
When I run it in IRB, I get this:
> Post.num_posted_x_days_ago(8)
(0.3ms) SELECT COUNT(*) FROM "posts" WHERE ("posts"."created_at" BETWEEN '2015-02-27 05:00:00.000000' AND '2015-02-26 05:00:00.000000')
=> 0
Note that the Time
on the date is 05:00:00.000000
for both the start_date
and end_date
.
But when I add a binding.pry
into the method, and inspect both the start_date
and end_date
, I get this:
1] pry(Post)> start_date
=> 2015-02-26 00:00:00 -0500
[2] pry(Post)> end_date
=> 2015-02-25 00:00:00 -0500
Which shows the right time starting at midnight.
When I try to do it all manually at the console, I get this:
[31] pry(main)> Time.now.midnight
=> 2015-03-07 00:00:00 -0500
[32] pry(main)> Time.now.midnight - 9.days
=> 2015-02-26 00:00:00 -0500
[33] pry(main)> Time.now.midnight - 9.day
=> 2015-02-26 00:00:00 -0500
Notice that all the times show midnight.
What could be causing this mismatch?
Upvotes: 0
Views: 63
Reputation: 4009
Database stores time in UTC. When you display it in console it shows you your local timezone.
Assuming you're interested in posts written on a particular day in your timezone the result should be what you expected. If you want to retrieve one day of posts in UTC timezone instead replace Time.now.midnight
with Time.now.utc.midnight
---edit---
All dates stored in the database use UTC. Whenever Rails saves into database or retrieves from the database it converts from your local time zone to UTC or vice versa. That's why you see different times in SQL query. If you check the returned objects you will see that in fact these are correct results.
The only thing to keep in mind is that if you run the app on a different server it's likely that the system timezone will be different (it's a good practice to set server timezone to UTC), so Time.now.midnight
will mean something different than on your local computer.
If you want to make sure Rails always retrieves posts from midnight of EST, you need to specify timezone explicitely:
Time.now.in_time_zone('EST').midnight
or (should switch to EDT when observing daylight saving time):
Time.now.in_time_zone('America/New_York').midnight
Upvotes: 3