昨晚修改一个图书馆的续借书籍日期的时候,发现了Date类的before()方法和after()方法,有点小问题。
首先给大家看我演示的第一个结论,直接上代码,代码中有注释
package a; import java.util.Date; public class 比较日期 { public static void main(String[] args) { // A.before(B)返回的是(A在B之前返回true,否则返回false) // A.after(B)返回的是(A在B之后返回true,否则返回false) Date a = new Date(); Date b = new Date(); System.out.println("a.before(a)-->" + a.before(a)); System.out.println("a.after(a)-->" + a.after(a)); System.out.println("a.before(b)-->" + a.before(b)); System.out.println("a.after(b)-->" + a.after(b)); System.out.println("-----------------------------"); Date c = new Date(1990, 5, 29); System.out.println("a.before(c)-->" + a.before(c)); System.out.println("a.after(c)-->" + a.after(c)); System.out.println("c.before(a)-->" + c.before(a)); System.out.println("c.after(a)-->" + c.after(a)); // 从上面可以知道: // A.before(B)在A<B时,返回true;在A>=B时,返回false; // A.after(B)在A>B时,返回true;在A<=B时,返回false; } }
运行的结果如下
a.before(a)-->false a.after(a)-->false a.before(b)-->false a.after(b)-->false ----------------------------- a.before(c)-->true a.after(c)-->false c.before(a)-->false c.after(a)-->true
细心的读者会发现,上述代码如果日期相同的话,返回的都是false,对吧
然而,问题出现了,请看下面的代码,首先声明一下,今天是2012年11月25号。
package a; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; public class 比较日期 { public static void main(String[] args) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd", Locale.CHINA); Date a = sdf.parse("2012/11/25");// 我自己定义的日期,也是2012/11/25日 Date b = new Date();// 系统的日期,今天是2012/11/25日 System.out.println("a.before(b)-->" + a.before(b)); System.out.println("b.before(a)-->" + b.before(a)); System.out.println("b.after(a)-->" + b.after(a)); System.out.println("a.after(b)-->" + a.after(b)); System.out.println("-------------------------------"); Date c = sdf.parse("2012/11/25"); System.out.println("a.before(c)-->" + a.before(c));// 也可以说明跟变量的生成时间没有关系 System.out.println("c.before(a)-->" + c.before(a));// 也可以说明跟变量的生成时间没有关系 } }
注意看运行结果,如下
a.before(b)-->true b.before(a)-->false b.after(a)-->true a.after(b)-->false ------------------------------- a.before(c)-->false c.before(a)-->false
很明显,结果是按照这两个日期不同来进行判断的,所以才会有上面的运行结果。
其实,上面的运行结果的逻辑是正确的,如果a,b不是在一天的话,方法确实很正确。
但是,上面的运行结果是在a,b是同一天的情况下,那么,明明是同一天,为什么有两个结果不是false呢?
这个问题纠结了我一个晚上,网上也没有解决的办法,于是我细细看了java 的API,汉化后如下
before方法 public boolean before(Date when)测试此日期是否在指定日期之前。 参数: when - 日期。 返回: 当且仅当此 Date 对象表示的瞬间比 when 表示的瞬间早,才返回 true;否则返回 false。 抛出: NullPointerException - 如果 when 为 null。 -------------------------------------------------------------------------------- after方法 public boolean after(Date when)测试此日期是否在指定日期之后。 参数: when - 日期。 返回: 当且仅当此 Date 对象表示的瞬间比 when 表示的瞬间晚,才返回 true;否则返回 false。 抛出: NullPointerException - 如果 when 为 null。
那么瞬间又是指的是什么呢?难道是变量生成的瞬间,生成变量的前后么?跟这个有关系么?
很明显,第一个例子就说明,按照先后顺序,生成变量,如果都是今天的话,返回的是false。说明不是变量生成的瞬间。
如果不相信的话,继续代码贴出来,一看就明白了,下面的这两个代码运行结果是一样的。
package a; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; public class 比较日期 { public static void main(String[] args) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd", Locale.CHINA); Date a = sdf.parse("2012/11/25");// 我自己定义的日期,也是2012/11/25日 Date b = new Date();// 系统的日期,今天是2012/11/25日 System.out.println("a.before(b)-->" + a.before(b)); System.out.println("b.before(a)-->" + b.before(a)); } }
package a; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; public class 比较日期 { public static void main(String[] args) throws ParseException { Date b = new Date();// 系统的日期,今天是2012/11/25日 SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd", Locale.CHINA); Date a = sdf.parse("2012/11/25");// 我自己定义的日期,也是2012/11/25日 System.out.println("a.before(b)-->" + a.before(b)); System.out.println("b.before(a)-->" + b.before(a)); } }
结果都是
a.before(b)-->true b.before(a)-->false
说明,跟变量生成顺序的先后无关。
那么这个瞬间到底是什么情况呢?这个就不知道了,这个就需要我们查看java的date类的源代码了,它内部的比较的机制是怎么回事呢?
这个我在网上找了找,也没有找到答案,希望哪位大神知道的话,可以告诉我一声。
当然,我自己有一个自己的认识,可以解释这个问题,不知道正确还是错误,遇到
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd", Locale.CHINA); Date a = sdf.parse("2012/11/25");// 我自己定义的日期,也是2012/11/25日
这个情况的时候,默认是比生成的系统的那个要小的。这样对代码的运行结果,以及API的说明,都无影响。
这个纯属个人观点,我目前的水平只能这样理解,谁有更好的理解方式,可以告诉我。
写这个帖子的目的在于,大家以后使用Date类的时候,一定要小心,日期相同的情况是true还是false,是要看比较的对象是自己定义的,还是系统的。
所以,慎用此方法,能用Calendar类代替就用Calendar类代替。