这是一个快速灵活的功能。您可以计算日期范围内的任何工作日。
CREATE OR REPLACE FUNCTION wfportal.cx_count_specific_weekdays( p_week_days   VARCHAR2 DEFAULT 'MON,TUE,WED,THU,FRI'
                                                              , p_start_date  DATE
                                                              , p_end_date    DATE)
RETURN NUMBER 
IS
 /***************************************************************************************************************
  *
  * FUNCTION DESCRIPTION:
  *
  *   This function calculates the total required week days in a date range.
  *
  * PARAMETERS:
  *
  *   p_week_days   VARCHAR2  The week days that need to be counted, comma seperated e.g. MON,TUE,WED,THU,FRU,SAT,SUN 
  *   p_start_date  DATE      The start date
  *   p_end_date    DATE      The end date
  *
  * CHANGE history
  *
  * No.  Date         Changed by       Change Description
  * ---- -----------  -------------    -------------------------------------------------------------------------
  *    0 07-May-2013  yourname         Created
  *
  ***************************************************************************************************************/
   v_date_end_first_date_range    DATE;
   v_date_start_last_date_range   DATE;
   v_total_days_in_the_weeks      NUMBER;
   v_total_days_first_date_range  NUMBER;
   v_total_days_last_date_range   NUMBER;
   v_output                       NUMBER;
   v_error_text                   CX_ERROR_CODES.ERROR_MESSAGE%TYPE;
   --Count the required days in a specific date ranges by using a list of all the weekdays in that range.
   CURSOR c_total_days ( v_start_date DATE
                       , v_end_date   DATE ) IS
     SELECT COUNT(*) total_days
     FROM ( SELECT ( v_start_date + level - 1) days
            FROM dual
            CONNECT BY LEVEL <= ( v_end_date - v_start_date ) + 1
           )
     WHERE INSTR( ',' || p_week_days || ',', ',' || TO_CHAR( days, 'DY', 'NLS_DATE_LANGUAGE=english') || ',', 1 ) > 0
   ;
   --Calculate the first and last date range by retrieving the first Sunday after the start date and the last Monday before the end date. 
   --Calculate the total amount of weeks in between and multiply that with the total required days.
   CURSOR c_calculate_new_dates ( v_start_date DATE
                                , v_end_date   DATE ) IS
     SELECT date_end_first_date_range
     ,      date_start_last_date_range
     ,      ( 
              (
                ( date_start_last_date_range - ( date_end_first_date_range + 1 ) )
              ) / 7 
            ) * total_required_days   total_days_in_the_weeks  --The total amount of required days 
     FROM ( SELECT v_start_date + DECODE( TO_CHAR( v_start_date, 'DY', 'NLS_DATE_LANGUAGE=english')
                                        , 'MON', 6
                                        , 'TUE', 5
                                        , 'WED', 4
                                        , 'THU', 3
                                        , 'FRI', 2
                                        , 'SAT', 1
                                        , 'SUN', 0
                                        , 0 )   date_end_first_date_range
            ,      v_end_date - DECODE( TO_CHAR( v_end_date, 'DY', 'NLS_DATE_LANGUAGE=english')
                                      , 'MON', 0
                                      , 'TUE', 1
                                      , 'WED', 2
                                      , 'THU', 3
                                      , 'FRI', 4
                                      , 'SAT', 5
                                      , 'SUN', 6
                                      , 0 )  date_start_last_date_range
            ,      REGEXP_COUNT( p_week_days, ',' ) + 1  total_required_days  --Count the commas + 1 to get the total required weekdays
            FROM dual 
     )
     ;
BEGIN
  --Verify that the start date is before the end date
  IF p_start_date < p_end_date THEN
    --Get the new calculated days.
    OPEN c_calculate_new_dates( p_start_date, p_end_date );
      FETCH c_calculate_new_dates INTO  v_date_end_first_date_range
                                      , v_date_start_last_date_range
                                      , v_total_days_in_the_weeks;
    CLOSE c_calculate_new_dates;
    --Calculate the days in the first date range
    OPEN c_total_days( p_start_date, v_date_end_first_date_range );
      FETCH c_total_days INTO v_total_days_first_date_range;
    CLOSE c_total_days;
    --Calculate the days in the last date range
    OPEN c_total_days( v_date_start_last_date_range, p_end_date );
      FETCH c_total_days INTO v_total_days_last_date_range;
    CLOSE c_total_days;
    --Sum the total required days
    v_output := v_total_days_first_date_range + v_total_days_last_date_range + v_total_days_in_the_weeks;
  ELSE
     v_output := 0;
  END IF;
  RETURN v_output;
  EXCEPTION
    WHEN OTHERS
    THEN
    RETURN NULL;
END cx_count_specific_weekdays;
/