最近项目中有一个自动扣款的需求,需要在商品出售之后 7 个工作日之后进行自动扣款,由此封装了一个存储过程以便于调用。

注意:本示例使用oracle。

一、创建一张GGHOLIDAY表并insert部分数据

①表中holiday字段长度为31,holiday字段:W-正常周末  H-全天假期  D-半天假期 X-这个月不存在这天 .-正常工作日'。

-- Create table
create table GGHOLIDAY
(id          VARCHAR2(32) not null,year        VARCHAR2(12),month       VARCHAR2(12),holiday     VARCHAR2(31),creatorcode VARCHAR2(10),createtime  DATE,updatercode VARCHAR2(10),updatetime  DATE,validdate   DATE,invaliddate DATE,validind    VARCHAR2(1) not null,remark      VARCHAR2(4000)
)
tablespace USERSpctfree 10initrans 1maxtrans 255storage(initial 64Knext 1Mminextents 1maxextents unlimited);
-- Add comments to the table
comment on table GGHOLIDAYis '节假日';
-- Add comments to the columns
comment on column GGHOLIDAY.idis 'id';
comment on column GGHOLIDAY.yearis '年份';
comment on column GGHOLIDAY.monthis '月份';
comment on column GGHOLIDAY.holidayis '节假日标志,31位代表31天 格式: W-正常周末  H-全天假期  D-半天假期 X-这个月不存在这天 .-正常工作日';
comment on column GGHOLIDAY.creatorcodeis '创建人';
comment on column GGHOLIDAY.createtimeis '创建时间';
comment on column GGHOLIDAY.updatercodeis '最后修改人';
comment on column GGHOLIDAY.updatetimeis '最后修改时间';
comment on column GGHOLIDAY.validdateis '生效日期';
comment on column GGHOLIDAY.invaliddateis '失效日期';
comment on column GGHOLIDAY.validindis '有效标志含义:1-有效;0-无效';
comment on column GGHOLIDAY.remarkis '备注';
-- Create/Recreate primary, unique and foreign key constraints
alter table GGHOLIDAYadd constraint PK_GGHOLIDAY primary key (ID)using index tablespace USERSpctfree 10initrans 2maxtrans 255storage(initial 512Knext 512Kminextents 1maxextents unlimited);

②在GGHOLIDAY表中添加2019年8月、9月、10月、11月、12月的节假日信息。若需更多,自行配置。

insert into ggholiday (ID, YEAR, MONTH, HOLIDAY, CREATORCODE, CREATETIME, UPDATERCODE, UPDATETIME, VALIDDATE, INVALIDDATE, VALIDIND, REMARK)
values ('4028d0816980aba8016980c355ef0011', '2019', '08', '..WW.....WW.....WW.....WW.....W', '100000001', to_date('15-03-2019 17:51:00', 'dd-mm-yyyy hh24:mi:ss'), '100000001', to_date('15-03-2019 17:51:00', 'dd-mm-yyyy hh24:mi:ss'), null, null, '1', null);insert into ggholiday (ID, YEAR, MONTH, HOLIDAY, CREATORCODE, CREATETIME, UPDATERCODE, UPDATETIME, VALIDDATE, INVALIDDATE, VALIDIND, REMARK)
values ('4028d0816980aba8016980c355ef0010', '2019', '09', 'W.....WW....HHH.....WW.....W..X', '100000001', to_date('15-03-2019 17:51:00', 'dd-mm-yyyy hh24:mi:ss'), '100000001', to_date('15-03-2019 17:51:00', 'dd-mm-yyyy hh24:mi:ss'), null, null, '1', null);insert into ggholiday (ID, YEAR, MONTH, HOLIDAY, CREATORCODE, CREATETIME, UPDATERCODE, UPDATETIME, VALIDDATE, INVALIDDATE, VALIDIND, REMARK)
values ('4028d0816980aba8016980c355ef0001', '2019', '10', 'HHHHHHH.....W.....WW.....WW....', '100000001', to_date('15-03-2019 17:51:00', 'dd-mm-yyyy hh24:mi:ss'), '100000001', to_date('15-03-2019 17:51:00', 'dd-mm-yyyy hh24:mi:ss'), null, null, '1', null);insert into ggholiday (ID, YEAR, MONTH, HOLIDAY, CREATORCODE, CREATETIME, UPDATERCODE, UPDATETIME, VALIDDATE, INVALIDDATE, VALIDIND, REMARK)
values ('4028d0816980aba8016980c355ef0012', '2019', '11', '.WW.....WW.....WW.....WW.....WX', '100000001', to_date('15-03-2019 17:51:00', 'dd-mm-yyyy hh24:mi:ss'), '100000001', to_date('15-03-2019 17:51:00', 'dd-mm-yyyy hh24:mi:ss'), null, null, '1', null);insert into ggholiday (ID, YEAR, MONTH, HOLIDAY, CREATORCODE, CREATETIME, UPDATERCODE, UPDATETIME, VALIDDATE, INVALIDDATE, VALIDIND, REMARK)
values ('4028d0816980aba8016980c355ef0013', '2019', '12', 'W.....WW.....WW.....WW.....WW..', '100000001', to_date('15-03-2019 17:51:00', 'dd-mm-yyyy hh24:mi:ss'), '100000001', to_date('15-03-2019 17:51:00', 'dd-mm-yyyy hh24:mi:ss'), null, null, '1', null);

