早上在群里看到一个老哥发出来的问题,原以为是老哥没睡醒判断12:00小于11:42为真,后续老哥说是期望是假,说错了。此时再看问题就怎么想怎么不对劲(老哥已经询问同事解决了问题,但我就想找下为什么会产生这样的问题)。

此为原例:

SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date completeTime = format.parse("2020-12-30 12:00:00");
Date endTime = format.parse("2020-12-30 11:42:00");
System.out.println(endTime.getTime() > completeTime.getTime());// it's true. but why?

此问题其实是老哥手误将时间里的HH写成了hh,这就变成了使用12小时制去解析时间,当时有个群友就说即使是12小时制也应该是12点更晚吧?我其实也是这么想的,但是我把代码自己敲一遍,看着结果我就只能去找为什么会变成这样。

我首先把原例子中的两个时间戳都输出出来,然后再把24小时制的时间戳也输出出来。

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date = format.parse("2020-12-30 12:00:00");
Date date2 = format.parse("2020-12-30 11:42:00");
System.out.println("date1 = " + date.getTime());
System.out.println("date2 = " + date2.getTime());
System.out.println(date2.after(date));

System.out.println("-----------24 hour style------------");

Date date1 = format2.parse("2020-12-30 12:00:00");
Date date3 = format2.parse("2020-12-30 11:42:00");
System.out.println("date1 = " + date1.getTime());
System.out.println("date2 = " + date3.getTime());

可以看到24小时制中12点的时间戳比较大,可以确定第一个是用了12小时制解析的。正常解析12小时制时间一般会带上AM/PM等,但是这里因为是误写自然是没有的,那么我按照12小时制解析方式去还原它的完整格式。

// java8必须指定语言环境,否则解析报错,而且还必须是英语。中文、简体中文等都不可。
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss a", Locale.ENGLISH);
Date date = format.parse("2020-12-30 12:00:00 AM");
// Date date = format.parse("2020-12-30 12:00:00 PM");
Date date2 = format.parse("2020-12-30 11:42:00 AM");
System.out.println("date1 = " + date.getTime());
System.out.println("date2 = " + date2.getTime());
System.out.println(date2.after(date));

System.out.println("-----------24 hour style------------");

SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("format2.format(date) = " + format2.format(date));

这次我想到把12点这个日期时间给转成24小时制的来看看到底是几点,然后发现这个12点是00:00,那就是按照上午12点去解析的,也就是如果没有指定AM/PM又要按12小时制解析,那么默认就是AM。然后我把12点的完整格式中的AM换成PM就可以得到正确的期望值,也与24小时制中的时间戳一样了。

至此日期时间的格式化问题就探究到这了,既长了见识又学了12小时制解析的方式,nice!