关于时间大小判断的坑和网上工具类的看法

 

关于时间大小判断的坑和网上工具类的看法

 

  1. 问题描述

    昨晚OA上线后,今早一来就出了问题,大量的用户反馈,OA中月度目标模块中,无法添加月度目标,一点击提交就出现提示:"月度目标的截止日期必须是本月份的日期!",我也很郁闷,最开始定位问题的时候,我认为是前端传递的年份和月份传递错了,后来发现是时间校验的工具类出了问题,这个问题隐藏很深,经过了N久都没有被发现,今天碰巧出了问题,为此还冤枉了一个前端妹子,好无辜。。。。

     

    该工具类的作用是:传递给它年份和月份两个参数,就返回给你当前月份的开始时间和结束时间。

     

    具体代码如下:网上拷贝的

    /**

     * 根据指定日期和月份来获取该月份的开始时间

     * @author zc

     * @date 2017830 下午1:56:02

     * @param time

     * @param month

     * @return

     */

    public static String getMonthStartDate(String time, int month) {

        String year = time.substring(0, 4);

        Calendar cal = Calendar.getInstance();

        cal.set(Calendar.YEAR, Integer.parseInt(year));

        cal.set(Calendar.MONTH, month - 1);

        Date time2 = cal.getTime();

        // 对时间进行格式化

        String str = DateUtil.formatTimestamp(time2, DateUtil.YMDHM);

        // 根据指定日期,获取其日期的月初开始时间

        return DateUtil.getStartMonth(str);    

}

 

 

 

    /**

     * 根据指定日期和月份来获取该月份的结束时间

     * @author zc

     * @date 2017830 下午1:56:02

     * @param time yyyy-MM-dd HH:mm

     * @param month

     * @return

     */

    public static String getMonthEndDate(String time, int month) {

        String year = time.substring(0, 4);

        Calendar cal = Calendar.getInstance();

        cal.set(Calendar.YEAR, Integer.parseInt(year));

        cal.set(Calendar.MONTH, month - 1);

        Date time2 = cal.getTime();

        // 对时间进行格式化

        String str = DateUtil.formatTimestamp(time2, DateUtil.YMDHM);

        // 根据指定日期,获取其日期的月底结束时间

        return DateUtil.getEndMonth(str);

}

内心的OS呐喊:

问题出了以后,定位了问题,不是在前端,而是时间校验的工具类出了问题,虽然知道了是工具类的问题,纠结了半天,依旧不知所措,同事过来帮忙看,也没有看出是哪里有问题,然后同桌突然说了一句,这个坑我踩过,靠,不早点说。

 

粗略看了一下,上面的代码好像没有什么问题,但是真的没有问题吗?咱们一起来走一下!

 

我们开始调用工具类:根据传入的年份和月份,获取当前月份的开始时间为例,来演示一下。

方法入参:time = "2018" , month = "06"

调用方法名:String getMonthEndDate(String time, int month)

这里开始分析方法:

 

    /**

     * 根据指定日期和月份来获取该月份的开始时间

     * @author zc

     * @date 2017830 下午1:56:02

     * @param time

     * @param month

     * @return

     */

    public static String getMonthStartDate(String time, int month) {

        // 传入参数为 2018 06

        String year = time.substring(0, 4);

        // 1. 获取系统当前的时间:2018531 11:32:27

        Calendar cal = Calendar.getInstance();

        // 2. 重新设置年份为:2018 此时时间为:2018531 11:32:27

        cal.set(Calendar.YEAR, Integer.parseInt(year));

        // 3. 重新设置月份为:06 此时时间为:2018631 11:32:27 ,重点

        cal.set(Calendar.MONTH, month - 1);

        // 4. 然后获取时间戳,此时的时间戳为:"2018631 11:32:27"这个日期的时间戳

        Date time2 = cal.getTime();

        // 5. 对时间进行格式化

        String str = DateUtil.formatTimestamp(time2, DateUtil.YMDHM);

        // 6. 根据指定日期,获取其日期的月初开始时间

        return DateUtil.getStartMonth(str);

    }

 

分析:

第一步:获取系统当前的时间,这里应该没有问题 2018531 11:32:27

第二步:把当前时间的年份,设置为2018年,这里也没有问题

第三步:把当前时间的月份,设置为06月,有问题了2018631 11:32:27

6月份只有30天,并没有31

第四步:获取变更后日期的时间戳:是获取:" 2018631 11:32:27

"这个日期的时间戳

第五步:此时时间戳转换为对应的日期为:" " 2018701 11:32:27", 你的眼睛没有看错,就是71号,631号,比起正常的6月份,多了一天,然后这个多了的一天,就加到7月份去了,所以就是71号。

 

吃瓜群众看到这里,应该可以发现,是年月日,当中的"日期"出了问题,也就是31号,既然知道了问题,只需要重新设置下当前的时间的号,就可以了,也就是说,不管当前的时间是多少号,统一设置为1号,就愉快的解决了。

代码如下,看红色代码部分,就Ko

 

    public static String getMonthStartDate(String time, int month) {

        // 传入参数为 2018 06

        String year = time.substring(0, 4);

        // 1. 获取系统当前的时间:2018531 11:32:27

        Calendar cal = Calendar.getInstance();

        // 重新设置下当前时间的号,就可以了

        cal.set(Calendar.DAY_OF_MONTH, 1);

        // 2. 重新设置年份为:2018 此时时间为:2018531 11:32:27

        cal.set(Calendar.YEAR, Integer.parseInt(year));

        // 3. 重新设置月份为:06 此时时间为:2018631 11:32:27 ,重点

        cal.set(Calendar.MONTH, month - 1);

        // 4. 然后获取时间戳,此时的时间戳为:"2018631 11:32:27"这个日期的时间戳

        Date time2 = cal.getTime();

        // 5. 对时间进行格式化

        String str = DateUtil.formatTimestamp(time2, DateUtil.YMDHM);

        // 6. 根据指定日期,获取其日期的月初开始时间

        return DateUtil.getStartMonth(str);

    }

 

血泪的教训,在这里记录一下。同时也说明了一个问题,在一般的开发情况下,我们没有过多的时间去编写乱大街的工具类,码农都懂的,工期很紧,所以正常的情况下都是直接从网上拷贝下来的,然后自己简单测试下,通过了就直接使用了。没有过多的去猜想。

 

 

二、关于工具类的一些想法

 

  1. 通用的工具类到底是拷贝网上的,还是自己写?
    1. 自己编写的:没有质量保证(需要看开发者水平),以及运行效率上面有差异。
    2. 网上拷贝的:有质量保障(我这次就被坑了,笑哭),效率高,经过了时间的检测。

 

 

结论:无论是自己编写的,还是网上拷贝的,一定需要经过充分、全面的测试,以及研读,符合项目的需要,才能纳入到项目的工具库中,不然坑了自己,也坑了项目组的人

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2018-06-04 11:27  runningto  阅读(344)  评论(0编辑  收藏  举报