Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1376402
  • 博文数量: 205
  • 博客积分: 6732
  • 博客等级: 准将
  • 技术积分: 2835
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-04 17:59
文章分类

全部博文(205)

文章存档

2016年(1)

2015年(10)

2014年(1)

2013年(39)

2012年(23)

2011年(27)

2010年(21)

2009年(55)

2008年(28)

我的朋友

分类: Oracle

2011-04-14 18:02:42

 

create or replace package PG_PPM_COMMON_UTIL is
  type commCur is ref cursor; -- 定义公用游标


  -- Author : kangyong

  -- Created : 2011-4-8

  -- Purpose : 公共操作组件


  -- 取某个时间最近的一个工作日

  FUNCTION getLateWorkday(DESC_DATE IN DATE) RETURN date;
  
  
  -- 判断某个时间是否是工作日

  FUNCTION isWorkday(DESC_DATE IN DATE) RETURN number;
  
  -- 查询两个时间段内的工作日(节假日除外,节假日表:prod_public_holiday)

  -- 精确到小数点后1位

  FUNCTION calcWorkdays(I_START_DATE IN DATE, I_END_DATE IN DATE) RETURN number;
  
end PG_PPM_COMMON_UTIL;
/
create or replace package body PG_PPM_COMMON_UTIL is

  -- Author : kangyong

  -- Created : 2011-4-8

  -- Purpose : 公共操作组件


  -- 取某个时间最近的一个工作日

  FUNCTION getLateWorkday(DESC_DATE IN DATE) RETURN date IS
    num number(3);
    temp_date date;
  begin

    temp_date := DESC_DATE;
    loop
      select count(1)
        into num
        from (select trunc(temp_date) dayList from dual) A
       where not exists (select 1
                from prod_public_holiday b
               where b.ph_date = A.dayList)
         and to_char(dayList, 'D') not in (1, 7);
      --dbms_output.put_line(num);

      exit when(num > 0);
      select (temp_date + 1) into temp_date from dual;
    end loop;
    return temp_date;
  end;

  -- 判断某个时间是否是工作日

  FUNCTION isWorkday(DESC_DATE IN DATE) RETURN number Is
    num number(3);
    temp_date date;
  begin

    temp_date := DESC_DATE;
    select count(1)
      into num
      from (select trunc(temp_date) dayList from dual) A
     where not exists (select 1
              from prod_public_holiday b
             where b.ph_date = A.dayList)
       and to_char(dayList, 'D') not in (1, 7);
      --dbms_output.put_line(num);

    return num;
  end;

  -- 查询两个时间段内的工作日(节假日除外,节假日表:prod_public_holiday)

  -- 精确到小数点后1位

  FUNCTION calcWorkdays(I_START_DATE IN DATE, I_END_DATE IN DATE)
           RETURN number IS
     NO_OF_DAYS number;
     START_DATE date;
     END_DATE date;
     hour number := 0;
     mi number := 0;
     mis number := 0;
     days number(12,1) := 0.0;
     m_days number := 0;
     isworkday_flag number := -1;
  BEGIN
    if I_START_DATE is not null and I_END_DATE is not null then
      
      START_DATE := getLateWorkday(I_START_DATE);
      END_DATE := getLateWorkday(I_END_DATE);
      
      isworkday_flag := isWorkday(I_END_DATE);
      
      if isworkday_flag = 0 THEN
        m_days := m_days + 1;
      end if;
      
      IF START_DATE < END_DATE THEN
        
        if(START_DATE = I_START_DATE) then
           m_days := m_days + 1;
           select (24-to_number(to_char(START_DATE,'HH24'))) into hour from dual;
           select (60-to_number(to_char(START_DATE,'MI'))) into mi from dual;
           mis := mis + (hour * 60) - mi;
        end if;
        
        if(END_DATE = I_END_DATE) then
           m_days := m_days + 1;
           select to_number(to_char(END_DATE,'HH24')) into hour from dual;
           select to_number(to_char(END_DATE,'MI')) into mi from dual;
           mis := mis + (hour * 60) + mi;
        end if;
        
        SELECT count(1) days
          INTO NO_OF_DAYS
          FROM (SELECT DISTINCT trunc(START_DATE) + level - 1 dayList
                  FROM dual
                connect BY trunc(START_DATE) + level - 1 < = trunc(END_DATE)) A
         where not exists (select 1
                  from prod_public_holiday b
                 where b.ph_date = A.dayList)
           and to_char(dayList, 'D') not in (1, 7);
           
        --大于半个小时,按1小时算 round(mis/60)

        days := ( (NO_OF_DAYS - m_days) * 24 + round(mis/60) ) / 24;
        
      ELSE
      
        if(END_DATE = I_END_DATE) then
           m_days := m_days + 1;
           select (24-to_number(to_char(END_DATE,'HH24'))) into hour from dual;
           select (60-to_number(to_char(END_DATE,'MI'))) into mi from dual;
           mis := mis + (hour * 60) - mi;
        end if;
        
        if(START_DATE = I_START_DATE) then
           m_days := m_days + 1;
           select to_number(to_char(START_DATE,'HH24')) into hour from dual;
           select to_number(to_char(START_DATE,'MI')) into mi from dual;
           mis := mis + (hour * 60) + mi;
        end if;
              
        SELECT count(1) days
          INTO NO_OF_DAYS
          FROM (SELECT DISTINCT trunc(END_DATE) + level - 1 dayList
                  FROM dual
                connect BY trunc(END_DATE) + level - 1 < = trunc(START_DATE)) A
         where not exists (select 1
                  from prod_public_holiday b
                 where b.ph_date = A.dayList)
           and to_char(dayList, 'D') not in (1, 7);
           
        --大于半个小时,按1小时算 round(mis/60)

        days := 0 - ( ( (NO_OF_DAYS - m_days) * 24 + round(mis/60) ) / 24 );
      END IF;
     else
       --开始时间或结束时间有为空的

       dbms_output.PUT_LINE('I_START_DATE:' || I_START_DATE || 'I_END_DATE:' || I_END_DATE ||'开始时间或结束时间有为空的');
       RAISE_APPLICATION_ERROR(-20001, '开始时间或结束时间有为空的');
     end if;
    Return days;
  END;

end PG_PPM_COMMON_UTIL;
/


阅读(1386) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~