これにより、@Catcall によって提供される進行中の作業が進められます。
SELECT count(*)
FROM generate_series(0, extract(days from timestamp '2013-02-25 11:18:36'
- timestamp '2013-01-23 10:47:52')::int * 24) n
WHERE extract(ISODOW from timestamp '2013-01-23 10:47:52' + n * interval '1h') < 6
AND (timestamp '2013-01-23 10:47:52' + n * interval '1h')::time >= '09:00'::time
AND (timestamp '2013-01-23 10:47:52' + n * interval '1h')::time < '17:30'::time
timestamp '2013-01-23 10:47:52-05'
あなたが考えているように見えることをしていません。-05
リテラルを にキャストしたため、タイム ゾーン オフセットは破棄されますtimestamp [without timezone]
。あなたはおそらく望んでいtimestamptz '2013-01-23 10:47:52-05'
た。ただし、通常、勤務時間は現地時間に拘束されるため、最初はその方が適切であると主張できますtimestamp [without time zone]
。この関連する回答の詳細:
Rails と PostgreSQL でタイムゾーンを完全に無視する
このフォームははるかに効率的です
timestamptz '2013-01-23 10:47:52-05' + n * interval '1h'
これより:
timestamptz '2013-01-23 10:47:52-05' + (n || ' hours')::interval
任意の間隔を単純に掛けることができます。
関数
さらに開発し、SQL 関数にラップしました。
まだ正確ではありませんが、系統誤差が修正され、30 分単位による丸め誤差が小さくなっています。
CREATE OR REPLACE FUNCTION f_worktime83(t_start timestamp
, t_end timestamp)
RETURNS interval AS
$func$
SELECT (count(*) - 1) * interval '30 min' -- fix off-by-one error
FROM (
SELECT $1 + generate_series(0, (extract(epoch FROM $2 - $1)/1800)::int)
* interval '30 min' AS t
) sub
WHERE extract(ISODOW from t) < 6
AND t::time >= '09:00'::time
AND t::time < '17:30'::time
$func$ LANGUAGE sql
電話:
SELECT f_worktime83('2013-06-26 10:47:52', '2013-06-26 11:10:51')
- 値を直接追加し
generate_series()
て、コードを簡素化します。
- (秒数) を抽出し、それを(30 分
epoc
の秒数) で割ることにより、(四捨五入された) 正確な時間単位数を取得します。1800
- カウントに上限境界を含めて発生する off-by-1 エラーを修正しました。