二、编写存储过程计算节假日:

1、计算某个日期 N 个工作日之后的日期:

代码:

  -- 计算传入日期之后v_days个工作日之后的日期,不支持跨2个月的操作FUNCTION getWorkDate(v_nowDatestr VARCHAR2, v_days NUMBER) RETURN DATE ISv_returnDate DATE;v_nowDate DATE; --当前时间v_strNowMonthHOLIDAY VARCHAR2(31); -- 当月v_nowDate后的节假日及工作日标识字符串v_strNextMonthHOLIDAY VARCHAR2(31); -- 下月节假日及工作日字符串v_nextDays NUMBER; -- 下月需要计算的工作日v_nowDays NUMBER;  -- 当前是本月第几天v_nowMonthWorkDay NUMBER; -- 当月剩余工作日天数v_realyDays NUMBER DEFAULT 0; -- v_nowDate到v_days个工作日的实际天数v_workDaysFlag NUMBER DEFAULT 0;-- 循环时记录这是第几个工作日BEGINv_nowDate := to_date(v_nowDatestr,'yyyy-MM-dd');v_nowDays := to_number(to_char(v_nowdate,'dd'));-- 获取当月v_nowDate日期之后的节假日及工作日标识字符串SELECT replace(substr(T.HOLIDAY,v_nowDays+1,31-v_nowDays),'X','')INTO V_STRNOWMONTHHOLIDAYFROM GGHOLIDAY TWHERE T.YEAR = TO_CHAR(V_NOWDATE, 'yyyy')AND T.MONTH = TO_CHAR(V_NOWDATE, 'MM');SELECT nvl((LENGTHB(V_STRNOWMONTHHOLIDAY) -LENGTHB(REPLACE(V_STRNOWMONTHHOLIDAY, '.', ''))),0)INTO v_nowMonthWorkDayFROM DUAL;IF v_nowMonthWorkDay >= v_days THEN-- 如果当月v_nowDate日期之后的工作日还多于v_days天FOR i IN 1..length(v_strNowMonthHOLIDAY) LOOPIF substr(v_strNowMonthHOLIDAY,i,1)='.' THENv_workDaysFlag := v_workDaysFlag + 1;END IF;v_realyDays := v_realyDays + 1;IF v_workDaysFlag = v_days THENGOTO NEXT;END IF;END LOOP;<<NEXT>> NULL;ELSE-- 如果当月v_nowDate日期之后的工作日还少于或等于v_days天,就需要推迟到下个月v_nextDays := v_days-v_nowMonthWorkDay;--v_realyDays:= v_nextDays;-- 获取下月节假日及工作日标识字符串SELECT replace(T.HOLIDAY,'X','')INTO v_strNextMonthHOLIDAYFROM GGHOLIDAY TWHERE T.YEAR = TO_CHAR(add_months(v_nowDate,1), 'yyyy')AND T.MONTH = TO_CHAR(add_months(v_nowDate,1), 'MM');FOR i IN 1..length(v_strNextMonthHOLIDAY) LOOPIF substr(v_strNextMonthHOLIDAY,i,1)='.' THENv_workDaysFlag := v_workDaysFlag + 1;END IF;v_realyDays := v_realyDays + 1;IF v_workDaysFlag = v_nextDays THENGOTO NEXTSTR;END IF;END LOOP;<<NEXTSTR>> NULL;if v_strNowMonthHOLIDAY is null then v_realyDays := v_realyDays;elsev_realyDays := v_realyDays + length(v_strNowMonthHOLIDAY);end if;END IF;v_returnDate := v_nowDate + v_realyDays;RETURN v_returnDate;END getWorkDate;

