日期格式‘YYYY-MM-DD’中的BUG

2023-11-10

1. 日期格式

先来看一下日期格式主要有下面三种,US style,Euro style,RFC 3389。

Layout                      Format string    Example
------------------------    -------------    ----------
US style (Dec 29, 2019)     MM/DD/YYYY       12/29/2019
Euro style (29 Dec 2019)    DD/MM/YYYY       29/12/2019
RFC 3339 (2019-12-29)       YYYY-MM-DD       2019-12-29

2. 时间转换类

开发中,我们经常需要将时间进行转换成我们需要的格式,我们可以使用JDK8提供的一个DateTimeFormatter类来完成对日期的转换,如下面的代码:

public class CarefulWithThatDateEugene {
    private static void tryit(int Y, int M, int D, String pat) {
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pat);
        LocalDate dat = LocalDate.of(Y, M, D);
        String str = fmt.format(dat);
        System.out.printf("Y=%04d M=%02d D=%02d " +
                "formatted with " +
                "\"%s\" -> %s\n", Y, M, D, pat, str);
    }

    public static void main(String[] args) {
        tryit(2020, 01, 20, "MM/DD/YYYY");
        tryit(2020, 01, 21, "DD/MM/YYYY");
        tryit(2020, 01, 22, "YYYY-MM-DD");
    }
}

上面的代码执行之后,可以完美的输出:

Y=2020 M=01 D=20 formatted with "MM/DD/YYYY" -> 01/20/2020
Y=2020 M=01 D=21 formatted with "DD/MM/YYYY" -> 21/01/2020
Y=2020 M=01 D=22 formatted with "YYYY-MM-DD" -> 2020-01-22

2.1 错误的DD

但是如果我们执行下面的代码去测试:

tryit(2020,05,17,"MM/DD/YYYY");
tryit(2020,05,18,"DD/MM/YYYY");
tryit(2020,05,19,"YYYY-MM-DD");

你会发现控制台会抛出异常

Exception in thread "main" java.time.DateTimeException: Field DayOfYear cannot be printed as the value 138 exceeds the maximum print width of 2
	at java.time.format.DateTimeFormatterBuilder$NumberPrinterParser.format(DateTimeFormatterBuilder.java:2548)
	at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2179)
	at java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1746)
	at java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1720)
	at com.liuyao.time.CarefulWithThatDateEugene.tryit(CarefulWithThatDateEugene.java:15)
	at com.liuyao.time.CarefulWithThatDateEugene.main(CarefulWithThatDateEugene.java:26)

提示说Day的值为138,超过了日期的最大长度2,为什么日期会变成138呢,如果我们不管异常,输出的结果将会是:

Y=2020 M=05 D=17 formatted with "MM/DD/YYYY" -> 05/138/2020
Y=2020 M=05 D=18 formatted with "DD/MM/YYYY" -> 139/05/2020
Y=2020 M=05 D=19 formatted with "YYYY-MM-DD" -> 2020-05-140

可见日期都不对了,因为 DD代表的并不是一个月的某一天,而是一年的某一天,所以才会出现138超过31的值。

所以我们应该使用 dd来转换日期。

2.2 错误的YYYY

然后继续执行代码:

tryit(2018,12,30,"YYYY-MM-dd");
tryit(2018,12,31,"YYYY-MM-dd");
tryit(2019,01,01,"YYYY-MM-dd");

输出的结果是:

Y=2018 M=12 D=30 formatted with "YYYY-MM-dd" -> 2019-12-30
Y=2018 M=12 D=31 formatted with "YYYY-MM-dd" -> 2019-12-31
Y=2019 M=01 D=01 formatted with "YYYY-MM-dd" -> 2019-01-01

可见前面两个的2018年变成了2019年,年份变了。

这是为什么呢?因为YYYY使用的基于周的年份,而不是基于天数的,会计人员可以使用 YYYY来避免两年的日期分割,从而方便的计算工资等, 它的转换采用下面的规则:

  • The first day of every week is Monday.(每周的第一天是星期一)
  • If a week is split at the end of the year then it is assigned to the year in which more that half of the days of that week occur.(如果一个星期在年底被分割,那么它被分配到一年中超过一半的一个星期发生)

由于上面第二条的限制:

Sun 2015-12-27  -> Payroll week 52 of 2015

Mon 2015-12-28  -> Payroll week 53 of 2015 
Tue 2015-12-29  -> Payroll week 53 of 2015 
Wed 2015-12-30  -> Payroll week 53 of 2015
Thu 2015-12-31  -> Payroll week 53 of 2015 
-------------NEW YEAR---------------------
Fri 2016-01-01  -> Payroll week 53 of 2015
Sat 2016-01-02  -> Payroll week 53 of 2015
Sun 2016-01-03  -> Payroll week 53 of 2015

