Home > Database > Mysql Tutorial > How to Calculate Working Hours Between Two Dates in PostgreSQL, Excluding Weekends?

How to Calculate Working Hours Between Two Dates in PostgreSQL, Excluding Weekends?

Mary-Kate Olsen
Release: 2024-12-31 20:14:14
Original
879 people have browsed it

How to Calculate Working Hours Between Two Dates in PostgreSQL, Excluding Weekends?

Calculate Working Hours Between 2 Dates in PostgreSQL

Problem Statement

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.

Solution

Step 1: Identify Working Hours per Day

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
)
Copy after login

Step 2: Calculate Intervals for Each Day

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
Copy after login

Step 3: Compute Working Hours for Each Interval

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
Copy after login

Step 4: Function to Calculate Fractional Hours

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;
Copy after login

Example

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;
Copy after login

Output:

| t_id | working_hours |
|------|---------------|
|    0 |             3 |
|    1 |             8 |
|    2 |             3 |
Copy after login

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!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template