2

「スナップショット」データを保存するテーブルがあります。勤務中のスタッフの数が 10 分ごとに取得され、そこに保存されます。特定の平日 (たとえば、過去 4 日間の日曜日) の 1 日を通して勤務しているスタッフの数を示すレポートを生成したいと考えています。

Rails では、クエリは次のようになります。

<model>.where("EXTRACT(dow FROM (time + interval '#{time_zone_offset} hours')) = ?", Time.zone.now.wday)
       .where('time BETWEEN ? AND ?', 5.weeks.ago.end_of_week, 1.week.ago.end_of_week)
       .select("organisation_id, date_trunc('hour', time) as grouped_time, avg(staff) as staff")
       .group("grouped_time").order("grouped_time")

これは、次の SQL に変換されます。

SELECT date_trunc('hour', time) as grouped_time, avg(staff) as staff
FROM <model>
WHERE (EXTRACT(dow FROM (time + interval '10 hours')) = 0)
AND (time BETWEEN '2013-09-22 13:59:59.999999' AND '2013-10-20 13:59:59.999999')
GROUP BY grouped_time
ORDER BY grouped_time

この場合、time_zone_offsetルックアップを行っているユーザーによって異なります。

def time_zone_offset
  @tzoffset ||= ActiveSupport::TimeZone[current_user.organisation.time_zone].utc_offset / 60 / 60
end

(現在のタイム ゾーンも around_filter に設定されているため、これら1.week.agoは正しいゾーンに含まれます。)

私のデータベースのタイムゾーンは UTC ( set TIME ZONE 'UTC') です。

これは機能しますが、手動で操作するよりも、特定の曜日のレコードを検索するためのより良い方法があると確信していますinterval。また、それが適用されるタイムゾーンの DST では機能しないと思います。PostgreSQL がを特定のタイム ゾーンに変換time with time zoneできることは知っていますが、これには日付が含まれていないため、曜日がわかりません。私が試した他のWHERE句:

  • EXTRACT (dow from time') = 0- これにより、日曜日の午前 10 時から月曜日の午前 10 時までのスナップショットが得られます

  • EXTRACT (dow from time at time zone 'Brisbane/Australia') = 0- これにより、日曜日の午後 8 時から月曜日の午後 8 時までのアクションが可能になります。私の理解では、これは、Postgres がフィールドをUTC からブリスベン時間に変換するtimeのではなく、ブリスベン時間であるかのように扱うために発生するということです。

したがって、このクエリを機能させるために何かすべきことがあるかどうか知りたいです。

4

1 に答える 1

3

AT TIME ZONEa に適用すると atimestamp without timezoneが生成されますtimestamp with timezone(およびその逆)。そして、これtimestamp with timezoneはセッションのタイムゾーンで解釈されます(あなたの場合は強制されますUTC)。

そのため、式EXTRACT (dow from time at time zone 'Brisbane/Australia')は Brisbane at time(UTC)timeの日付を抽出するのではなく、UTC タイム ゾーンに仮想的に住んでいる人の視点から変換された に対応する日付を抽出します。

例として、これを入力しているとき、UTC のふりをしている場合:

=> タイムゾーンを「UTC」に設定;
=> タイムゾーン「オーストラリア/ブリスベン」で now(),now() を選択;
             今 | タイムゾーン          
------------------------------+---------------------------------- --------
 2013-10-27 18:01:03.15286+00 | 2013-10-28 04:01:03.15286

わかりました。UTC では日曜日の 18:01、ブリスベンでは月曜日の 04:01 です

しかし、タイムゾーンの変位を a に適用する場合timestamp without timezone:

select now(),now()::timestamp at time zone 'Australia/Brisbane';
              今 | タイムゾーン            
-------------------------------+------------------ -------------
 2013-10-27 18:01:57.878541+00 | 2013-10-27 08:01:57.878541+00

2 番目の列が前の結果とどのように異なるかに注意してください。実際には、UTC で表したブリスベンから 20 時間離れています。これはおそらく、あまり意味のない質問に対する技術的に正しい答えです。

おそらくあなたはこれが欲しい:

EXTRACT (dow from (time AT TIME ZONE 'UTC') at time zone 'Brisbane/Australia')=0

timeどちらが答える必要がありますか: UTC で測定された日付と時刻は、ブリスベンの日曜日に対応していますか?

于 2013-10-27T18:10:59.150 に答える