坑在哪里:
在我之前接触的一个项目中涉及到这么一项功能:每天00:00:00把某些数据移动到mongodb数据库的另一个集合中,也就是关系型数据库的表中。这个集合名是一个固定的名称加上当前的两个月前的日期所在的年和月份。
这个功能是在我接触这个项目之前就已经存在,也就是之前的同事实现的功能,写了一个java的定时任务。
那个同事如今已经不在我们公司了,但是最近却发现这个功能有些问题,数据的移动并不像预计那样,原本应该存在2月的数据却出现在了1月的表中。
坑的根源:
mongodb相关的问题暂时归我维护,这个问题也自然而然需要我来解决,于是便把他的代码翻出来看了一遍。结果便发现了问题出在了calendar的相关方法上。
要转移两个月前的数据,首先要获取两个月前的日期,他的生成表名的相关代码是这样的:
private String getDataCollectionName() { Calendar calendar = Calendar.getInstance(); try { calendar.set(Calendar.DATE, -day); return "alarm_" + ToolUtils.dateToFormatStrDate(calendar.getTime(), "yyyy_MM"); } catch (Exception e) { logger.error("{}: data transformating failed,{}", this.getClass().getName(), e.getMessage()); } return null; }
问题正是出在calendar的set方法上,包括后来的查询数据使用的开始和结束时间,也一样用的是 calendar.set(Calendar.DATE, -day);
这个方法乍一看起来似乎就是设置日期为当前日期减去指定的天数,
但是实际上结果并不是想象中的这样得到两个月前的日期(这里的day它定义的是60,也就是两个月)。
填坑:
找到原因之后,我把这个方法进行了替换,把set改为了add,至于里边的参数没有去动,而结果证明这个方法才是真正能实现当前功能的,得到的结果也正是预想中的结果。
当然了,也可以不改方法的同时把参数略做改变,如
calendar.set(Calendar.DATE, calendar.get(calendar.DATE)-day);