Proponuję wygenerować wszystkie zakresy godzin pracy między created_at
i current_timestamp i ich sumowanie. Chociaż jest to dalekie od optymalnego rozwiązania pod względem wydajności, myślę, że jest to najprostsze podejście. Używam znacznika czasu z zakresem stref czasowych tstzrange
ze skrzyżowaniem operator (*)
.
SELECT id,
created_at,
SUM(upper(business_range) - lower(business_range) ) business_hours
FROM (
SELECT id,
created_at,
tstzrange(date_in_range + '09:00'::time with time zone, date_in_range + '17:00'::time with time zone)
* tstzrange(created_at, current_timestamp) as business_range
FROM (
SELECT id,
created_at,
created_at::date + generate_series(0, current_timestamp::date - created_at::date) as date_in_range
FROM times
) dates_in_range
WHERE date_part('dow', date_in_range) in (1,2,3,4,5)
) business_hour_ranges
GROUP BY
id,
created_at
Zobacz konfigurację i przykład w db<>fiddle
Przestroga
Chociaż implementacja została wykonana tak, aby była łatwa do zrozumienia i debugowania, może to skutkować słabą wydajnością - zwłaszcza jeśli jest używana z bardzo starymi datami created_at. Jeśli tak jest w twoim systemie, może lepiej będzie napisać funkcję, która sprawdza dzień tygodnia w utworze i current_date, znajduje liczbę dni między nimi i określa godziny pracy.