Mon 2016-01-04  -> Payroll week 01 of 2016

2015年,第52周之后还剩下四天,因此2016年的前三天被“放到”到2015年的工资单中。

但在2025年,情况刚好相反,到2025年底只剩下三天时间,就会被“放进”到2026年的工资单年份

Sun 2025-12-28  -> Payroll week 52 of 2025 
 
Mon 2025-12-29  -> Payroll week 01 of 2026 
Tue 2025-12-30  -> Payroll week 01 of 2026 
Wed 2025-12-31  -> Payroll week 01 of 2026 
-------------NEW YEAR---------------------
Thu 2026-01-01  -> Payroll week 01 of 2026 
Fri 2026-01-02  -> Payroll week 01 of 2026 
Sat 2026-01-03  -> Payroll week 01 of 2026 
Sun 2026-01-04  -> Payroll week 01 of 2026
 
Mon 2026-01-05  -> Payroll week 02 of 2026 

所以你如果采用的是 YYYY来格式化的年份,那么你讲不可避免的会在一年的结束或者一年的开始遇到这个问题,除非某年的第一天刚好是星期一,这样ISO-8601就会把日期分割的刚刚好。

下面就是活生生的例子:

在这里插入图片描述

3. 正确使用

采用 DD来格式化代码,你会很容易发现这个错误,因为一年有85%的时间都是错误的,但是你如果采用了 YYYY这个错误的 格式来格式年份,一年中只有1%的时间是错误的,而且这个错误还不是每7年就会出现一次的。

  • 正确的格式化ISO-8601模板为: yyyy-MM-dd HH:mm:ss

  • 正确的UTC的时间模板为 yyyy-MM-dd'T'HH:mm:ss.SSSXXX

4. 参考链接

  1. Serious Security: The decade-ending “Y2K bug” that wasn’t
  2. DateTimeFormatter
  3. 你今天因为 YYYY-MM-dd 被提 BUG 了吗

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

