1 函数一: 2 3 CREATE OR REPLACE FUNCTION dayadd(p_Component varchar2, 4 p_Number number, 5 p_Date date) RETURN DATE IS 6 /****************************************************************/ 7 /* 该函数为日期计算函数主要是计算〕 */ 8 /* 从当前日期开始经过多少日、季、月、年等后的日期。 */ 9 /* 入参说明:p_Component 时间元件,如年月日季度等等 */ 10 /* p_Number 加数, 注意:应该为整数(可正可负) */ 11 /* p_Date 基准时间 */ 12 /* 注意:其他日期元件,如世纪等等,暂时未考虑 */ 13 /***************************************************************/ 14 15 v_Component varchar2(10); 16 v_MiddleNumber number; 17 v_ReturnValue_Str varchar2(20); --字符串日期格式 18 v_ReturnValue date; --返回日期 19 20 BEGIN 21 v_Component := upper(ltrim(rtrim(p_Component))); 22 if v_Component in ('Y', 'YY', 'YEAR', 'YYYY') then 23 --年情况 24 v_ReturnValue := add_months(p_Date, p_Number * 12); 25 elsif v_Component in ('M', 'MM', 'MONTH', 'MON') then 26 --月情况 27 v_ReturnValue := add_months(p_Date, p_Number); 28 elsif v_Component in ('D', 'DD', 'DAY') then 29 --日情况 30 v_ReturnValue := p_Date + p_Number; 31 elsif v_Component in ('H', 'HH', 'HOUR') then 32 --时情况 33 v_ReturnValue := p_Date + p_Number / 24; 34 elsif v_Component in ('MI', 'MINUTE') then 35 --分情况 36 v_ReturnValue := p_Date + p_Number / 1440; 37 elsif v_Component in ('S', 'SS', 'SECOND') then 38 --秒情况 39 v_ReturnValue := p_Date + p_Number / 86400; 40 elsif v_Component in ('Q', 'QQ', 'QUARTER') then 41 --季度情况 42 v_ReturnValue := p_Date + p_Number * 3; 43 elsif v_Component in ('W', 'WW', 'WK', 'WEEK') then 44 --周情况 45 v_ReturnValue := p_Date + p_Number * 7; 46 else 47 v_ReturnValue := to_date('1-1-1', 'yyyy-mm-dd'); 48 end if; 49 RETURN v_ReturnValue; 50 EXCEPTION 51 WHEN OTHERS THEN 52 RETURN to_date('1-1-1', 'yyyy-mm-dd'); --例外处理 53 54 END; 55 56 57 58 函数二: 59 60 61 62 create or replace function datediff(p_Component varchar2, 63 p_Subtranhend date, 64 p_Minuend date) RETURN NUMBER IS 65 /*************************************************************************/ 66 /* 功 能:返回两个日期之间的天、周、月、年等数量。 */ 67 /* 入参说明: p_Component 时间元件,如年月日季度等等 */ 68 /* p_Subtrahend 减数时间 */ 69 /* p_Minuend 被减数时间 */ 70 /*************************************************************************/ 71 72 v_ReturnValue number; -- 结果数值 73 v_Component varchar2(10); --日期组件中间转换形式,截取空格并且转为大写 74 v_YearNum1 number; --减数年份数 75 v_YearNum2 number; --被减数年份数 76 v_MonthNum1 number; --减数月份数 77 v_MonthNum2 number; --被减数月份数 78 v_HourNum1 number; --减数时数 79 v_HourNum2 number; --被减数时数 80 v_MinuteNum1 number; --减数分钟数 81 v_MinuteNum2 number; --被减数分钟数 82 v_SecondNum1 number; --减数秒钟数 83 v_SecondNum2 number; --减数秒钟数 84 v_QuarterValue1 number; --减数季度数 85 v_QuarterValue2 number; --被减数季度数 86 v_WeekNum1 number; --减数与标准时间周差 87 v_WeekNum2 number; --被减数与标准时间周差 88 BEGIN 89 v_Component := upper(ltrim(rtrim(p_Component))); 90 if v_Component in ('Y', 'YY', 'YEAR', 'YYYY') then 91 --年情况 92 v_YearNum1 := to_number(to_char(p_Subtranhend, 'YYYY')); 93 v_YearNum2 := to_number(to_char(p_Minuend, 'YYYY')); 94 v_ReturnValue := v_YearNum2 - v_YearNum1; 95 elsif v_Component in ('M', 'MM', 'MONTH', 'MON') then 96 --月情况 97 --请注意,这个部分与Oracle内置日期函数MONTH_BETWEEN()不同,忽略了日因素 98 --而后者的两个日期如都是所在月的最后一天,才返回整数,否则,返回分数 99 --而且这个分数是以31天作为一个月进行计算的结果 100 v_YearNum1 := to_number(to_char(p_Subtranhend, 'YYYY')); 101 v_YearNum2 := to_number(to_char(p_Minuend, 'YYYY')); 102 v_MonthNum1 := to_number(to_char(p_Subtranhend, 'MM')); 103 v_MonthNum2 := to_number(to_char(p_Minuend, 'MM')); 104 v_ReturnValue := (v_YearNum2 - v_YearNum1) * 12 + 105 (v_MonthNum2 - v_MonthNum1); 106 elsif v_Component in ('D', 'DD', 'DAY') then 107 --日情况 108 --这里与两个日期直接相减的oracle日期算术也不同,只返回整数天数; 109 --而后者可以返回一天的几分之几(以小数形式表达) 110 v_ReturnValue := to_date(to_char(p_Minuend, 'yyyy-mm-dd'), 'YYYY-MM-DD') - 111 to_date(to_char(p_Subtranhend, 'yyyy-mm-dd'), 112 'YYYY-MM-DD'); 113 elsif v_Component in ('H', 'HH', 'HOUR') then 114 --时情况 115 --第一步:求出天数 116 v_ReturnValue := (to_date(to_char(p_Minuend, 'yyyy-mm-dd'), 117 'YYYY-MM-DD') - 118 to_date(to_char(p_Subtranhend, 'yyyy-mm-dd'), 119 'YYYY-MM-DD')); 120 --第二步:求出时数 121 v_HourNum1 := to_number(to_char(p_Subtranhend, 'HH24')); 122 v_HourNum2 := to_number(to_char(p_Minuend, 'HH24')); 123 v_ReturnValue := v_ReturnValue * 24 + (v_HourNum2 - v_HourNum1); 124 elsif v_Component in ('MI', 'MINUTE') then 125 --分情况 126 --第一步:求出天数 127 v_ReturnValue := (to_date(to_char(p_Minuend, 'yyyy-mm-dd'), 128 'YYYY-MM-DD') - 129 to_date(to_char(p_Subtranhend, 'yyyy-mm-dd'), 130 'YYYY-MM-DD')); 131 --第二步:求出时数 132 v_HourNum1 := to_number(to_char(p_Subtranhend, 'HH24')); 133 v_HourNum2 := to_number(to_char(p_Minuend, 'HH24')); 134 v_ReturnValue := v_ReturnValue * 24 + (v_HourNum2 - v_HourNum1); 135 --第三步:求出分钟数 136 v_MinuteNum1 := to_number(to_char(p_Subtranhend, 'MI')); 137 v_MinuteNum2 := to_number(to_char(p_Minuend, 'MI')); 138 v_ReturnValue := v_ReturnValue * 60 + (v_MinuteNum2 - v_MinuteNum1); 139 elsif v_Component in ('S', 'SS', 'SECOND') then 140 --秒情况 141 --第一步:求出天数 142 v_ReturnValue := (to_date(to_char(p_Minuend, 'yyyy-mm-dd'), 143 'YYYY-MM-DD') - 144 to_date(to_char(p_Subtranhend, 'yyyy-mm-dd'), 145 'YYYY-MM-DD')); 146 --第二步:求出时数 147 v_HourNum1 := to_number(to_char(p_Subtranhend, 'HH24')); 148 v_HourNum2 := to_number(to_char(p_Minuend, 'HH24')); 149 v_ReturnValue := v_ReturnValue * 24 + (v_HourNum2 - v_HourNum1); 150 --第三步:求出分钟数 151 v_MinuteNum1 := to_number(to_char(p_Subtranhend, 'MI')); 152 v_MinuteNum2 := to_number(to_char(p_Minuend, 'MI')); 153 v_ReturnValue := v_ReturnValue * 60 + (v_MinuteNum2 - v_MinuteNum1); 154 --第四步:求出秒钟数 155 v_SecondNum1 := to_number(to_char(p_Subtranhend, 'SS')); 156 v_SecondNum2 := to_number(to_char(p_Minuend, 'SS')); 157 v_ReturnValue := v_ReturnValue * 60 + (v_SecondNum2 - v_SecondNum1); 158 elsif v_Component in ('Q', 'QQ', 'QUARTER') then 159 --季度情况 160 v_YearNum1 := to_number(to_char(p_Subtranhend, 'YYYY')); 161 v_YearNum2 := to_number(to_char(p_Minuend, 'YYYY')); 162 v_QuarterValue1 := to_number(to_char(p_Subtranhend, 'Q')); 163 v_QuarterValue2 := to_number(to_char(p_Minuend, 'Q')); 164 v_ReturnValue := (v_YearNum2 - v_YearNum1) * 4 + 165 (v_QuarterValue2 - v_QuarterValue1); 166 elsif v_Component in ('W', 'WW', 'WK', 'WEEK') then 167 --周情况 168 --一周的起始日期应当为星期日 169 --关于周差的计算,尝试采用中间日期的方法 170 --经查,‘1-1-2’即公元一年1月2日为周日,我们就可以用两个时间分别与其相减求周差 171 --两个结果再相减,即可得到正确的数值 172 v_WeekNum1 := floor((to_date(to_char(p_Subtranhend, 'YYYY-MM-DD'), 173 'YYYY-MM-DD') - 174 to_date('1-1-2', 'YYYY-MM-DD')) / 7); 175 v_WeekNum2 := floor((to_date(to_char(p_Minuend, 'YYYY-MM-DD'), 176 'YYYY-MM-DD') - 177 to_date('1-1-2', 'YYYY-MM-DD')) / 7); 178 v_ReturnValue := v_WeekNum2 - v_WeekNum1; 179 else 180 v_ReturnValue := -88888; 181 end if; 182 RETURN v_ReturnValue; 183 EXCEPTION 184 WHEN OTHERS THEN 185 RETURN - 99999; --例外处理 186 END datediff; 187 188 函数三: 189 190 191 192 create or replace function datepart(p_Component varchar2, p_Date date) 193 RETURN NUMBER IS 194 /*************************************************************************/ 195 /* 功 能:获取某个日期中的部分时间元件(日、月、年、分、秒、等) */ 196 /* 入参说明: p_Component 时间元件,如年月日季度等等 */ 197 /* p_Date 需要解析的时间 */ 198 /*************************************************************************/ 199 v_Component varchar2(10); 200 v_ReturnValue NUMBER; 201 BEGIN 202 v_Component := upper(ltrim(rtrim(p_Component))); 203 if v_Component in ('Y', 'YY', 'YEAR', 'YYYY') then 204 --年情况 205 v_ReturnValue := to_number(to_char(p_Date, 'YYYY')); 206 elsif v_Component in ('M', 'MM', 'MONTH', 'MON') then 207 --月情况 208 v_ReturnValue := to_number(to_char(p_Date, 'MM')); 209 elsif v_Component in ('D', 'DD', 'DAY') then 210 --日情况 211 v_ReturnValue := to_number(to_char(p_Date, 'DD')); 212 elsif v_Component in ('H', 'HH', 'HOUR', 'HH24') then 213 --时情况 214 v_ReturnValue := to_number(to_char(p_Date, 'HH24')); 215 elsif v_Component in ('MI', 'MINUTE') then 216 --分情况 217 v_ReturnValue := to_number(to_char(p_Date, 'MI')); 218 elsif v_Component in ('S', 'SS', 'SECOND') then 219 --秒情况 220 v_ReturnValue := to_number(to_char(p_Date, 'SS')); 221 elsif v_Component in ('Q', 'QQ', 'QUARTER') then 222 --季度情况 223 v_ReturnValue := to_number(to_char(p_Date, 'Q')); 224 elsif v_Component in ('W', 'WW', 'WK', 'WEEK') then 225 --周几情况(周日为第一天) 226 v_ReturnValue := to_number(to_char(p_Date, 'D')); 227 elsif v_Component in ('WEEK_NO') then 228 -- 第几周情况 229 v_ReturnValue := to_number(to_char(p_Date, 'IW')); 230 else 231 v_ReturnValue := -88888; 232 end if; 233 234 RETURN v_ReturnValue; 235 EXCEPTION 236 WHEN OTHERS THEN 237 RETURN - 99999; --例外处理 238 239 END datepart;