oracle add_months函数与Java不同

时间:2009-09-24 19:29:50

标签: java oracle

我最近发现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中的某些参数)?

4 个答案:

答案 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_monthshttp://download-west.oracle.com/docs/cd/B19306_01/server.102/b14200/functions004.htm

上的Oracle参考
  

如果日期是该月的最后一天,或者结果月份的日期少于日期的日期组成部分,则结果是结果月份的最后一天。否则,结果与日期具有相同的日期组件。

这意味着你将不得不为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();
}