日期格式‘YYYY-MM-DD’中的BUG 的相关文章

  • mac上使用IntelliJ IDEA运行项目

    一 Mac OSX系统下安装Tomcat 1 下载Tomcat官方下载地址 2 解压Tomcat到目录 Library 中 并把文件夹名由 apache tomcat 6 0 16 改为 Tomcat 3 打开 应用程序 Applicati
  • mysql如何一秒插入10万条数据

    当我们需要批量插入或者更新记录时 可以采用Java的批量更新机制 该机制允许多条语句甚至一次性提交给数据库处理 通常情况下比一句一提交处理更有效率 jdbc处理批量提交有三个方法 需要注意的是 这三种方法都要和PreparedStateme
  • 集合addAll方法使用存在的问题。

    集合addAll 方法的时候 这里里有两个集合 集合2要拿到集合1中的元素 然后对集合2进行removeAll方法 结果集合1中的值也没有了 只是因为listTwo listOne 只是把集合1的引用给了集合2 集合1和集合2的引用是指向同
  • FullGC问题分析

    一 常见的FullGC场景分析 频繁的大对象 大对象直接被分配到老年代 系统高负载运行 请求量很大 jvm来不及将对象转移到老年代 直接到老年代分配对象 系统内存泄漏 导致对象长时间在老年代 得不到释放 二 产生FullGC的原因 Syst
  • java Map集合

    目录 一 介绍 二 HashMap 三 TreeMap 四 LinkedHashMap 一 介绍 Java中的Map是一种键值对的集合数据类型 用于存储无序的 不重复的键值对 它提供了快速的查找和访问功能 可以根据键来获取值 常见的Map实
  • Java中的IO流如何理解——精简

    目录 引言 缓冲流 字节缓冲流 字符缓冲流 转换流 字符输入转换流 字符输出转换流 序列化和反序列化 对象序列化 对象反序列化 打印流 Properties 引言 通过前面的简单学习 我们已经能够大致了解了关于文件的操作 但是能够明显感受到
  • 一文彻底弄懂零拷贝原理

    零拷贝 零拷贝 Zero Copy 是一种 I O 操作优化技术 可以快速高效地将数据从文件系统移动到网络接口 而不需要将其从内核空间复制到用户空间 其在 FTP 或者 HTTP 等协议中可以显著地提升性能 但是需要注意的是 并不是所有的操
  • [透彻]为什么要前后端分离?

    前后端分离的意义 前后端分离 已成为互联网项目开发的业界标准使用方式 前后端分离 会为以后的大型分布式架构 弹性计算架构 微服务架构打下坚实的基础 核心思想 前端页面调用后端的restuful api接口 并使用json数据进行交互 服务器
  • JAVA,异常

    异常概念 通常大家认为异常就是错误 但这个错误有很多种 1 语法错误 2 JVM虚拟机错误 3 平台错误 4 程序运行错误 平台或者资源或者逻辑 数值等错误 常见的异常 1 java lang NullPointerException 空指
  • 解释执行与编译执行语言有什么区别?

    一 主体不同 1 编译执行 由编译程序将目标代码一次性编译成目标程序 再由机器运行目标程序 2 解释执行 将源语言直接作为源程序输入 解释执行 解释一句后就提交计算机执行一句 并不形成目标程序 二 优势不同 1 编译执行 相比解释执行编译执
  • 第一个java程序helloworld代码的编写

    第一个java程序helloworld代码的编写 文章目录 第一个java程序helloworld代码的编写 toc 一 项目 二 认识JVM JRE和JDK 2 1 JVM是什么 2 2 JVM的主要功能和作用 2 3 JRE和JDK J
  • 对接百度api的工具类:Base64Util,FileUtil,HttpUtil

    对接百度api的工具类 Base64Util FileUtil HttpUtil package com baidu ai aip utils Base64 工具类 public class Base64Util private stati
  • java 模拟库存管理系统

    本案例要求编写一个程序 模拟库存管理系统 该系统内容主要包括 商品入库 商品显示 和删除商品功能 此程序用手机举例 此管理系统分别为两个类Phone 和Test类 Phone类 确定四个变量 类 1 生成空参数构造方法 2 全部参数的构造方
  • jeecgboot问题解决方案

    常见问题Q A JEECG老版在线文档 点击进入 1 后台访问提示token错误 报错截图 解决方案 JeecgBoot后台的所有请求访问 增加了token机制 所以不能直接访问后台 而需要通过前台登录才能访问 默认前台访问地址 http
  • AQS底层原理

    1 AQS能干嘛 是什么 能干嘛 加锁就会有阻塞 有阻塞就需要排队 实现排队必然需要有某种形式的队列来进行管理 是什么 废话 抽象的队列同步器 翻译一下 AQS是用来构建锁或者其它同步器组件的重量级基础框架及整个JUC体系的基石 通过内置的
  • 多线程下载文件(支持暂停、取消、断点续传)

    多线程下载文件 支持暂停 取消 断点续传 多线程同时下载文件即 在同一时间内通过多个线程对同一个请求地址发起多个请求 将需要下载的数据分割成多个部分 同时下载 每个线程只负责下载其中的一部分 最后将每一个线程下载的部分组装起来即可 涉及的知
  • 如何做单元测试

    如何做单元测试 一 定义 二 为什么要做单元测试 三 单元测试用例 四 阿里单元测试规约 五 测试框架的使用 Junit 下面以Junit4 为例来介绍 1 1 什么是Junit 1 2 为何使用Junit 1 3 Junit的快速入门 导
  • java基础之HashSet详解

    HashSet详解 HashSet是基于HashMap实现的一个单列存储的集合类 将所有的数据存在HashMap的key值中 而value全部使用一个Object对象存储 继承关系 public class HashSet
  • mysql无法连接问题及其环境变量配置

    问题 Can t connect to MySQL server on localhost 3306 10061 方案一 不推荐 第一 在环境变量 系统变量的path中添加mysql的bin目录 我的是D mysql mysql 8 0 2
  • 详解toLowerCase(判断字符串相等)

    一 toLowerCase 函数简介 toLowerCase 是一个在多个编程语言中都存在的字符串方法 它的作用是将字符串中的所有大写字母转换为对应的小写字母 常用于文本处理 搜索和比较等情况 以确保字符串的一致性和非大小写敏感的操作 二

