BUG现场

一个线上项目之前一直运行得很稳定,从没出过数据错误的问题,但是在2021.12.26这天却“意外”地出现了数据计算错误。

刚开始一头雾水,不知道是什么问题,后来经过日志排查才定位到原来是日期格式化引起的问题,原本应该是“2021-12-26”日期字符串,但是格式化为“2022-12-26”了。

现场还原:

// 备注:如下示例代码的输出结果是在2022.01.09执行的
// 2021-12-26
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2021);
calendar.set(Calendar.MONTH, 11);
calendar.set(Calendar.DATE, 26);
Date date = calendar.getTime();
String p1 = "YYYY-MM-dd";
String p2 = "yyyy-MM-dd";
SimpleDateFormat f1 = new SimpleDateFormat(p1);
SimpleDateFormat f2 = new SimpleDateFormat(p2);
// 输出2022-12-26
System.out.println(f1.format(date));
// 输出2021-12-26
System.out.println(f2.format(date));

从上述代码的输出结果来看,使用"YYYY-MM-dd"格式化出来的日期显然是不对的,必须使用“yyyy”才能格式化出正确的“年”。

然而有意思的是:在Java中不论是“YYYY”还是“yyyy”都可以用来格式化“年”,且都是合法的!那么,它们的区别是什么呢?在使用过程中该如何选择呢?

原因追溯

实际上,Java中格式化日期可以使用的格式已经明确在java.text.SimpleDateFormat类的注释中明确定义了。

从字面上看,“y”和“Y”是有区别的:“y”表示的年为我们通常所说的年,即当前真正所属的年份;而“Y”表示的是一种所谓“周年”的计算方法,那么这个“周年”的第一周是什么时候呢?根据中华人民共和国国家标准GB/T 7408-2005《数据元和交换格式信息交换日期和时间表示法》中4.3.2.2部分:

即一年中的第一个日历星期包括该年的第一个星期四,并且日历年的最后一个日历星期就是在下一个日历年的第一个日历星期之前的那个星期,日历星期数是其在该年中的顺序。

按照这个计算方法,"2021-12-26"将是2021年的最后一周,而“2021-12-30”为周四,会被计算为“2022”年的第一周,也就是说如果使用“YYYY”格式化日期,从“2021-12-27”开始都会被计算为2022年。

我的程序出错正好是“2021-12-27 00:00:00”之后,所以就能解释为什么被格式化为“2022”年了。

解决办法

既然Java中关于年的格式化“y”和“Y”有着不同的含义,“y”才能表示我们通常意义上理解的真实的年份,那么我们在使用时就必须记住,只能使用“yyyy”格式化年份,而不要使用“YYYY”。

为了避免的每次格式化日期时写错格式,可以直接引用一些经过实践验证后固话下来的工具方法,比如hutool-core中的工具类:cn.hutool.core.date.DateUtil。

// 使用hutool-core的工具类DateUtil格式化日期
System.out.println(DateUtil.formatDate(new Date()));

【参考】

https://blog.csdn.net/weixin_29092031/article/details/114191979 java格式化日期 yyyy_JAVA日期格式化中的“yyyy”与“YYYY”

