1

バックグラウンド

created_atデフォルトの列を持つ記事モデル

レールconfig.time_zone = 'Warsaw'

created_at = local time 2012-08-19 00:15 (UTC で 2012-08-18 22:15) の記事があります。

ゴール

2012 年 8 月 19 日 (現地時間) に作成されたすべての記事を受信するには。

私の(正しく動作していない)解決策

Article.where(
  "date_trunc('day', created_at AT TIME ZONE '#{Time.zone.formatted_offset}')
   = '#{Date.civil(2012, 8, 19)}'"
)

SQL を生成するもの:

SELECT "articles".* FROM "articles"
WHERE (date_trunc('day', created_at AT TIME ZONE '+01:00') = '2012-08-19')

そして空のセットを返します。しかし、psql で同じクエリを実行すると、アーティクルが返されてしまい、混乱してしまいます。

質問

何が間違っていて、どうすれば修正できますか?

4

2 に答える 2

5

目標: 2012 年 8 月 19 日 (現地時間) に作成されたすべての記事を受け取ること。

'+01:00'(使用するように) は固定の時間オフセットであり、DST (夏時間) を考慮に入れることはできません。そのためにタイムゾーンを使用します (省略形ではありません)。これらは PostgreSQL で利用できます。

SELECT * FROM pg_timezone_names;

ワルシャワの場合、これは'Europe/Warsaw'. システムは、保存された情報から DST の境界を認識し、それに応じた時間オフセットを適用します。


また、クエリを簡素化できます。

と同様created_attimestamp [without time zone]、保存される値は、行が作成されたときのサーバーの現地時間を反映します (UTC タイムスタンプとして内部的に保存されます)。

クライアントのタイムゾーンに応じて、基本的に 2 つの可能性しかありません。

  1. 読み取りクライアントは、書き込みクライアントと同じ設定で実行timezoneされます: Just cast to date.

    SELECT *
    FROM   articles
    WHERE  created_at::date = '2012-08-19';
    
  2. 読み取りクライアントは、書き込みクライアントとは異なる設定で実行されtimezoneます: Add AT TIME ZONE '<tz name of *writing* client here>'. たとえばEurope/Warsaw、それが の場合、次のようになります。

    ...
    WHERE (created_at AT TIME ZONE 'Europe/Warsaw')::date = '2012-08-19';
    

AT TIME ZONE投稿された回答にあるようなものを二重に適用する必要はありません

省略形ではなくタイムゾーン名に注意してください。見る:

アプリケーションで複数のタイムゾーンにまたがる場合..

..列のデフォルトcreated_atnow() AT TIME ZONE 'UTC'-または他のタイムゾーンに設定します。ポイントは、どこでも同じものを使用することです。

.. または、できれtimestamptzば( )に切り替えtimestamp with time zoneます。

于 2012-08-19T13:55:06.273 に答える
1

リンクされた回答が役立ちました。次のクエリを実行する必要があります。

SELECT *
FROM   articles
WHERE (created_at AT TIME ZONE 'UTC' AT TIME ZONE 'CEST')::date = '2012-08-19';

この質問には、列 created_at の正確な定義が必要です (正確にはどのデータ型ですか?)

Rails は常に、タイム ゾーンなしのタイムスタンプとして created_at 列を作成します。したがって、最初AT TIME ZONE 'UTC'にこのタイムスタンプが UTC であることを dbms に伝え、2 番目に CEST ゾーンの日付を表示する必要があります。

于 2012-08-19T20:59:07.793 に答える