2019 年 12 月 29 到 31 日在格式化时间时出现了一个有趣的小 bug:比如 2019 年 12 月 31 日时间戳有可能会被格式化成:2020-12-31。
这里给出复现和对比的代码:
1Long timeStamp = 1577750400000L;//2019-12-31 08:00:00 的时间戳
2SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
3SimpleDateFormat sdf2 = new SimpleDateFormat("YYYY-MM-dd");
4System.out.println(sdf1.format(timeStamp));//System.out: 2019-12-31
5System.out.println(sdf2.format(timeStamp));//System.out: 2020-12-31
可以看到当年份格式化时,使用 YYYY
会被格式化成 2020,而 yyyy
是我们想要的 2019。
显而易见,这个 bug 出现的原因是:y
和 Y
的语义不同。根据 JDK 文档规定:y
表示年份(Year),Y
表示周所属的年份(Week year)。
根据 ISO 8601 定义:包含当年第一个周四的那一周是第一周(等效语义:1 月 4 日所在的周是第一周)。JDK 默认的周起始日是周日,所以 2019-12-29 到 2020-01-04 是 2020 年的第一周。那么使用 YYYY
格式化出来的数据 2019-12-29 到 2019-12-31 都是 2020。