Java日期格式化中的“YYYY”陷阱:为什么跨年周会让你的年份突然+1?.md
结论先行
在Java中使用 YYYY-MM-dd
格式化日期时,若日期所在的周跨年,年份可能会被错误计算为下一年(如2021年12月26日显示为2022年)。而使用 yyyy-MM-dd
会始终返回正确的年份。问题的根源是 YYYY
和 yyyy
对年份的定义不同:YYYY
是「基于周的年份」,而 yyyy
是「自然年份」。
文章持续更新,可以微信搜一搜「 半个脑袋儿 」第一时间阅读
问题复现
尝试用以下代码格式化 2021-12-26
:
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateFormatDemo {
public static void main(String[] args) {
SimpleDateFormat sdf1 = new SimpleDateFormat("YYYY-MM-dd");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
Date date = new Date(121, 11, 26); // 2021年12月26日
System.out.println(sdf1.format(date)); // 输出:2022-12-26
System.out.println(sdf2.format(date)); // 输出:2021-12-26
}
}
结果差异明显,YYYY
的年份跳到了2022年。
原因解析
1. YYYY
是「基于周的年份」
- 定义:
YYYY
遵循 ISO 8601 标准,表示「日期所在周所属的年份」。 - 周的计算规则:
- 默认一周从 周日开始,到 周六结束(可通过
Locale
调整,如某些地区从周一开始)。 - 若某周跨年(即该周包含新年的第一天),则这一周会被归属到新年所在的年份。
- 默认一周从 周日开始,到 周六结束(可通过
以 2021年12月26日 为例:
- 该周为 2021年12月26日(周日)至2022年1月1日(周六)。
- 由于这一周的大部分天数(4天)属于2022年,因此
YYYY
会将其归属到2022年。
2. yyyy
是「自然年份」
- 定义:
yyyy
直接表示日期所在的自然年份,与周无关。 - 无论日期是否跨周或跨月,始终返回实际年份。
如何避免踩坑?
优先使用
yyyy
除非明确需要基于周的年份计算,否则格式化日期时应使用yyyy
。理解业务场景
- 财务系统、周报统计等可能需要
YYYY
(如按周生成报表)。 - 普通日期场景(如订单时间、日志记录)应使用
yyyy
。
- 财务系统、周报统计等可能需要
注意
Locale
的影响- 不同地区的周起始日不同(如美国默认周日开始,欧洲多从周一开始)。
- 可通过
SimpleDateFormat.setLocale()
或DateTimeFormatter.withLocale()
指定区域。
Java 8+ 的替代方案
使用DateTimeFormatter
时,yyyy
对应Y
和u
的行为更清晰:LocalDate date = LocalDate.of(2021, 12, 26);
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("YYYY-MM-dd");
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd"); System.out.println(date.format(formatter1)); // 2022-12-26
System.out.println(date.format(formatter2)); // 2021-12-26
总结
YYYY
与yyyy
的区别:基于周的年份 vs 自然年份。- 根本原因:跨年周的归属规则导致
YYYY
的年份偏移。 - 最佳实践:若无特殊需求,始终使用
yyyy-MM-dd
格式化日期。
一个小小的格式字符差异,可能导致跨年时的严重逻辑错误。切记:日期格式化无小事!
Java日期格式化中的“YYYY”陷阱:为什么跨年周会让你的年份突然+1?.md的更多相关文章
- Java日期格式化带来的年份不正确
BUG现场 一个线上项目之前一直运行得很稳定,从没出过数据错误的问题,但是在2021.12.26这天却"意外"地出现了数据计算错误. 刚开始一头雾水,不知道是什么问题,后来经过日志 ...
- java 时间格式化中的模式字母
java日期格式化中的模式字母有特定的意义,由于没有注意,今天在做工程的时候导致出现了奇怪的日期: 错误写法如下: 然而得到了错误的结果: 正确写法如下: 这样就得到了正确的结果 mm指的是分钟,MM ...
- Java日期格式化方法
首先获取当前系统时间的方法有两种:第一种可以用currentTimeMillis()方法获取,它其实产生的是一个当前的毫秒数,这个毫秒是自1970年1月1日0时起至现在的毫秒数,类型是long 型,可 ...
- java 日期格式化-- SimpleDateFormat 的使用。字符串转日期,日期转字符串
日期和时间格式由 日期和时间模式字符串 指定.在 日期和时间模式字符串 中,未加引号的字母 'A' 到 'Z' 和 'a' 到 'z' 被解释为模式字母,用来表示日期或时间字符串元素.文本可以使用单引 ...
- Java日期格式化
翻译人员: 铁锚 翻译时间: 2013年11月17日 原文链接: Simple example to show how to use Date Formatting in Java 代码示例如下, ...
- Java——日期格式化YYYYMMdd与yyyyMMdd的区别
public static void main(String[] args) { //YYYY 是表示:当天所在的周属于的年份,一周从周日开始,周六结束,只要本周跨年,那么这周就算入下一年. //20 ...
- Java日期格式化及其使用例子收集
1 SimpleDateFormat担当重任,怎样格式化都行 import java.util.Date; import java.text.SimpleDateFormat; public clas ...
- Java 日期格式化,Java 日期工具类,Java Date工具类
================================ ©Copyright 蕃薯耀 2020-01-19 https://www.cnblogs.com/fanshuyao/ import ...
- java 日期格式化
DateFormat DateFormat 是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间. SimpleDateFormat SimpleDateFormat 是一个以与 ...
- java日期格式化(util包下转成sql包下)
package test; import java.text.SimpleDateFormat;import java.util.Date;import java.util.Scanner; publ ...
随机推荐
- RFID基础——高频RFID协议、读写模块和标签
RFID技术中的低频.高频.超高频有各自的优点和应用场景.其中,与我们个人生活息息相关的门禁卡.公交卡.身份证.图书标签主要用到的是高频RFID.这些应用也对应着高频RFID中不同的协议. 高频RFI ...
- V-Control:一个基于 .NET MAUI 的开箱即用的UI组件库
前言 今天大姚给大家分享一个基于 .NET MAUI 的开源免费.开箱即用的UI组件库:V-Control. V-Control项目介绍 V-Control 是一个适用于 .NET MAUI 的开源( ...
- C# OpenMP
在C#中实现代码优化,并行的方式来提升速度. 参考链接:https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/ho ...
- led色块是什么,bin指值是什么
色块其实就是色温的区域范围. LED的色温按标准是分段的, 既然是分段,就有一个最大值和最小值,在色坐标系中是一个,X和Y的坐标对应的也就有一个最大值和最小值,这样一个色温段就是以小块的区域,即所谓的 ...
- Hive - 表相关
一.文件存储格式 Hive的文件存储格式包括:textfile.sequence.rcfile.orc.parquet textfile (简介)默认的文件格式,基于行存储.建表时不指定存储格式即为t ...
- C#之 Dictionary 详解
基本概念 Dictionary<TKey, TValue>是C#中用于存储键值对集合的泛型类,属于System.Collections.Generic命名空间.它允许使用键(Key)来访问 ...
- Abaqus-Steady-State-Dynamic-Analysis的求解原理
0. 总括 基于模态的谐响应分析,可以通过扫频的方式求解频率范围内结构的线性稳态响应情况.阻尼是和频率相关的,但模态叠加法只需要知道n个模态阻尼即可推广到其他频率范围(原因详见文内公式). 1. 谐响 ...
- ocr识别过程中报错 tesseract is not installed
这个问题无论在初始编译时或者在后来坏境变更调试时都会遇到的问题. 解决:问题原因是源码中的默认路径位置与文件位置不同,需要更改一下
- QWidget的isHidden和isVisible
文章目录 QWidget的isHidden和isVisible 问题的出现 QWidget的show()函数 QWidget的isVisible和isHidden 源码追溯 QWidget的isHid ...
- Go语言修改字符串
Go 语言的字符串无法直接修改每一个字符元素,只能通过重新构造新的字符串并赋值给原来的字符串变量实现.请参考下面的代码: angel := "Heros never die" an ...