Java Calendar的add方法与Oracle的add_months方法有何不同应用场景?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1219个文字,预计阅读时间需要5分钟。
Java Calendar类的add方法与Oracle的ADD_MONTHS函数的使用:
1. Java Calendar类的add方法javaimport java.util.Calendar;
public class CalendarAddExample { public static void main(String[] args) { Calendar calendar=Calendar.getInstance(); calendar.set(2021, Calendar.DECEMBER, 31); // 设置为2021年12月31日 calendar.add(Calendar.MONTH, 1); // 月份加1 System.out.println(Java Calendar: + calendar.getTime()); }}
2. Oracle ADD_MONTHS函数sqlSELECT ADD_MONTHS(TO_DATE('31-DEC-2021', 'DD-MON-YYYY'), 1) FROM DUAL;
3. 为什么不同Java的Calendar.add方法在添加月份时,会根据当前日期自动调整年份和月份。例如,如果当前是12月,添加1个月后,年份会增加1,月份变为1月。
而Oracle的ADD_MONTHS函数仅增加月份,不会自动调整年份。如果月份超过12,它会将年份增加,并将月份设置为1。
最近程序中出现的异常问题:在Java程序中,当使用Calendar.add方法添加月份时,如果当前日期是月末(如2月28日),添加月份后,可能会出现日期不正确的问题。例如,如果将2月28日添加1个月,结果应该是3月28日,但由于Calendar的月份是从0开始的(0代表1月),所以实际上会变成3月29日。这是由于Java Calendar类在处理月末日期时的一个特性。
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没有月底概念。
本文共计1219个文字,预计阅读时间需要5分钟。
Java Calendar类的add方法与Oracle的ADD_MONTHS函数的使用:
1. Java Calendar类的add方法javaimport java.util.Calendar;
public class CalendarAddExample { public static void main(String[] args) { Calendar calendar=Calendar.getInstance(); calendar.set(2021, Calendar.DECEMBER, 31); // 设置为2021年12月31日 calendar.add(Calendar.MONTH, 1); // 月份加1 System.out.println(Java Calendar: + calendar.getTime()); }}
2. Oracle ADD_MONTHS函数sqlSELECT ADD_MONTHS(TO_DATE('31-DEC-2021', 'DD-MON-YYYY'), 1) FROM DUAL;
3. 为什么不同Java的Calendar.add方法在添加月份时,会根据当前日期自动调整年份和月份。例如,如果当前是12月,添加1个月后,年份会增加1,月份变为1月。
而Oracle的ADD_MONTHS函数仅增加月份,不会自动调整年份。如果月份超过12,它会将年份增加,并将月份设置为1。
最近程序中出现的异常问题:在Java程序中,当使用Calendar.add方法添加月份时,如果当前日期是月末(如2月28日),添加月份后,可能会出现日期不正确的问题。例如,如果将2月28日添加1个月,结果应该是3月28日,但由于Calendar的月份是从0开始的(0代表1月),所以实际上会变成3月29日。这是由于Java Calendar类在处理月末日期时的一个特性。
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没有月底概念。