随机推荐

  • ​在可视化大屏中轻松完成机器学习建模和调参应用实例

    Streamlit 是一个开源 Python 库 可帮助开发人员为其系统创建交互式图形用户界面 它专为机器学习和数据科学家团队设计 使用 Streamlit 我们可以快速创建交互式 Web 应用程序并进行部署 前端工作对数据科学家来说并不重
  • 互联网生活中的隐私保护:用隐私换便利还是花钱护隐私?

    近日 某高校毕业生在校期间窃取学校内网数据 收集全校学生个人隐私信息的新闻引发了人们对互联网生活中个人信息安全问题的再度关注 在大数据时代 算法分发带来了隐私侵犯 在享受消费生活等便捷权利的同时 似乎又有不少个人信息泄露的担忧 用隐私换便利
  • 【华为OD统一考试A卷

    华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一修改为OD统一考试 A卷 和OD统一考试 B卷 你收到的链接上面会标注A卷还是B卷 请注意 根据反馈 目前大部分收到的都是
  • Python 函数的说明文档

    视频版教程 Python3零基础7天入门实战视频教程 用 备注说明 然后我们调用函数的地方 鼠标移动上去就能看到函数的说明 提供代码的可读性 def add x y 两数相加函数 param x 两数相加数x param y 两数相加数y
  • matlab中Img(:,:,n)函数的说明

    Img n 中 n可以取1 2 3分别代表img图像的第1 2 3通道 即对应着R G B三种颜色 也就是说 Img 1 是红色分量图像 Img 2 是绿色分量图像 Img 3 是蓝色分量图像 具体也可通过如下一段函数定义可以看出 img
  • zabbix使用手册

    1 添加主机组 将多个主机合并在一个逻辑组件内即为主机组 分组的目的是将同一属性的主机归类 方 便以后管理 例如以业务指标划分组 以系统版本划分组 以应用程序划分组等 主机组中可以包含主机 也可以包含模板 进入zabbix管理界面 单击 配
  • 手把手教你运行yolov6 (小白版教程)

    一 yolov6的介绍 二 yolov6的吐槽 三 yolov6运行详解 前言 自己运行yolov6的完整教程 一 yolov6的介绍 我在此应用美团视觉部官方的说法叙述一下yolov6 YOLOv6 是美团视觉智能部研发的一款目标检测框架
  • 【Linux】VMware安装unbuntu18.04虚拟机-超详细步骤(附镜像文件)

    这次为大家带来的是在VMware创建的虚拟机上安装ubuntu18 04桌面版系统 ubuntu18 04也是目前比较流行的一个linux系统版本 接下来就一起来实操吧 文章目录 一 环境准备 二 创建虚拟机 三 安装虚拟机 一 环境准备
  • 包、模块、函数

    包 模块 函数 一 while循环与使用场景 1 while循环 counter 1 while counter lt 10 counter 1 print counter else print EOF 运行结果 2 3 4 5 6 7 8
  • 邮件发送原理和实现

    邮件发送 拓展 MIME 多用途互联网邮件扩展类型 就是附件 1 准备工作 获取QQ邮箱权限 测试代码 package com jyw import com sun mail util MailSSLSocketFactory import
  • wifi名称可以有空格吗_是真的吗?WiFi名称后面带“5G”,网速会更快?

    要想体验快到飞起的千兆网速 感受全屋覆盖的满分信号 移动全千兆 你值得拥有 千兆5G 无论是旅途中紧急处理工作 文件 图片秒传秒下 还是在外时与家人视频问候 无卡顿低延迟 用千兆5G 网速始终快人一步 千兆宽带 品质生活从品质宽带开始 用千
  • AcWing--756. 蛇形矩阵

    输入两个整数 n 和 m 输出一个 n 行 m 列的矩阵 将数字 1 到 n m 按照回字蛇形填充至矩阵中 具体矩阵形式可参考样例 输入格式 输入共一行 包含两个整数 n 和 m 输出格式 输出满足要求的矩阵 矩阵占 n 行 每行包含 m
  • Linux——使用第三方库链接的方式——动态式

    回顾上文 122条消息 Linux使用第三方库链接的使用方式 静态式 橙予清的zzz 的博客 CSDN博客https blog csdn net weixin 69283129 article details 131414804 spm 1
  • 【qiankun】微前端在项目中的具体使用

    1 安装qiankun npm install qiankun save 2 主应用中注册和配置qiankun 在主应用的入口文件main ts中 引入qiankun的注册方法 import registerMicroApps start
  • java/php/net/python健身房管理系统设计

    本系统带文档lw万字以上 答辩PPT 查重 如果这个题目不合适 可以去我上传的资源里面找题目 找不到的话 评论留下题目 或者站内私信我 有时间看到机会给您发 系统设计 4 1 系统体系结构 健身房管理系统的结构图4 1所示
  • mysql localhost值_jdbc:mysql://localhost:3306/mysql这句话中localhost具体指什么的localhost?能修改么?在哪里配置的?...

    展开全部 jdbc mysql 是指JDBC连接方式 localhost 是指你的本机地址 3306 SQL数据库的端口 jdbc 就是你要连接的32313133353236313431303231363533e59b9ee7ad94313
  • Mysql 8.0修改密码

    1 mysql u root p 原来的密码 进入数据库中 2 show databases 3 use mysql 4 使用下面的语句修改密码 ALTER USER root localhost IDENTIFIED WITH mysql
  • 驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接

    驱动程序无法通过使用安全套接字层 SSL 加密与 SQL Server 建立安全连接 错误 The server selected protocol version TLS10 is not accepted by client prefe
  • STM32初始化结构体变量时成员排序的问题

    平台 STM32F103RCT6 MDK 笔者在调试时发现 结构体不同类型成员的定义顺序对于程序运行过程中的取值可能会产生很大的BUG 开始时定义 输入参数结构体 typedef struct u8 TempRange 温度最大值 floa
  • 日期格式‘YYYY-MM-DD’中的BUG

    1 日期格式 先来看一下日期格式主要有下面三种 US style Euro style RFC 3389 Layout Format string Example US style Dec 29 2019 MM DD YYYY 12 29