背景
最近接到一个需求,做表结算(每月固定日期结算一次,类似抄表),需要对仪表数据进行补录(比如:钢厂电表坏了,做报表时需要把坏了这段时间消耗的电补录进去)。数据库有一张统计表,表中有字段开始时间,结束时间。现在补录数据也有个时段,现在需要把补录的数据结算到统计表中去。
分析
因为统计表中数据很多,不止存在一个表数据,还有各种水表气表等的结算数据。实现方案是按照用户所选择的表和时段进行补录。用户选择的时段可能和库中已有表数据存在交叉时段,也有可能不存在交叉。可是怎么求交叉呢?在网上找找查查自己修改一番然后适应了需求,下面直接上干货!!
解决方案
- 在库中找到是否与补录进来的数据存在时段交叉
- 补录数据拆分到分钟级别。value = diffSecond*miniteValue
1.在数据库查询有交叉时段的数据
mapper.java
SELECT xxxxx FROM energy_data_point_statistics WHERE data_code = #{dataCode}
and ((time_begin <![CDATA[ <= ]]> #{beginDate} and time_end >= #{endDate}) or (time_begin <![CDATA[ <= ]]> #{endDate} and time_end >= #{endDate})
or (time_begin >= #{beginDate} and time_end <![CDATA[ <= ]]> #{endDate}) or (time_begin <![CDATA[ <= ]]> #{beginDate} and time_end >=#{beginDate}))
此处,A-B,C-D两个时段包含情况
- 两段不相交
- 包含关系
- 相交
XxxserviceImpl.java–计算相交时间长度
/***
* @Author
* @Description 判断两个日期重合部分时间(单位 : 毫秒)
* @Date 2021/7/19 9:52
*/
public long countDateIntersection(String start1, String end1, String start2, String end2) {
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
long s1 = 0;
long s2 = 0;
long e1 = 0;
long e2 = 0;
try {
//标准化到1970-01-01
s1 = sdf2.parse(start1).getTime();
s2 = sdf2.parse(end1).getTime();
e1 = sdf2.parse(start2).getTime();
e2 = sdf2.parse(end2).getTime();
} catch (ParseException e) {
log.error("countDateIntersection--计算错误", e);
}
if (e1 >= s1 && e2 <= s2) {
//s1,s2时段包含e1,e2
return e2 - e1;
} else if (s1 >= e1 && e2 >= s2) {
//e1,e2时段包含s1,s2
return s2 - s1;
} else {
//两者时段相交
long ret = Math.min(s2, e2) - Math.max(s1, e1);
return ret < 0 ? 0 : ret;
}
}
思考和自测耗时久,回过头去思考也就那么也回事儿~
打完收工!
如有不对,希望大家多多斧正,留言交流!!