Why does a Time math calculation return one value in IRB but sends a diff value to SQL?

北城以北 提交于 2020-01-16 18:35:13

问题


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?


回答1:


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


来源:https://stackoverflow.com/questions/28911949/why-does-a-time-math-calculation-return-one-value-in-irb-but-sends-a-diff-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!