Ich würde vorschlagen, alle Bereiche der Geschäftszeiten zwischen created_at
zu generieren und current_timestamp und deren Summierung. Obwohl es in Bezug auf die Leistung alles andere als eine optimale Lösung ist, denke ich, dass es der einfachste Ansatz ist. Ich verwende Zeitstempel mit Zeitzonenbereich tstzrange
mit Schnittpunkt 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
Siehe Setup und Beispiel in db<>fiddle
Warnung
Obwohl die Implementierung so gestaltet wurde, dass sie leicht verständlich und debuggbar ist, kann sie zu einer schlechten Leistung führen – insbesondere, wenn sie mit sehr alten „created_at“-Daten verwendet wird. Wenn dies in Ihrem System der Fall sein kann, sollten Sie besser eine Funktion schreiben, die den Wochentag von "created_at" und "current_date" überprüft, die Anzahl der Tage zwischen ihnen ermittelt und die Arbeitszeit bestimmt.