2、计算某个日期之前 N 个工作日的日期:

  -- 获取 V_NOWDATEstr 日期前 V_DAYS 个工作日的日期PROCEDURE GETBEFOREWORKDATE(V_NOWDATEstr  IN VARCHAR2,V_DAYS        IN NUMBER,V_MESSAGECODE OUT VARCHAR2,V_RETURNDATE  OUT DATE) ISv_nowDate DATE;v_strNowMonthHOLIDAY VARCHAR2(31); -- 当月v_nowDate前的节假日及工作日标识字符串v_strLastMonthHOLIDAY VARCHAR2(31); -- 上月节假日及工作日字符串v_lastDays NUMBER; -- 上月需要计算的工作日v_nowDays NUMBER;  -- 当前是本月第几天v_nowMonthWorkDay NUMBER; -- 当月剩余工作日天数v_realyDays NUMBER DEFAULT 0; -- v_nowDate到v_days个工作日的实际天数v_workDaysFlag NUMBER DEFAULT 0;-- 循环时记录这是第几个工作日BEGINv_nowDate := to_date(v_nowDatestr,'yyyy-MM-dd');v_nowDays := to_number(to_char(v_nowdate,'dd'))-1;-- 获取当月v_nowDate日期之前的节假日及工作日标识字符串SELECT replace(substr(T.HOLIDAY,0,v_nowDays),'X','')INTO V_STRNOWMONTHHOLIDAYFROM GGHOLIDAY TWHERE T.YEAR = TO_CHAR(V_NOWDATE, 'yyyy')AND T.MONTH = TO_CHAR(V_NOWDATE, 'MM');SELECT (LENGTHB(V_STRNOWMONTHHOLIDAY) -LENGTHB(REPLACE(V_STRNOWMONTHHOLIDAY, '.', '')))INTO v_nowMonthWorkDayFROM DUAL;IF v_nowMonthWorkDay >= v_days THEN-- 如果当月v_nowDate日期之后的工作日还多于v_days天FOR i IN 1..length(v_strNowMonthHOLIDAY) LOOPIF substr(v_strNowMonthHOLIDAY,length(v_strNowMonthHOLIDAY)-i+1,1)='.' THENv_workDaysFlag := v_workDaysFlag + 1;END IF;v_realyDays := v_realyDays + 1;IF v_workDaysFlag = v_days THENGOTO NEXT;END IF;END LOOP;<<NEXT>> NULL;ELSE-- 如果当月v_nowDate日期之后的工作日还少于或等于v_days天,就需要推迟到下个月v_lastDays := v_days-v_nowMonthWorkDay;-- 获取上月节假日及工作日标识字符串SELECT replace(T.HOLIDAY,'X','')INTO v_strLastMonthHOLIDAYFROM GGHOLIDAY TWHERE T.YEAR = TO_CHAR(v_nowDate - interval '1' month, 'yyyy')AND T.MONTH = TO_CHAR(v_nowDate - interval '1' month, 'MM');FOR i IN 1..length(v_strLastMonthHOLIDAY) LOOPIF substr(v_strLastMonthHOLIDAY,length(v_strLastMonthHOLIDAY)-i+1,1)='.' THENv_workDaysFlag := v_workDaysFlag + 1;END IF;v_realyDays := v_realyDays + 1;IF v_workDaysFlag = v_lastDays THENGOTO NEXTSTR;END IF;END LOOP;<<NEXTSTR>> NULL;v_realyDays := v_realyDays + length(v_strNowMonthHOLIDAY);END IF;v_returnDate := v_nowDate - v_realyDays;EXCEPTIONWHEN OTHERS THENV_MESSAGECODE := '000';END GETBEFOREWORKDATE;

三、进行测试

1、计算某个日期 N 个工作日之后的日期:

SELECT ggHolidayPackage.getWorkDate('2019-09-21',3) FROM dual;输出:2019/9/25

2、计算某个日期之前 N 个工作日的日期:

DECLAREV_MESSAGECODE  VARCHAR2(10);V_RETURNDATE   DATE;
BEGINggHolidayPackage.GETBEFOREWORKDATE('2019-09-21',3,V_MESSAGECODE,V_RETURNDATE);dbms_output.put_line('V_MESSAGECODE='||V_MESSAGECODE);dbms_output.put_line('V_RETURNDATE='||to_char(V_RETURNDATE,'yyyy-MM-dd'));
END;输出:
V_MESSAGECODE=
V_RETURNDATE=2019-09-18

