6

タイムゾーンと postgresql データベース (Rails 3.0.4、PostgreSQL 9.0) に問題があります。私はいくつかの条件を追加し、結合などを行うカスタムスコープを使用しています.pp.

問題は、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")
  }

within メソッドは範囲をチェックし、Activity.in_week スコープはこれを返します。

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

select ステートメントでは、starting_at フィールドを 1 日に切り詰めたいと思います。

日付フィールドに対して次の出力が得られます。

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

私が間違っていることは何ですか?誰かが助けてくれることを願っています!

thx、タックス

4

1 に答える 1

5

データベースはタイムスタンプを 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 は賢いですが、魔法ではありません。

于 2011-04-21T08:13:26.050 に答える