2020年来临之前,日期格式化操作也为程序员准备了一个跨年级别的bug,不知你的系统是否遇到?

临近2020年元旦的几天,不少网站出现了类似2020/12/29,2020/12/30,2020/12/31这样的日期显示。神奇不?就连微信的提供的订阅号助手工具都出现了这样的错误。

下面两张图是本公众号“程序新视界”在12月31日订阅号助手助手中的截图。

新增粉丝时间显示的部分内容。

评论区的时间显示的部分内容。

上图中,新增粉丝显示的时间和评论的时间均为“2020/12/31”。那么,下面我们就来分析一下出现此bug的原因。实例胜千言,先用示例还原一下此bug。

示例一,还原示例:

public class DateFormatBug {

	public static void main(String[] args) throws ParseException {
// 示例一
printBugDate();
} private static void printBugDate() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
Date date = sdf.parse("2020-1-1 13:12:12");
System.out.println(date);
String dateStr = sdf.format(date);
System.out.println(dateStr);
}
}

猜猜第一行和第二行打印的结果分别是什么?如果猜对一个说明很聪明,因为上面已经说了,此实例为还原bug。

打印日志为:

Sun Dec 29 13:12:12 CST 2019
2020-12-29 13:12:12

神奇不?把字符串“2020-1-1 13:12:12”解析成日期打印出来竟然成2019年12月29日了!!!然后再对日期进行处理竟然变成2020-12-29日了!彻底乱套了,我们想要的是2020-1-1的日期啊。

示例二,延伸示例:

private static void printBugDateExtend() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
Date date = sdf.parse("2019-12-31 13:12:12");
System.out.println(date);
String dateStr = sdf.format(date);
System.out.println(dateStr);
}

这次只是把日期从2020-1-1改为2019-12-31,猜猜打印结果是什么?保证你猜不到。下面是打印结果:

Sun Dec 30 13:12:12 CST 2018
2019-12-30 13:12:12

2018年12月30?这次连年份都错了。

好了,不卖关子了,如果你的IDE上安装的有阿里巴巴操作规范手册的插件。你会发现“YYYY-MM-dd HH:mm:ss”上面已经有提示信息了。同样,如果你打开新版(华山版)阿里巴巴Java开发手册,对此问题已经进行了明确的说明了。

那么,哪里可以获得新版的《阿里巴巴Java开发手册》?关注公众号“程序新视界”的朋友,只需回复“005”即可获得PDF版本。新的一年,没事看看大厂的开发手册,借鉴一下经验,避免踩坑也是不错的。当然,关注公众号持续学习也是另外一种不错的选择。

同时,也可参看javadoc中对week-based-year的说明,相关链接如下:https://docs.oracle.com/javase/8/docs/api/java/time/temporal/WeekFields.html

A week is defined by:

(1) The first day-of-week. For example, the ISO-8601 standard considers Monday to be the first day-of-week.

(2) The minimal number of days in the first week. For example, the ISO-8601 standard counts the first week as needing at least 4 days.

Together these two values allow a year or month to be divided into weeks.

总结一下就是:在基于周的年份中,每周仅属于某一年。一年中的第1周要求从一周的第一天开始,并且天数要大于4天(the minimum number of days),所以跨年周具体是哪一年还得看具体情况。

不过无论怎样,最好的方法就是避免使用大写的“Y”来代表年份。

尽信书不如无书,我们将代码中“Y”修改为“y”,再执行一遍看看效果。

private static void printDate() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse("2020-1-1 13:12:12");
System.out.println(date);
String dateStr = sdf.format(date);
System.out.println(dateStr);
} private static void printDateExtend() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse("2019-12-31 13:12:12");
System.out.println(date);
String dateStr = sdf.format(date);
System.out.println(dateStr);
}

打印结果显示如下:

Wed Jan 01 13:12:12 CST 2020
2020-01-01 13:12:12
Tue Dec 31 13:12:12 CST 2019
2019-12-31 13:12:12

很显然,这个跨年bug被修复了。

经过这个问题,我们是否会思考一个问题:高手与新手的差不在哪里?或许上面的问题就能够回答,同样是日期格式化,在正常情况下两种写法都可正常运行,无法区分高手与新手。而只有在某时某刻某些极端情况下才能看出高手之高。

那么高手是从哪里来的?是从坑中跳出来的。或许他比你早掉进去早出来了,或许他博览群书有那么一次“不期而遇”,也或许就是像你现在一样看到这篇文章。

原文链接:《跨年bug,是否与你不期而遇?

