java中getDate()和getDay()方法踩坑

今天在调试bug的时候发现根据时间获取当天的年月日不对,如下

1
2
Date now=new Date();
Date day=new Date(now.getYear(),now.getMonth(),now.getDay());

打印出来的日期是Fri Jun 05 00:00:00 CST 2020
查找了下官方文档,描述如下
int getDate() Deprecated. As of JDK version 1.1, replaced by Calendar.get(Calendar.DAY_OF_MONTH).
int getDay() Deprecated. As of JDK version 1.1, replaced by Calendar.get(Calendar.DAY_OF_WEEK).
其中getDate()方法获取的才是当月的第几天。getDay()获取的时本周的第几天。
另外,查找了相关资料,总结了以下几个在java日期处理易踩的坑。

用Calendar设置时间的坑

反例

1
2
3
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR, 10);
System.out.println(c.getTime());

正例

1
2
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, 10);

解析:
我们设置了10小时,但运行结果是22点,而不是10点。因为Calendar.HOUR默认是按12小时制处理的,需要使用Calendar.HOUR_OF_DAY,因为它才是按24小时处理的。

Java日期格式化YYYY的坑

反例:

1
2
3
4
5
Calendar calendar = Calendar.getInstance();
calendar.set(2019, Calendar.DECEMBER, 31);
Date testDate = calendar.getTime();
SimpleDateFormat dtf = new SimpleDateFormat("YYYY-MM-dd");
System.out.println("2019-12-31 转 YYYY-MM-dd 格式后 " + dtf.format(testDate));

运行结果
2019-12-31 转 YYYY-MM-dd 格式后 2020-12-31
解析:
YYY是基于周来计算年的,它指向当天所在周属于的年份,一周从周日开始算起,周六结束,只要本周跨年,那么这一周就算下一年的了。正确姿势是使用yyyy格式。
正例:

1
2
3
4
5
Calendar calendar = Calendar.getInstance();
calendar.set(2019, Calendar.DECEMBER, 31);
Date testDate = calendar.getTime();
SimpleDateFormat dtf = new SimpleDateFormat("yyyy-MM-dd");
System.out.println("2019-12-31 转 yyyy-MM-dd 格式后 " + dtf.format(testDate));

Java日期格式化hh的坑

反例:

1
2
3
4
String str = "2020-03-18 12:00";
SimpleDateFormat dtf = new SimpleDateFormat("yyyy-MM-dd hh:mm");
Date newDate = dtf.parse(str);
System.out.println(newDate);

正例:

1
2
3
4
String str = "2020-03-18 12:00";
SimpleDateFormat dtf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Date newDate = dtf.parse(str);
System.out.println(newDate);

解析:
hh是12制的日期格式,当时间为12点,会处理为0点。正确姿势是使用HH,它才是24小时制。

Calendar获取的月份比实际数字少1即(0-11)

反例:

1
2
3
//获取当前月,当前是6月
Calendar calendar = Calendar.getInstance();
System.out.println("当前"+calendar.get(Calendar.MONTH)+"月份");

运行结果:当前5月份
正例:

1
2
3
//获取当前月,当前是3月
Calendar calendar = Calendar.getInstance();
System.out.println("当前"+(calendar.get(Calendar.MONTH)+1)+"月份");

解析:
The first month of the year in the Gregorian and Julian calendars
is JANUARY which is 0;
也就是1月对应的是下标 0,依次类推。因此获取正确月份需要加 1.

Java日期格式化DD的坑

DD和dd表示的不一样,DD表示的是一年中的第几天,而dd表示的是一月中的第几天。

Java日期的夏令时问题

反例:

1
2
3
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.parse("1986-05-04 00:30:00"));

运行结果:Sun May 04 01:30:00 CDT 1986
解析:
先了解一下夏令时:
夏令时,表示为了节约能源,人为规定时间的意思。
一般在天亮早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。
各个采纳夏时制的国家具体规定不同。目前全世界有近110个国家每年要实行夏令时。
1986年4月,中国中央有关部门发出“在全国范围内实行夏时制的通知”,具体作法是:每年从四月中旬第一个星期日的凌晨2时整(北京时间),将时钟拨快一小时。(1992年起,夏令时暂停实行。)
夏时令这几个时间可以注意一下哈,1986-05-04, 1987-04-12, 1988-04-10, 1989-04-16, 1990-04-15, 1991-04-14.
结合demo代码,中国在1986-05-04当天还在使用夏令时,时间被拨快了1个小时。所以0点30分打印成了1点30分。如果要打印正确的时间,可以考虑修改时区为东8区。
正例:

1
2
3
TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.parse("1986-05-04 00:30:00"));