《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 http://www.iocoder.cn/Fight/YYYY-MM-dd-keng/ 「芋道源码」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

1. 概述

下班回家的路上,习惯性打开 群聊,不是为了解答问题,而是不想错过任何一个装 x 的机会。这不,就有胖友聊到一个经典的“神坑”:错误使用 YYYY-MM-dd 格式化时间,导致生产翻车。

带有马赛克的群聊

2. 翻车示例

下面,艿艿带大家写一个翻车的 Java 示例代码:

import java.text.SimpleDateFormat;
import java.util.Calendar;

public class TestXXXXXXXXXXXXX {

public static void main(String[] args) {
// 创建 2020-12-31
Calendar calendar = Calendar.getInstance();
calendar.set(2020, Calendar.DECEMBER, 31);

// 演示 YYYY-MM-dd 输出示例
SimpleDateFormat dfYYYY = new SimpleDateFormat("YYYY-MM-dd");
System.out.println("YYYY-MM-dd 输出:" + dfYYYY.format(calendar.getTime()));

// 演示 yyyy-MM-dd 输出示例
SimpleDateFormat dfyyyy = new SimpleDateFormat("yyyy-MM-dd");
System.out.println("yyyy-MM-dd 输出:" + dfyyyy.format(calendar.getTime()));
}

}

讲道理,正确输出的时间格式化结果应该为 "2020-12-31",但是使用 YYYY-MM-dd 却是 "2021-12-31"。如下图所示:

翻车啦

3. 翻车原因

为什么使用 YYYY-MM-dd 格式化 "2020-12-31" 时间时,打印的结果是错误"2021-12-31" 呢?

我们打开 https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#patterns 文档,看看 YYYY 的定义描述,就非常好理解背后的原因:

官方文档

翻译君:YYYY 使用的是 week-based-year,当天所在的周属于的年份,一周从周日开始,周六结束。只要本周跨年,那么这周就算入下一年。

关键在于 “只要本周跨年,那么这周就算入下一年” 这句话!什么意思呢,打开日历,安排的明明白白。

日历 - 2020~12

因为 "2021-01-01" 属于 2021 年,而 "2020-12-31" 与其处于同一周,所以被 YYYY 格式化时,输出的肯定是 2021 啦。不仅仅如此,这个问题,从 "2020-12-27" 开始就已经存在。

我们再来打开日历到 2021 年的 12 月来瞅瞅,康康还会不会存在翻车的情况。

日历 - 2021~12

答案当然是,翻车

未来不过是历史的一再重演。

4. 怎么避免

问题的解决,非常容易,只要将 YYYY-MM-dd 修改成 yyyy-MM-dd 即可。

但是,仅仅这样就足够了吗?良心的艿艿,建议胖友一定要定义一个 DateUtil 工具类,并在其中将常用的日期格式都提供好,禁止在其它地方定义。

日历 - 2021~12

实际上,有良好 IDEA 使用习惯的胖友,绝对不会出现 YYYY 这样的问题,因为 IDEA 已经智能提醒

IDEA

一切 IDEA 警告,皆为错误,必须去解决。


End~继续抠脚。

我是艿艿,一个每天徘徊在煞笔牛啤的死胖子。

我

文章目录
  1. 1. 1. 概述
  2. 2. 2. 翻车示例
  3. 3. 3. 翻车原因
  4. 4. 4. 怎么避免