今天收到一个生产 bug,场景如下:列表有两个字段分别记录用户的入党日期和转正日期,正常来说入党日期比转正日期早一年整,用户在导出列表数据的时候发现入党日期和转正日期是一样的,这明细与系统上显示的不符合。
如图所示:
好了,bug 定位,首先想到的肯定就是是不是在 Java 代码中 set 字段设置错误了,拿的是和转正时间一个字段,但是其他数据都正常,只有这一个异常,明显不是。
于是开始 debug,发现有一行代码异常:
dataMap.put(12, sdf.format(membersList.get(i).getJoinPartyTime()));
membersList.get(i).getJoinPartyTime()) 获取到的时间戳为 1041177600000,就是 2002-12-30 00:00:00,但是发现,经过 format 函数转换之后,得到的结果却是,2003-12-30。这很奇怪,于是去看了 sdf 的时间格式,代码如下:
SimpleDateFormat sdf = new SimpleDateFormat("YYYY/MM/dd");
果然,Idea 编译器都给出高亮提示了,YYYY 应该替换成 yyyy,那这是为什么呢?
于是进行测试:
结合2张图,可以得知,
2015-12-27 日这天的Unix时间戳经过 SimpleDateFormat("YYYY-MM-dd")
之后,结果会加了一年,变成了2016-12-27.注意这里的格式中 “YYYY” 是大写的。
而将 “YYYY” 换成 “yyyy” 即 SimpleDateFormat(“yyyy-MM-dd”) 之后结果都完全正确。
查询文档
得知,正确的用法就是用小写的 “y”。那么大写的 “Y” 为啥有时对有时不对了呢?
通过查询 Java 文档 得知
A week year is in sync with a WEEK_OF_YEAR cycle. All weeks between the first and last weeks (inclusive) have the same week year value. Therefore, the first and last days of a week year may have different calendar year values.
“YYYY” 代表的是星期年
,而 “yyyy” 代表的是公历年
。
什么是星期年呢?
星期年(Week Year)是指根据 ISO 8601 标准计算的年度序号,种年度序号基于周而不是传统的公历年。以 52 周作为完整的一年。每个星期年通常以第一周的星期天作为一年的开始,以第 52 周的星期六作为一年的结束。(在星期年的标准下,星期天是一周的开始,星期六是一周的结束)
举例说明:
假设我们以 2002 年为例,按照星期年的定义:
- 2002 年的最后一个星期六是 2002 年的12 月 28 日结束的,2002 年 12 月 29 日是 2003 年的开始(星期天)。
代码检测:
public static void main(String[] args) {
long time1 = 1041091200000L; // 2002-12-29 00:00:00
long time2 = 1041004800000L; // 2002-12-28 00:00:00
SimpleDateFormat sf = new SimpleDateFormat("YYYY-MM-dd");
String date1 = sf.format(time1);
String date2 = sf.format(time2);
System.out.println(date1);
System.out.println(date2);
}
输出结果:
2003-12-29 // 年份归属了2003
2002-12-28
因此通过SimpleDateFormat("YYYY-MM-dd")
格式化之后多了一年也就很好解释了,就是通过获取周年然后加上月份与日期,因此多了一年。