我最近发现Oracle在给定日期(使用ADD_MONTHS函数)添加月数与Java向Calendar对象添加月份的方式之间存在差异。
例如在oracle中:
select add_months('2009-02-28', +1) from dual;
产生了结果:“09-03-31”
查询:
select add_months('2009-02-28', -1) from dual;
产生结果“09-01-31”
然而在Java中,相同计算的结果(使用GregorianCalendar.add()方法)分别是: 28年9月3日 和 28年9月1日
是否有某种方法可以使Oracle和Java的行为相同? (例如oracle中的某些设置或Java中的某些参数)?
答案 0 :(得分:5)
当您进行月算术时,您需要从业务角度决定处理具有不同天数的月份的正确方法。你提出的问题的另一面是从较长的月份(如8月份)到较短的月份(如2月份)(如果涉及到闰年,甚至从2月到2月)。 如果您对报告错误感到高兴,因为计算无法找到'Feb-30',那么请查看INTERVAL
答案 1 :(得分:4)
您可以创建自己的 DateService 类,例如波纹管,并使用“ addMonthToDateLikeOracle ”方法。
package db;
import org.joda.time.LocalDate;
import java.util.Calendar;
import java.util.Date;
public class DateService {
public static Date addMonthToDateLikeOracle(Date date, int months) {
Calendar c = Calendar.getInstance();
c.setTime(date);
Date retval;
if (DateService.isLastDayOfMonth(date)) {
c.add(Calendar.MONTH, 1);
c.add(Calendar.MONTH, 1);
c.set(Calendar.DATE, 1);
c.add(Calendar.DATE, -1);
retval = c.getTime();
} else {
retval = LocalDate.fromDateFields(date).plusMonths(months).toDate();
}
return retval;
}
public static boolean isLastDayOfMonth(Date date) {
if (date == null) {
throw new RuntimeException("The date parameter cannot be null!");
}
Date endOfMonth = getEndOfMonth(date);
return endOfMonth.equals(date);
}
public static Date getEndOfMonth(Date date) {
Date startOfMonth = getStartOfMonth(date);
Date startOfNextMonth = LocalDate.fromDateFields(startOfMonth).plusMonths(1).toDate();
return LocalDate.fromDateFields(startOfNextMonth).plusDays(-1).toDate();
}
public static Date getStartOfMonth(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.DAY_OF_MONTH, 1);
return calendar.getTime();
}
}
答案 2 :(得分:2)
来自add_months
(http://download-west.oracle.com/docs/cd/B19306_01/server.102/b14200/functions004.htm)
如果日期是该月的最后一天,或者结果月份的日期少于日期的日期组成部分,则结果是结果月份的最后一天。否则,结果与日期具有相同的日期组件。
这意味着你将不得不为Java编写一个方法来执行相同的检查以获得相同的结果(或者PL / SQL中的函数与Java的行为相同)。
答案 3 :(得分:0)
您可以在java中编写自己的add months函数。
public Date functionAddMonth(Date d, int month)
{
Calendar c = Calendar.getInstance();
c.setTime(d);
c.add(Calendar.DAY, 1);
c.add(Calendar.MONTH, month);
c.add(Calendar.DAY, -1);
return c.getTime();
}