Oracle获取指定周次的周几的日期

  /************************************************
  *功能描述:
  *    获取某一年的最大周次。
  *
  *算法描述:
  *    N/A
  *
  *修订记录:
  *    修改时间     编辑人       修改大致描述
  *    2017-03-29   何秋城       1.创建此函数
  *
  *入参出参描述:
  *    p_Year VARCHAR2   年份YYYY
  *
  *返回值描述:
  *    最大周次
  ************************************************/
  FUNCTION Get_Max_Year_Week(p_Year VARCHAR2) RETURN NUMBER IS
    x_Week NUMBER;
    l_Year VARCHAR2(4);
    Ex_Error_Year EXCEPTION;
  
  BEGIN
  
    DECLARE
    BEGIN
      SELECT To_Char(To_Date(p_Year, 'YYYY'), 'YYYY')
        INTO l_Year
        FROM Dual;
    EXCEPTION
      WHEN OTHERS THEN
        RAISE Ex_Error_Year;
    END;
  
    WITH Params AS
     (SELECT l_Year AS Nf FROM Dual)
    SELECT To_Char(To_Date(Pm.Nf || '-12-28', 'YYYY-MM-DD'), 'IW')
      INTO x_Week
      FROM Dual
      LEFT JOIN Params Pm
        ON 1 = 1;
  
    RETURN x_Week;
  
  EXCEPTION
    WHEN Ex_Error_Year THEN
      Dbms_Output.Put_Line('输入年份有误');
      RAISE Ex_Week_Notfound;
    WHEN OTHERS THEN
      RAISE Ex_Week_Notfound;
    
  END Get_Max_Year_Week;

  /************************************************
  *功能描述:
  *    由周次获取指定周次的指定周几的日期。
  *
  *算法描述:
  *    N/A
  *
  *修订记录:
  *    修改时间     编辑人       修改大致描述
  *    2017-03-29   何秋城       1.创建此函数
  *
  *入参出参描述:
  *    p_Week    VARCHAR2
  *    p_Number  NUMBER - 1:周一
  *                       2:周二
  *                       3:周三
  *                       4:周四
  *                       5:周五
  *                       6:周六
  *                       7:周日
  *
  *返回值描述:
  *    指定周次指定周几的日期
  ************************************************/
  FUNCTION Get_Date_Fn(p_Week VARCHAR2, p_Number NUMBER) RETURN VARCHAR2 IS
    x_Monday VARCHAR2(10);
    --l_Max_Week      NUMBER;
    l_Interval_Year NUMBER; --相隔多少年
    l_Interval_Week NUMBER := 0; --相隔多少周
    l_Interval_Day  NUMBER;
    Ex_Beyond_Week EXCEPTION;
    Ex_Below_Week EXCEPTION;
  
  BEGIN
  
    --输入周次小于当周最小周次
    IF Substr(p_Week, 5, 2) < '01' THEN
      RAISE Ex_Below_Week;
    END IF;
    --输入周次大于当年最大周次
    IF Get_Max_Year_Week(Substr(p_Week, 1, 4)) < Substr(p_Week, 5, 2) THEN
      RAISE Ex_Beyond_Week;
    END IF;
  
    CASE p_Number
      WHEN 1 THEN
        l_Interval_Day := 0;
      WHEN 2 THEN
        l_Interval_Day := 1;
      WHEN 3 THEN
        l_Interval_Day := 2;
      WHEN 4 THEN
        l_Interval_Day := 3;
      WHEN 5 THEN
        l_Interval_Day := 4;
      WHEN 6 THEN
        l_Interval_Day := 5;
      WHEN 7 THEN
        l_Interval_Day := 6;
    END CASE;
  
    --周次于当周比较
    IF p_Week >= To_Char(SYSDATE, 'IYYYIW') THEN
      --向后跨年(未来)
      IF Substr(p_Week, 1, 4) > To_Char(SYSDATE, 'YYYY') THEN
        l_Interval_Year := Substr(p_Week, 1, 4) - To_Char(SYSDATE, 'YYYY');
      
        FOR i IN 1 .. l_Interval_Year LOOP
          l_Interval_Week := l_Interval_Week +
                             Get_Max_Year_Week(Substr(p_Week, 1, 4) - i);
        END LOOP;
      
        SELECT To_Char(Trunc(SYSDATE +
                             (l_Interval_Week +
                             To_Number(Substr(p_Week, 5, 2)) -
                             To_Number(To_Char(SYSDATE, 'IW'))) * 7,
                             'IW') + l_Interval_Day,
                       'YYYY-MM-DD')
          INTO x_Monday
          FROM Dual;
      ELSE
        --同一年
        SELECT To_Char(Trunc(SYSDATE +
                             (To_Number(p_Week) -
                             To_Number(To_Char(SYSDATE, 'IYYYIW'))) * 7,
                             'IW') + l_Interval_Day,
                       'YYYY-MM-DD')
          INTO x_Monday
          FROM Dual;
      END IF;
    ELSE
      --向前跨年(过去)
      IF Substr(p_Week, 1, 4) < To_Char(SYSDATE, 'YYYY') THEN
        l_Interval_Year := To_Char(SYSDATE, 'YYYY') - Substr(p_Week, 1, 4);
      
        FOR i IN 1 .. l_Interval_Year LOOP
          l_Interval_Week := l_Interval_Week +
                             Get_Max_Year_Week(To_Char(SYSDATE, 'YYYY') - i);
        END LOOP;
      
        SELECT To_Char(Trunc(SYSDATE - (l_Interval_Week +
                             To_Number(To_Char(SYSDATE, 'IW')) -
                             To_Number(Substr(p_Week, 5, 2))) * 7,
                             'IW') + l_Interval_Day,
                       'YYYY-MM-DD')
          INTO x_Monday
          FROM Dual;
      ELSE
        --同一年
        SELECT To_Char(Trunc(SYSDATE - (To_Number(To_Char(SYSDATE, 'IYYYIW')) -
                             To_Number(p_Week)) * 7,
                             'IW') + l_Interval_Day,
                       'YYYY-MM-DD')
          INTO x_Monday
          FROM Dual;
      END IF;
    END IF;
    RETURN x_Monday;
  
  EXCEPTION
    WHEN Ex_Below_Week THEN
      Dbms_Output.Put_Line('输出周次小于指定年份的最大周次');
      RETURN 'E';
    WHEN Ex_Week_Notfound THEN
      Dbms_Output.Put_Line('未找到指定年份的最大周次');
      RETURN 'E';
    WHEN Ex_Beyond_Week THEN
      Dbms_Output.Put_Line('输出周次大于指定年份的最大周次');
      RETURN 'E';
    WHEN OTHERS THEN
      Dbms_Output.Put_Line('未找到指定周次的日期');
      RETURN 'E';
    
  END Get_Date_Fn;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值