Rails 不转换时区 (PostgreSQL)

发布于 2024-11-02 17:53:34 字数 1009 浏览 0 评论 0原文

我对时区和 postgresql 数据库(Rails 3.0.4,PostgreSQL 9.0)有问题。我正在使用自定义范围,在其中附加一些条件,执行连接等。

问题是,Rails 不会将时间转换为我的本地时区。 以下是范围的代码:

  scope :with_activities_within_range_in_week, lambda{ |latMin, lngMin, latMax, lngMax, date|
    select("date_trunc('day', activities.starting_at) as date,
      count(activities.id) as value
    ") \
    .within(latMin, lngMin, latMax, lngMax) \
    .joins(:activities) \
    .merge(Activity.in_week(date)) \
    .group("date") \
    .order("date")
  }

inside 方法检查范围,Activity.in_week 范围返回此:

where("activities.starting_at >= ? AND activities.starting_at < ?", start, stop)

在 select 语句中,我想将starting_at 字段截断为day。

我得到日期字段的以下输出:

2011-04-07 18:48:32
2011-04-02 14:07:20
2011-04-02 14:06:49

不幸的是它不包括时区。当我尝试通过“正常”Rails 函数访问我的模型时,它起作用了:

puts Activity.first.starting_at
-> 2011-04-15 06:47:55 +0200

我做错了什么?希望有人可以帮忙!

谢谢, 无尾礼服

I have a problem with timezones and a postgresql db (Rails 3.0.4, PostgreSQL 9.0). I'm using a custom scope, in which I append some conditions, do joins etc.pp.

The problem is, that Rails don't convert the times to my local timezone.
Here is the code of the scope:

  scope :with_activities_within_range_in_week, lambda{ |latMin, lngMin, latMax, lngMax, date|
    select("date_trunc('day', activities.starting_at) as date,
      count(activities.id) as value
    ") \
    .within(latMin, lngMin, latMax, lngMax) \
    .joins(:activities) \
    .merge(Activity.in_week(date)) \
    .group("date") \
    .order("date")
  }

The within method checks for ranges, the Activity.in_week scope returns this:

where("activities.starting_at >= ? AND activities.starting_at < ?", start, stop)

And in the select statement, I want to trunc the starting_at field to day.

I'm getting the following output for the date field:

2011-04-07 18:48:32
2011-04-02 14:07:20
2011-04-02 14:06:49

Unfortunately it doesn't include the timezone. When I try to access my model through the "normal" Rails functions, it works:

puts Activity.first.starting_at
-> 2011-04-15 06:47:55 +0200

What I'm doing wrong? Hope someone can help!

thx,
tux

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

如果没结果 2024-11-09 17:53:34

您的数据库正在以 UTC 格式存储时间戳(理应如此)。当 ActiveRecord 知道它有时间戳时,它就会进行时区调整;所以,当你这样说时:

puts Activity.first.starting_at

AR 知道 starting_at 是一个时间戳,因此它将时间戳实例化为 ActiveSupport::TimeWithZone 实例,该类应用时区调整。但是,当您这样说时:

select("date_trunc('day', activities.starting_at) as date ...

AR 不会解析 SQL 来确定 date_trunc 将返回时间戳,AR 甚至不知道 date_trunc 的含义。 AR 只会看到从数据库中出来的字符串,然后它会将其交给您而不进行解释。您可以自己将该字符串提供给 ActiveSupport::TimeWithZone(或您最喜欢的时间处理类):告诉 AR 自己不知道也不可能知道的事情并没有什么问题。

Rails 很聪明,但它并不神奇。

Your database is storing your timestamps in UTC (as it should). ActiveRecord is making timezone adjustments when it knows that it has a timestamp; so, when you say this:

puts Activity.first.starting_at

AR knows that starting_at is a timestamp so it instantiates the timestamp as an ActiveSupport::TimeWithZone instance and that class applies the timezone adjustment. But, when you say this:

select("date_trunc('day', activities.starting_at) as date ...

AR isn't going to parse the SQL to figure out that date_trunc will return a timestamp, AR doesn't even know what date_trunc means. AR will just see a string coming out of the database and it will hand it to you without interpretation. You are free to feed that string to ActiveSupport::TimeWithZone (or your favorite time handling class) yourself: there's nothing wrong with telling AR things that it does not and cannot know on its own.

Rails is clever but it isn't magic.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文