Design an algorithm to compute working hours between two timestamps, considering that weekends are not working days and weekdays are counted from 8 am to 3 pm.
Define working hours as weekdays from 8 am to 3 pm:
WITH WorkingHours AS ( SELECT '08:00'::time AS start_time, '15:00'::time AS end_time )
Create a series of intervals for each day within the given date range:
SELECT t_id, generate_series(date_trunc('day', t_start), date_trunc('day', t_end), '1 day') AS day FROM t
Interpolate working hours for each day and compute fractional hours using the range type tsrange:
SELECT t_id, SUM(CASE WHEN EXTRACT(ISODOW FROM day) < 6 THEN COALESCE( f_worktime(day::timestamp + WorkingHours.start_time, day::timestamp + WorkingHours.end_time), '0' ) ELSE '0' END) AS work_time FROM WorkingHours CROSS JOIN ( SELECT t_id, day FROM temp ) AS temp GROUP BY 1
Define a function f_worktime to calculate fractional hours:
CREATE FUNCTION f_worktime(_start timestamp, _end timestamp) RETURNS interval LANGUAGE sql AS $func$ SELECT COALESCE(upper(tsrange(_start::timestamp, _end::timestamp)) - lower(tsrange(_start::timestamp, _end::timestamp)), '0')::interval; $func$ IMMUTABLE;
WITH t AS ( SELECT 0 AS t_id, '2023-05-01 09:00'::timestamp AS t_start, '2023-05-01 11:30'::timestamp AS t_end UNION ALL SELECT 1, '2023-05-02 10:00'::timestamp, '2023-05-02 18:00'::timestamp UNION ALL SELECT 2, '2023-05-03 09:15'::timestamp, '2023-05-04 10:45'::timestamp ) SELECT t.t_id, extract(hour from work_time) AS working_hours FROM t CROSS JOIN ( SELECT t_id, SUM(CASE WHEN EXTRACT(ISODOW FROM day) < 6 THEN f_worktime(day::timestamp + WorkingHours.start_time, day::timestamp + WorkingHours.end_time) ELSE '0' END) AS work_time FROM WorkingHours CROSS JOIN ( SELECT t_id, day FROM ( SELECT t_id, generate_series(date_trunc('day', t_start), date_trunc('day', t_end), '1 day') AS day FROM t ) AS temp ) AS temp GROUP BY 1 ) AS temp;
Output:
| t_id | working_hours | |------|---------------| | 0 | 3 | | 1 | 8 | | 2 | 3 |
The above is the detailed content of How to Calculate Working Hours Between Two Dates in PostgreSQL, Excluding Weekends?. For more information, please follow other related articles on the PHP Chinese website!