How to add number of business days to given date

后端 未结 3 1857
花落未央
花落未央 2020-12-19 21:26

I\'m looking for a function which adds number of business days to given date.

Holidays table

create table pyha (pyha date primary key) ;
insert into          


        
3条回答
  •  再見小時候
    2020-12-19 22:08

    Here's a solution if you don't want to rely on generate_series. It's a fairly straight forward algorithm that allows you to specify your own business day definition via an array. The default business days (mo-fr) would be defined like this array[0,1,1,1,1,1,0]. Since it doesn't use generate_series it presumably is much faster especially for larger intervals.

    It doesn't consider the holiday table case, but will hopefully be a helpful pointer nonetheless.

    create or replace function add_business_days(start timestamp with time zone, business_days int[], add_days int)
      returns timestamp with time zone as $$
      declare
        days_left int := add_days;
        num_bds int := (select sum(x.val) from ( select unnest(business_days) val ) as x);
        add_real_days int := 0;
        start_dow int := extract(dow from start);
      begin
        -- if all weekdays are false just ignore the logic below
        if num_bds = 0 then
          return start + make_interval(days := add_days);
        end if;
    
        -- if the start day is no business day, go forward until we hit one
        while business_days[((start_dow + add_real_days) % 7) + 1] = 0 loop
          add_real_days := add_real_days + 1;
        end loop;
    
        -- jump to the final week
        add_real_days := add_real_days + (days_left / num_bds)::int * 7;
        days_left := days_left % num_bds;
    
        -- go ahead with the remaining days until we hit a business day
        while days_left > 0 or business_days[((start_dow + add_real_days) % 7) + 1] = 0 loop
          add_real_days := add_real_days + 1;
          days_left := days_left - business_days[((start_dow + add_real_days) % 7) + 1];
        end loop;
        return start + make_interval(days := add_real_days);
      end;
    $$
    language plpgsql immutable;
    
    

    You can use the function like this:

    select add_business_days(now(), array[0,1,1,1,1,0], 4);
    

提交回复
热议问题