Search code examples
postgresqltime-seriesplpgsql

Counting number of weekdays between two dates


I am trying to get the number of weekdays between two dates in plpgsql. The following is my code:

CREATE FUNCTION weekdays(DATE, DATE) RETURNS INTEGER AS
$$
DECLARE
    d date := $1;
    weekdays integer := 0
BEGIN

LOOP
    IF select extract(dow from date d) != 6 or select extract(dow from date d) != 0
      weekdays := weekdays +1
    END IF
    d := d + 1;
    EXIT WHEN d > $2;
END LOOP;
RETURN weekdays;
END;
$$
LANGUAGE 'plpgsql' IMMUTABLE;

However, I keep getting the following error:

Unterminated dollar quote started at position 56 in SQL
CREATE FUNCTION weekdays(DATE, DATE) RETURNS INTEGER AS $$ DECLARE d date := $1.
Expected terminating $$

Solution

  • The error is due to a missing ; after weekdays integer := 0;. Plus several more errors of this kind. This would work:

    CREATE  OR REPLACE FUNCTION weekdays(date, date)
      RETURNS integer AS
    $func$
    DECLARE
       d        date := $1;
       weekdays int  := 0;
    BEGIN
       LOOP
          IF extract(isodow from d) < 6 THEN  -- simpler
             weekdays := weekdays + 1;
          END IF;
          d := d + 1;
          EXIT WHEN d > $2;
       END LOOP;
       RETURN weekdays;
    END
    $func$  LANGUAGE plpgsql IMMUTABLE;
    

    But I suggest this simpler and faster SQL function instead:

    CREATE OR REPLACE FUNCTION weekdays_sql(date, date)
      RETURNS integer AS
    $func$
    SELECT count(*)::int
    FROM   generate_series($1, $2, interval '1d') d
    WHERE  extract(isodow FROM d) < 6;
    $func$  LANGUAGE sql IMMUTABLE;
    

    Further performance improvement for big ranges possible. Related: