plsql - oracle add_months添加额外的一天

时间:2017-03-15 19:11:10

标签: oracle plsql

Oracle: 12c

说明:尝试使用add_months将日期添加99年,但是它可以在返回日期值中添加额外的一天。我应该如何正确地添加年份?

declare 
  toRetDate DATE;
  inputDate DATE;
  numYears number;
begin

  numYears := 99;
  inputDate := TO_DATE('28-FEB-85', 'DD-Mon-YY' );
  toRetDate := add_months(inputDate, numYears*12);
  DBMS_OUTPUT.put_line(toRetDate);
end;

输出:29-FEB-84

2 个答案:

答案 0 :(得分:3)

ADD_MONTHS不会在结果中添加一天。相反,它具有这个非常一般的功能:如果您将月份添加到某个日期,并且该日期是该特定月份/年份的月末,则ADD_MONTHS的结果是结果月份的最后一天。

因此,例如,如果您在1月31日之前添加一个月,则总是在2月28日(或闰年2月29日)。如果你将一个月添加到6月30日,那么你将获得7月31日。

如果你在2月28日增加一个月,你将获得3月31日,除非它在闰年;在闰年2月28日不是这个月的最后一天,所以如果你加一个月就可以到3月28日。

在所有情况下,如果结果是天数大于结果月份中的天数,则结果只是该月的最后一天。

编辑:在本答案下面的评论中,OP会询问是否有办法保持当月的完全相同的一天,但2月29日(应该是2月)。非闰年28岁。)

答案是肯定的。正如@Xing在另一个答案中所示,添加interval '99' year将保留日期,但是当输入日期是2月29日并且结果年份不是闰年时,它可能会引起麻烦。这可以通过初步检查来解决。可以使用IF语句或CASE表达式来完成。我更喜欢后者,因为它在PL / SQL和SQL中的工作方式相同;在纯SQL中没有IF。

toretdate := case when to_char(inputdate, 'mm-dd') = '02-29'
                  then (inputdate + 1) + interval '99' year - 1
                  else inputdate + interval '99' year end

诀窍是,当inputdate是2月29日时,将它向前推进一天使其成为3月1日,然后再添加99年(仍然是3月1日),然后减去一天使其成为2月29日(如果是闰年)或2月28日(否则)。

答案 1 :(得分:0)

您可以这样使用:

declare 
  toRetDate DATE;
  inputDate DATE;
  numYears number;
begin

  numYears := 99;
  inputDate := TO_DATE('28-FEB-1985', 'DD-Mon-YYYY' );
  toRetDate := inputDate + INTERVAL '99' YEAR; --add_months(inputDate, numYears*12);
  DBMS_OUTPUT.put_line(to_date(toRetDate,'dd-mon-yyyy'));
end;

虽然值得注意的是,间隔的算术是有限的(如果没有破坏),因为它只是“增加”日期值的月/年值。这可能导致无效日期(例如从1月到2月)。

修改 一般情况Add_months通常会将30/31(取决于月份)添加到其应用日期。对于周一来说,情况略有不同。如果在add_months月份完成FEBURARY,则会根据leap year添加(28/29)天。 如果您的要求是简单地添加99 years而不检查结果日期是否为valiad,那么您可以使用INTERVAL,但如果您真的想检查结果日期是否应该得到很好的评估和正确的日期,那么你必须ADD_MONTHS。它不会使sense首次使用INTERVAL,然后检查结果日期(使用任何逻辑)是否为有效日期。 Oracle已经为此类方案提供了解决方案。