Oracle计算当前日期在N个工作日之后的日期相关推荐

  1. oracle 计算当前日期是今年的第几周的计算方法

    一.oracle 计算当前日期是今年的第几周的计算方法(以周六为每周第一天为例) 完整代码: select * from ( SELECT sysdate , LEVEL 周次,(TRUNC(sysd ...

  2. java计算当前日期后N个工作日的日期

    如图,合同中有很多这种日期计算,故封装一通用工具类,记录于此.需求如下: WorkDayUtils如下: package com.sqds.utils;import org.apache.common ...

  3. oracle获取当前日期的前一天,判断两个日期是否相等

    select TRUNC(SYSDATE ) from dual;   //获取当前日期 select TRUNC(SYSDATE - 1) from dual;   //获取前一天的日期 selec ...

  4. oracle查找当前日期的三个工作日前那天日期,采用函数方式

    业务场景: 取A表中的字段"日期1"的三个工作日前的那一天.有一张现成的表里面是有每年的节假日和周末的期间. 具体表如下: 查询表ZS_YJSF 时,加条件:YZRQ(应征日期)字 ...

  5. oracle计算期间工作日的简单查询办法

    oracle计算期间工作日的简单查询办法 SELECT sum(天数) 天数 FROM ( SELECT rownum 行,to_char(to_date('2019-12-31','yyyy-mm- ...

  6. Oracle计算某日期段内排除周六日之后的天数(请假,工作日,日期型)

    因为本人不是主要从事Oracle等大数据操作方向,所以对于SQL语句了解并不专业,本文主要用于记录自己的使用心得,以及为广大网友提供思路,如果不喜欢我的解析和讲解可以直接跳过,拿走你觉得有用的SQL. ...

  7. oracle计算两个日期间的工作日(根据表配置)

    首先新增表用于配置非工作日,工作日,具体配置在程序中处理 DROP TABLE "T_WEEKDAY"; CREATE TABLE "T_WEEKDAY" (& ...

  8. oracle的当前日期,Oracle 获取当前日期及日期格式

    http://blog.sina.com.cn/s/blog_6168ee920100l2ye.html Oracle 获取当前日期及日期格式 获取系统日期:  SYSDATE() 格式化日期:    ...

  9. Oracle计算时间差表达式

    --获取两时间的相差豪秒数  select ceil((To_date('2008-05-02 00:00:00' , 'yyyy-mm-dd hh24-mi-ss') - To_date('2008 ...

最新文章

  1. 如何让SELECT 查询结果额外增加自动递增序号
  2. 实时获取ccd图像_薄膜瑕疵在线检测系统0.1mm检测精度_实时在线检测
  3. 搜狗输入法错误推送地震信息,但其背后的真正价值值得思考
  4. linux的文件io操作(转)
  5. Linux 命令之 du -- 显示每个文件和目录的磁盘使用空间/所占用的磁盘空间大小/所使用的磁盘空间大小/查看文件和目录的大小
  6. 新媒体中的MCN机构是什么意思
  7. python do while语句_python控制语句执行流程(while)
  8. IAP升级功能编写初期的一些困惑与疑问---完毕功能后的总结
  9. Linux学习笔记(6)
  10. 获取对象属性名的方法 Object.keys() 与 Object.getOwnPropertyNames() 与 for循环
  11. 可方向导不一定连续的例子
  12. 天堂2单机版服务器时间修改,L2Jserver版本天堂2进游戏公告的修改
  13. scratch编程超好玩的解密游戏
  14. Source Insight 使用技巧整理
  15. sm框架 访问局域网mysql_ssm框架搭建之sm框架整合
  16. ui设计移动端字体适配_移动端界面设计之尺寸篇
  17. ubuntu 生成桌面快捷方式(有图)
  18. 软件设计师认证 -如何画数据流图
  19. 使用ping测试MTU值
  20. 官方资料:Oracle 10g DBA 学习手册(精心整理,申请加精)

热门文章

  1. 星露谷物语联机开服务器的人不在线,《星露谷物语》多人联机模式细节公布 竟可与NPC结婚!...
  2. 基于MDKA5D31-EK_T70开发板的QT示例-demo01:LEDTimer
  3. 淘宝京东1688以图搜图,按图搜索商品,API接口调用展示(拍立淘API)返回值说明
  4. word如何设置长宽高_word页面高度和宽度怎么设置
  5. xstream 反序列化漏洞研究与修复
  6. Win7旗舰版下安装Sql2008
  7. 外国人搞笑的诗歌比赛
  8. 深圳公司注册银行开户
  9. 做项目经理 考PMP含金量会高嘛?
  10. linux 反转符号用法,Linux 常见特殊符号