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 ...
随机推荐
- Luogu P9869 NOIp2023 三值逻辑 题解 [ 绿 ] [ 带权并查集 ]
三值逻辑:有点坑并且细节较繁琐,但有点板子的并查集. 修改操作 发现对于每个点,只有对他的最后一次操作才是有用的,所以记录下最终的祖先即可. 然而这里并不能用并查集来实现,因为并查集它具有的是传递性, ...
- 初探ASP.NET Core 3.x (2) - ASP.NET Core与ASP.NET前世今生
本文地址:https://www.cnblogs.com/oberon-zjt0806/p/12210662.html 注意 本节是历史课,且绝大多数内容来自于百科或者其他的什么资料来源,如果不感兴趣 ...
- RFID基础——高频RFID协议、读写模块和标签
RFID技术中的低频.高频.超高频有各自的优点和应用场景.其中,与我们个人生活息息相关的门禁卡.公交卡.身份证.图书标签主要用到的是高频RFID.这些应用也对应着高频RFID中不同的协议. 高频RFI ...
- 燕千云ITSM已支持DeepSeek对接!AI能力持续升级
春节期间,DeepSeek火爆全网,引发热议,作为国产AI大模型的黑马,DeepSeek凭借独特的训练方法.先进的模型架构和强大的联网推理能力,正不断拓展AI技术的应用边界.其"快思考&qu ...
- linux的使用(2)
1,覆盖 > cat 文件名a>文件名b:将文档a覆盖文档b 2,追加 >> cat 文档名a>>文档名b:将文档a追加到文档b后 追加错误 上图所示:尽量使用字母 ...
- [BZOJ3600] 没有人的算术 题解
妙不可言!妙绝人寰! 单点修,区间查,包是线段树的.考虑如何比较两节点大小. 考虑二叉搜索树,我们只要再给每个节点附一个权值,就可以比较了! 注意力相当惊人的注意到,假如给每个点一个区间 \([l_x ...
- 使用selenium下载文件--设置下载文件自动保存文件夹
selenium自动下载文件到指定目录 本文参考:https://www.cnblogs.com/huxiaofeng1029/p/17383726.html 有时候,我们需要在网页中点击某些按钮,将 ...
- C# TCP/IP通信,Socket通信例子
1.服务端建立监听,等待客户端连接 class Program { static void Main(string[] args) { TcpListener listener = new TcpLi ...
- 如何利用 PostgreSQL 的 JSONB API 作为扩展的轻量级 JSON 解析器
前言 在基于 C 语言的 PostgreSQL 扩展开发中,您可能会遇到需要处理 JSON 等结构化数据的情况.通常,您可能会在扩展中引入第三方 JSON 解析库,例如 cJSON 或 libjans ...
- rsarsa-给定pqe求私钥对密文解密
题目: Math is cool! Use the RSA algorithm to decode the secret message, c, p, q, and e are parameters ...