java Calendar类的add方法与oracle的add_months方法的使用

java Calendar类的add方法与oracle的add_months方法的使用


最近程序中出现了一个非常怪异的问题:
在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个参数,返回一个参数。
第一个参数为时间,第二个参数为整数,返回时间。

SELECT TO_CHAR(ADD_MONTHS(TO_DATE('2020-4-30', 'yyyy-mm-dd'), 1),
               '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没有月底概念。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值