java Calendar类的add方法与oracle的add_months方法的使用
- 1.java Calendar类
- 2.oracle ADD_MONTHS
- 3.为什么不同
最近程序中出现了一个非常怪异的问题:
在java程序中时间范围是2019.9.30~2019.10.30
但是在c++的程序用的是2019.9.30~2019.10.31
java 程序负责往oracle数据库中写入数据,C++程序从oracle程序中读取数据。
一写一读怎么就出现问题了呢?
而且客户反映,这个问题比较特殊,只有开始时间是月底,且时间段是1个月的才会复现。
真是见了鬼了。
ok,查问题。
发现c++从oracle数据库中查询数据时并不是直接查询截止时间,而是根据开始时间+月份数计算的,使用的就是oracle里面的一个函数ADD_MONTHS。
这个时间就出现了偏差。
真是坑啊。
java中使用Calendar类的add方法计算的,所以oracle中就使用相同的业务逻辑进行处理。
测试正常的数据也没有什么问题。
但是,就是月底这个数据就出现问题了。。。。。。。。。。
oracle有月底概念,java没有月底概念。
1.java Calendar类
public class MyCl {@Test
public void getNextMonthOneDate() throws ParseException {
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd");
Date date = dateFormat.parse("2019-1-31");
System.out.println(dateFormat.format(date));
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.MONTH, 1);
// calendar.add(Calendar.SECOND, -1);
Date end = new Date(calendar.getTimeInMillis());
System.out.println(dateFormat.format(end));
}
}
就这样一个简单的程序,我们计算下时间:
是的,我测试用的jdk的版本为6u38版本(还有公司在用吗?)
2.oracle ADD_MONTHS
oracle的ADD_MONTHS是oracle实现的函数,接收2个参数,返回一个参数。
第一个参数为时间,第二个参数为整数,返回时间。
'yyyy-mm-dd')
FROM DUAL;
我们用这个SQL语句对同样的时间进行查询:
oracle的版本
3.为什么不同
经过查看jdk源码,oracle的实现以及自己测试数据,得出下面的结论。(如有问题,还请指正)
在oracle中,存在两种概念:
对于普通日期,对日期加1月,就是说下一个是什么日期。
举个例子:
3月5日过一个月是几月几号?
4月5日。
对于月底日期,对日期加1月,就是说下一个月的月底是什么日期。
举个例子:
3月5日下一个月月底是几月几号?
4月30日。
总结:
x年y月z日加n月
=> (x+(y+n)/13)年((y+n) > 12 ? ((y+n)%12 == 0 ? 12:(y+n)%12) : (y+n))月min(dayofmon(y),dayofmon((y+n) > 12 ? (y+n)%12 : (y+n))) || enddayofmon((y+n) > 12 ? (y+n)%12 : (y+n))日
举个例子:
2019年5月4日+4月
=>2019年9月4日
2019年5月31日+8月
=> 2020年1月31日
2019年2月27日+22月
2019+24/13=2020
24%12 = 0 => 12
=>2020年12月27日
2019年2月28日+22月
=>2020年12月31日
在java中就只有普通日期,没有月底日期这个概念:
举个例子:
2019.1.31
=>2019.2.28
2019.2.28
=>2019.3.28
总结:
x年y月z日加n月
=> (x+(y+n)/13)年((y+n) > 12 ? ((y+n)%12 == 0 ? 12:(y+n)%12) : (y+n))月min(dayofmon(y),dayofmon((y+n) > 12 ? (y+n)%12 : (y+n))) 日
举个例子:
2019年5月4日+4月
=>2019年9月4日
2019年5月31日+8月
=>2020年1月31日
2019年2月27日+22月
2019+24/13 = 2020
24%12 = 0 =>12
=>2020年12月27日
2019年2月28日+22月
=>2020年12月28日
说了这么多,这两种计算日期的方式有什么区别? oracle有月底概念,java没有月底概念。