PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Décalage horaire dans les heures ouvrables

Je suggérerais de générer toutes les plages d'heures d'ouverture entre created_at et current_timestamp et en les additionnant. Bien qu'il soit loin d'être une solution optimale en termes de performances, je pense que c'est l'approche la plus simple. J'utilise l'horodatage avec la plage de fuseau horaire /docs/current/rangetypes.html#RANGETYPES-BUILTIN">tstzrange avec intersection opérateur (*) .

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

Voir la configuration et l'exemple dans db<>fiddle

Mise en garde

Bien que l'implémentation ait été conçue pour être facile à comprendre et à déboguer, elle peut entraîner des performances médiocres, en particulier si elle est utilisée avec de très anciennes dates created_at. Si tel est le cas dans votre système, vous feriez peut-être mieux d'écrire une fonction qui vérifie le jour de la semaine de created_at et current_date, trouve le nombre de jours entre eux et détermine les heures de travail.