程序新视界:精彩和成长都不容错过
![程序新视界-微信公众号](https://img2018.cnblogs.com/blog/1742867/201910/1742867-20191013111755842-2090947098.png)

日期格式化跨年bug,是否与你不期而遇?的更多相关文章

  1. Javascript 日期格式化 相关操作

    1.相关扩展函数 //--------------------------------------------------- // 判断闰年 //--------------------------- ...

  2. SQL 横转竖 、竖专横 (转载) 使用Dapper.Contrib 开发.net core程序,兼容多种数据库 C# 读取PDF多级书签 Json.net日期格式化设置 ASPNET 下载共享文件 ASPNET 文件批量下载 递归,循环,尾递归 利用IDisposable接口构建包含非托管资源对象 《.NET 进阶指南》读书笔记2------定义不可改变类型

    SQL 横转竖 .竖专横 (转载)   普通行列转换 问题:假设有张学生成绩表(tb)如下: 姓名 课程 分数 张三 语文 74 张三 数学 83 张三 物理 93 李四 语文 74 李四 数学 84 ...

  3. Java日期格式化带来的年份不正确

    BUG现场 一个线上项目之前一直运行得很稳定,从没出过数据错误的问题,但是在2021.12.26这天却"意外"地出现了数据计算错误. 刚开始一头雾水,不知道是什么问题,后来经过日志 ...

  4. C# DateTime日期格式化

    在C#中DateTime是一个包含日期.时间的类型,此类型通过ToString()转换为字符串时,可根据传入给Tostring()的参数转换为多种字符串格式. 目录 1. 分类 2. 制式类型 3. ...

  5. Json.net日期格式化

    1. 全局设置,可以在App_Global中配置 JsonSerializerSettings setting = new JsonSerializerSettings(); JsonConvert. ...

  6. 分享自己写的JS版日期格式化和解析工具类,绝对好用!

    前言 本来想模仿Java里面的SimpleDateFormat()对象的,但是感觉这样用起来不方便,所以还是直接写成单独的方法算了. 原文链接 日期格式化 使用说明 formatDate(date, ...

  7. Oracle 英文 非标准格式 日期 格式化

    最近在处理一张表的时候,需要按照日期排序,日期字段中日期的格式有两种. 格式一:07-Aug-2015 格式二:10/28/16 日期转化及格式化sql语句: select to_date('07-A ...

  8. Sql Server 日期格式化函数

    Sql Server 中一个非常强大的日期格式化函数Select CONVERT(varchar(100), GETDATE(), 0): 05 16 2006 10:57AMSelect CONVE ...

  9. django 过滤器、日日期格式化参数

    转载:http://blog.csdn.net/xyp84/article/details/7945094 django1.4 html页面从数据库中读出DateTimeField字段时,显示的时间格 ...

随机推荐

  1. Class.forName(“com.mysql.jdbc.Driver”)

    传统的使用jdbc来访问数据库的流程为: Class.forName(“com.mysql.jdbc.Driver”); String url = “jdbc:mysql://localhost:33 ...

  2. 9-1进程,进程池和socketserver

    一 进程: # 什么是进程 : 运行中的程序,计算机中最小的资源分配单位# 程序开始执行就会产生一个主进程# python中主进程里面启动一个进程 —— 子进程# 同时主进程也被称为父进程# 父子进程 ...

  3. 洛谷P1546 最短网络 Agri-Net(Prim堆优化)

    #include<bits/stdc++.h> using namespace std; ; const int INF=0x3f3f3f3f; inline void read(int ...

  4. VisualStudio 自定义外部命令

    通过自定义命令,可以在 VisualStudio 加上一些自定义命令,可以快速启动 git 或者做其他的事情 添加命令 首先打开工具 外部命令,点击添加,然后在弹出的窗口输入下面内容 例如添加内容是打 ...

  5. 54个提高PHP程序运行效率的方法

    1.在可以用file_get_contents替代file.fopen.feof.fgets等系列方法的情况下,尽量用 file_get_contents,因为他的效率高得多!但是要注意file_ge ...

  6. ArrayList存储基本类型时的封装类

  7. 列出display的值,说明他们的作用。position的值, relative和 absolute定位原点是?

    display的值: block 像块类型元素一样显示. none 像行内元素类型一样显示. inline-block 像行内元素一样显示, 但其内容像块类型元素一样显示. list-item 像块类 ...

  8. 基于jquery读取input上传的文件内容

    <script src="/static/js/jquery.js"></script> // 前端页面实现头像预览 // 当用户选中文件之后,也就是头像的 ...

  9. HDU 1072

    题意:给你一个迷宫,2代表你当前的位置,0代表墙,1代表可走的路,3代表出口,4代表的是炸弹的重置点,一开始炸弹的倒计时设置为6,每走一步时间减少1,倒计时到0的时候走到3或者4都不可以,问走出迷宫的 ...

  10. java面向接口编程之制定标准和简单工厂模式

    制定一个标准,让别人去实现或者说满足它! Eg: interface USB{//定义USB标准 void useUSB();//USB有使用USB的行为 } 简单工厂模式 构建一个工厂出来,在里面进 ...