PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Differenza di fuso orario all'interno dell'orario lavorativo

Suggerirei di generare tutti gli intervalli di orari lavorativi tra created_at e current_timestamp e sommandoli. Sebbene sia tutt'altro che una soluzione ottimale in termini di prestazioni, penso che sia l'approccio più diretto. Uso timestamp con intervallo di fuso orario tstzrange con intersezione operatore (*) .

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

Vedi la configurazione e l'esempio in db<>fiddle

Avvertimento

Sebbene l'implementazione sia stata realizzata per essere facile da capire e da eseguire il debug, può comportare prestazioni scadenti, specialmente se utilizzata con date create_at molto vecchie. Se questo può essere il caso nel tuo sistema, potresti fare meglio a scrivere una funzione che controlla il giorno della settimana della data_at e quella_corrente, trova il numero di giorni tra di loro e determina l'orario di lavoro.