首页 > 代码库 > [转] SQL日期函数dayadd/datediff/datepart

[转] SQL日期函数dayadd/datediff/datepart

  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;

 

[转] SQL日期函数dayadd/datediff/datepart