在java.util.Date中pattern = ‘YYYY‘导致的bug

在java.util.Date中pattern = 'YYYY’导致的bug

今天在测试Date.setSeconds()函数时,发现有个bug,代码如下(这里有三个方法,主要用来实现String和Date类型的转换,以及通过秒数来更新Date):

/**字符串转Date对象**/
public static Date str2Date(String str) {

    //创建SimpleDateFormat对象实例并定义好转换格式
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date date = null;
    try {
        date = sdf.parse(str);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return date;
}

/**Date对象转字符串**/
public static String date2Str(Date date){
    //参考<https://www.cnblogs.com/zhengwanmeixiansen/p/7391411.html>
    SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss"); //注意使用yyyy,而不是YYYY
    String form = sdf.format(date);
    return  form;
}

/**通过当前时间startT和秒数duration,得到结束时间endT, duration可取任意值**/
public static Date getEndT(Date startT, int duration){

    int second = startT.getSeconds();

    int temp = second + duration;  //原始秒 + 持续时间

    Date endT = Utils.Dateclone(startT);  //深拷贝
    endT.setSeconds(temp);  //更新日期(会自动进位,不用自己处理)

    return endT;
}

结果在运行时,日期出错了

date = Utils.str2Date("2021-12-27 00:05:38"); //2022-12-27 00:12:18计算出错
//date = Utils.str2Date("2021-05-31 23:58:38"); //2021-06-01 00:05:18计算正确
endT = Utils.getEndT(date,400);
System.out.println(Utils.date2Str(endT));

会发现,每到跨年前几天,就会出错(!!!),主要原因如下:

参考官方文档,

https://www.oracle.com/technetwork/cn/java/javase/documentation/api-jsp-136079-zhs.html

jdk6的SimpleDateFormat只有"y",没有"Y"

dk7和8,甚至jdk9(https://docs.oracle.com/javase/9/docs/api/java/text/SimpleDateFormat.html),除了“y”,引入了"Y",“Y”表示Week year

YYYY是week-based-year,表示:当天所在的周属于的年份,一周从周日开始,周六结束,只要本周跨年,那么这周就算入下一年。所以2019年12月31日那天在这种表述方式下就已经 2020 年了。一定要用小写的yyyy来显示年份

在任何编程语言中,对于时间、数字等数据上,都存在很多类似这种平时一切OK,特定时间、特定环境出问题的情况。出现这种问题的根本原因还是我们对于各种数据结构的细节定义在开始的时候都不太注意,都是从每一次使用问题出现之后才开始有了“刻骨铭心”的认识。

参考资料

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值