Java日期格式化带来的年份不正确的更多相关文章

  1. Java日期格式化方法

    首先获取当前系统时间的方法有两种:第一种可以用currentTimeMillis()方法获取,它其实产生的是一个当前的毫秒数,这个毫秒是自1970年1月1日0时起至现在的毫秒数,类型是long 型,可 ...

  2. Java日期格式化

    翻译人员: 铁锚 翻译时间: 2013年11月17日 原文链接:   Simple example to show how to use Date Formatting in Java 代码示例如下, ...

  3. java 日期格式化-- SimpleDateFormat 的使用。字符串转日期,日期转字符串

    日期和时间格式由 日期和时间模式字符串 指定.在 日期和时间模式字符串 中,未加引号的字母 'A' 到 'Z' 和 'a' 到 'z' 被解释为模式字母,用来表示日期或时间字符串元素.文本可以使用单引 ...

  4. Java日期格式化及其使用例子收集

    1 SimpleDateFormat担当重任,怎样格式化都行 import java.util.Date; import java.text.SimpleDateFormat; public clas ...

  5. Java 日期格式化,Java 日期工具类,Java Date工具类

    ================================ ©Copyright 蕃薯耀 2020-01-19 https://www.cnblogs.com/fanshuyao/ import ...

  6. java 日期格式化

    DateFormat DateFormat 是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间. SimpleDateFormat SimpleDateFormat 是一个以与 ...

  7. java日期格式化(util包下转成sql包下)

    package test; import java.text.SimpleDateFormat;import java.util.Date;import java.util.Scanner; publ ...

  8. Java——日期格式化YYYYMMdd与yyyyMMdd的区别

    public static void main(String[] args) { //YYYY 是表示:当天所在的周属于的年份,一周从周日开始,周六结束,只要本周跨年,那么这周就算入下一年. //20 ...

  9. Java日期格式化参数对照表

    Symbol Meaning Presentation Example G era designator Text AD y year Number 2009 M month in year Text ...

随机推荐

  1. 设置项目的日程排定方式(Project)

    <Project2016 企业项目管理实践>张会斌 董方好 编著 [项目]>[属性]>[项目信息]>[日程排定方法]>选取: 默认项是[项目开始日期]. 这两位是干 ...

  2. android 基于dex的插件化开发

    安卓里边可以用DexClassLoader实现动态加载dex文件,通过访问dex文件访问dex中封装的方法,如果dex文件本身还调用了native方法,也就间接实现了runtime调用native方法 ...

  3. Python3的数据类型

    不可变类型:Number(数值,包含Bool类型).String(字符串).Tuple(元组) 可变类型:List(列表).Dict(字典).Set(集合) Bool不再单独存在,属于Number数值 ...

  4. LuoguB2029 大象喝水 题解

    Update \(\texttt{2021.12.4}\) 修改了原先的错误代码,给各位造成影响,在此表示很抱歉. Content 大象要喝 \(20\) 升水,但现在只有一个深 \(h\) 厘米,半 ...

  5. CF831B Keyboard Layouts 题解

    Content 给你 \(26\) 个字母的映射(都是小写,大写的映射方式相同),再给你一个字符串 \(s\),求它的映射结果(如果有非字母的字符保持不变). 数据范围:\(1\leqslant |s ...

  6. java 输入输出IO流 RandomAccessFile文件的任意文件指针位置地方来读写数据

    RandomAccessFile的介绍: RandomAccessFile是Java输入输出流体系中功能最丰富的文件内容访问类,它提供了众多的方法来访问文件内容,它既可以读取文件内容,也可以向文件输出 ...

  7. Spring Boot应用程序启动器

    官网地址:https://docs.spring.io/spring-boot/docs/2.1.12.RELEASE/reference/html/using-boot-build-systems. ...

  8. codeforce 597C-Subsequences(dp+树状数组)

    题目和南阳那道题一样链接http://www.cnblogs.com/zzuli2sjy/p/4943774.html 代码: 1 #include<stdio.h> 2 #include ...

  9. 实现golang io.Writer支持按照天为单位分割日志

    golang中的日志不支持按照天分割,很多开源的日志包都是只支持按照文件大小分割日志,不太利于生产环境中的使用.因此我实现了timewriter,支持: 实现按照天为单位分割日志,可以完美支持gola ...

  10. 海康威视摄像机Java SDK拉流(二)开启关闭实时预览

    本篇介绍海康威视摄像机通过SDK开启关闭实时预览接口 下篇介绍实时预览的回调函数及解码库 测试环境: 系统:Centos 7 SDK:设备网络SDK Linux64 实时预览模块流程: 图中虚线框部分 ...