Commit 9820c96f681311c33d0f7b6a6810cb00871bbe03
1 parent
43458e11
定时检测超时任务
Showing
1 changed file
with
109 additions
and
62 deletions
src/main/java/com/order/erp/job/OrderOverTimeEventJob.java
1 | 1 | package com.order.erp.job; |
2 | 2 | import cn.hutool.core.bean.BeanUtil; |
3 | -import com.alibaba.fastjson.JSON; | |
4 | -import com.alibaba.fastjson.TypeReference; | |
3 | +import com.alibaba.fastjson.*; | |
5 | 4 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
6 | 5 | import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; |
7 | 6 | import com.order.erp.common.constant.Constant; |
8 | -import com.order.erp.common.utils.EmailSendUtils; | |
9 | -import com.order.erp.common.utils.RedisUtils; | |
10 | -import com.order.erp.common.utils.StringUtils; | |
11 | -import com.order.erp.common.utils.TransactionHelper; | |
7 | +import com.order.erp.common.utils.*; | |
12 | 8 | import com.order.erp.domain.EmailTemplateEnum; |
13 | 9 | import com.order.erp.domain.OrderEventEnum; |
14 | 10 | import com.order.erp.domain.dto.order.OrderBaseInfoDO; |
... | ... | @@ -25,10 +21,13 @@ import javax.annotation.Resource; |
25 | 21 | import javax.mail.MessagingException; |
26 | 22 | import java.io.IOException; |
27 | 23 | import java.time.LocalDate; |
24 | +import java.time.LocalDateTime; | |
28 | 25 | import java.time.format.DateTimeFormatter; |
29 | 26 | import java.time.temporal.ChronoUnit; |
30 | 27 | import java.util.*; |
31 | 28 | import java.util.function.Function; |
29 | +import java.util.regex.Matcher; | |
30 | +import java.util.regex.Pattern; | |
32 | 31 | import java.util.stream.Collectors; |
33 | 32 | |
34 | 33 | |
... | ... | @@ -70,22 +69,29 @@ public class OrderOverTimeEventJob { |
70 | 69 | @Resource |
71 | 70 | private RedisUtils redisUtils; |
72 | 71 | |
72 | + String dateFormatDay= com.order.erp.common.excel4j.utils.DateUtils.DATE_FORMAT_DAY; | |
73 | + String dateFormatSEC= com.order.erp.common.excel4j.utils.DateUtils.DATE_FORMAT_SEC; | |
74 | + | |
73 | 75 | /** |
74 | 76 | * 凌晨1点执行,一天一次 |
75 | 77 | */ |
76 | - @Scheduled(cron = "0 0 2 * * ?") | |
78 | + @Scheduled(cron = "0 0 1 * * ?") | |
79 | + //存储的日期都必须为yyyy-MM-dd HH:mm:ss。 | |
77 | 80 | public void checkOverTimeExecuteV2() throws MessagingException, TemplateException, IOException { |
78 | 81 | List<OrderBaseInfoDO> orderBaseInfoDOList = orderBaseInfoService.getEventList(); |
79 | - Set<Long> orderIds = orderBaseInfoDOList.stream().map(OrderBaseInfoDO::getId).collect(Collectors.toSet()); | |
80 | - List<OrderInspectionStageDO> orderInspectionStageDOList = inspectionStageService.list(new LambdaQueryWrapper<OrderInspectionStageDO>() | |
81 | - .in(OrderInspectionStageDO::getOrderId, orderIds)); | |
82 | - List<OrderTrackStageDO> orderTrackStageDOList = trackStageService.list(new LambdaQueryWrapper<OrderTrackStageDO>() | |
83 | - .in(OrderTrackStageDO::getOrderId, orderIds)); | |
84 | - List<OrderEventJobVO> jobVOList = transfer2OrderEventList(orderBaseInfoDOList, orderInspectionStageDOList, orderTrackStageDOList); | |
85 | - Map<String, List<OrderEventJobVO>> map = handlerOrderEvent(jobVOList); | |
86 | - for (Map.Entry<String, List<OrderEventJobVO>> entry : map.entrySet()) { | |
87 | - sendEmail4OrderEvent(OrderEventEnum.getEvent(entry.getKey()), entry.getValue()); | |
82 | + if(CollectionUtils.isNotEmpty(orderBaseInfoDOList)){ | |
83 | + Set<Long> orderIds = orderBaseInfoDOList.stream().map(OrderBaseInfoDO::getId).collect(Collectors.toSet()); | |
84 | + List<OrderInspectionStageDO> orderInspectionStageDOList = inspectionStageService.list(new LambdaQueryWrapper<OrderInspectionStageDO>() | |
85 | + .in(OrderInspectionStageDO::getOrderId, orderIds)); | |
86 | + List<OrderTrackStageDO> orderTrackStageDOList = trackStageService.list(new LambdaQueryWrapper<OrderTrackStageDO>() | |
87 | + .in(OrderTrackStageDO::getOrderId, orderIds)); | |
88 | + List<OrderEventJobVO> jobVOList = transfer2OrderEventList(orderBaseInfoDOList, orderInspectionStageDOList, orderTrackStageDOList); | |
89 | + Map<String, List<OrderEventJobVO>> map = handlerOrderEvent(jobVOList); | |
90 | + for (Map.Entry<String, List<OrderEventJobVO>> entry : map.entrySet()) { | |
91 | + sendEmail4OrderEvent(OrderEventEnum.getEvent(entry.getKey()), entry.getValue()); | |
92 | + } | |
88 | 93 | } |
94 | + | |
89 | 95 | } |
90 | 96 | |
91 | 97 | /** |
... | ... | @@ -94,28 +100,28 @@ public class OrderOverTimeEventJob { |
94 | 100 | */ |
95 | 101 | //发送邮件。 |
96 | 102 | private void sendEmail4OrderEvent(OrderEventEnum eventEnum, List<OrderEventJobVO> eventJobVOS) throws MessagingException, TemplateException, IOException { |
97 | - HashSet<String> strings = new HashSet<>(); | |
103 | + List<ReceiveEmailMappingDO> allMappings = receiveEmailMappingService.list(); | |
104 | + //存储 customerCode | |
105 | + Set<String> customerCodes = new HashSet<>(); | |
106 | + // 遍历 eventJobVOS,添加不在 Redis 中的 customerCode | |
98 | 107 | for (OrderEventJobVO orderEventJob : eventJobVOS) { |
99 | - if (!redisUtils.hasKey(EmailTemplateEnum.byTemplate( | |
100 | - eventEnum.getTemplateId()) + Constant.POINT_BAR_CHARACTER + orderEventJob.getBaseInfo().getId())){ | |
101 | - strings.add(orderEventJob.getBaseInfo().getCustomerCode()); | |
108 | + String cacheKey = EmailTemplateEnum.byTemplate(eventEnum.getTemplateId()) | |
109 | + + Constant.CROSS_BAR_CHARACTER | |
110 | + + orderEventJob.getBaseInfo().getId(); | |
111 | + if (!redisUtils.hasKey(cacheKey)) { | |
112 | + customerCodes.add(orderEventJob.getBaseInfo().getCustomerCode()); | |
102 | 113 | } |
103 | 114 | } |
104 | - LambdaQueryWrapper<ReceiveEmailMappingDO> queryWrapper = new LambdaQueryWrapper<>(); | |
105 | - queryWrapper.eq(ReceiveEmailMappingDO::getEnableFlag, Constant.ENABLE_TEN); | |
106 | - if (strings == null || strings.isEmpty()) { | |
107 | - queryWrapper.eq(ReceiveEmailMappingDO::getTypeValue, " "); | |
108 | - } else { | |
109 | - queryWrapper.in(ReceiveEmailMappingDO::getTypeValue, strings); | |
110 | - } | |
111 | - queryWrapper.apply("JSON_CONTAINS(JSON_EXTRACT(config_infos, '$[*].event'), JSON_QUOTE({0}), '$')", eventEnum.getEvent()); | |
112 | - List<ReceiveEmailMappingDO> receiveEmailMappingDOList = receiveEmailMappingService.list(queryWrapper); | |
113 | 115 | |
114 | - /* List<ReceiveEmailMappingDO> receiveEmailMappingDOList = receiveEmailMappingService.list( | |
115 | - new LambdaQueryWrapper<ReceiveEmailMappingDO>() | |
116 | - .eq(ReceiveEmailMappingDO::getEnableFlag, Constant.ENABLE_TEN) | |
117 | - .in(CollectionUtils.isNotEmpty(strings),ReceiveEmailMappingDO::getTypeValue, strings) | |
118 | - .apply("JSON_CONTAINS(JSON_EXTRACT(config_infos, '$[*].event'), JSON_QUOTE({0}), '$')", eventEnum.getEvent()));*/ | |
116 | + // 过滤 ReceiveEmailMappingDO | |
117 | + List<ReceiveEmailMappingDO> receiveEmailMappingDOList = allMappings.stream() | |
118 | + .filter(mapping -> customerCodes.isEmpty() || customerCodes.contains(mapping.getTypeValue())) | |
119 | + .filter(mapping -> { | |
120 | + // 检查 config_infos 是否包含 eventEnum.getEvent() | |
121 | + String configInfos = mapping.getConfigInfos(); | |
122 | + return configInfos != null && configInfos.contains(eventEnum.getEvent()); | |
123 | + }) | |
124 | + .collect(Collectors.toList()); | |
119 | 125 | |
120 | 126 | Set<Map<String, List<String>>> set = receiveEmailMappingDOList.stream().map(x -> { |
121 | 127 | Map<String, List<String>> map = new HashMap<>(); |
... | ... | @@ -138,11 +144,10 @@ public class OrderOverTimeEventJob { |
138 | 144 | emailSendUtils.sendEmail(EmailTemplateEnum.byTemplate(eventEnum.getTemplateId()), |
139 | 145 | map.get(map.keySet().iterator().next()), orderEventJob); |
140 | 146 | redisUtils.set(EmailTemplateEnum.byTemplate( |
141 | - eventEnum.getTemplateId()) + Constant.POINT_BAR_CHARACTER + orderEventJob.getBaseInfo().getId(), | |
147 | + eventEnum.getTemplateId()) + Constant.CROSS_BAR_CHARACTER + orderEventJob.getBaseInfo().getId(), | |
142 | 148 | orderEventJob); |
143 | 149 | } |
144 | 150 | } |
145 | - | |
146 | 151 | } |
147 | 152 | } |
148 | 153 | |
... | ... | @@ -159,8 +164,7 @@ public class OrderOverTimeEventJob { |
159 | 164 | Map<Long, OrderTrackStageDO> OrderTrackStageMap = orderTrackStageList.stream().collect(Collectors.toMap(OrderTrackStageDO::getOrderId, Function.identity(), (x, y) -> x)); |
160 | 165 | List<OrderEventJobVO> orderEventJobVOList = orderBaseInfoList.stream().map(x -> { |
161 | 166 | OrderEventJobVO orderEventJobVO = new OrderEventJobVO(); |
162 | - if (x.getId() == OrderInspectionStageMap.get(x.getId()).getOrderId() && | |
163 | - x.getId() == OrderTrackStageMap.get(x.getId()).getOrderId()) { | |
167 | + if (OrderInspectionStageMap.containsKey(x.getId()) && OrderTrackStageMap.containsKey(x.getId())) { | |
164 | 168 | OrderBaseInfoVO orderBaseInfoVO = new OrderBaseInfoVO(); |
165 | 169 | OrderTrackStageVO orderTrackStageVO = new OrderTrackStageVO(); |
166 | 170 | OrderInspectionStageVO orderInspectionStageVO = new OrderInspectionStageVO(); |
... | ... | @@ -171,8 +175,10 @@ public class OrderOverTimeEventJob { |
171 | 175 | orderEventJobVO.setInspectionStageInfo(orderInspectionStageVO); |
172 | 176 | orderEventJobVO.setBaseInfo(orderBaseInfoVO); |
173 | 177 | orderEventJobVO.setTrackStageInfo(orderTrackStageVO); |
178 | + return orderEventJobVO; | |
179 | + }else{ | |
180 | + return null; | |
174 | 181 | } |
175 | - return orderEventJobVO; | |
176 | 182 | }).filter(Objects::nonNull) |
177 | 183 | .collect(Collectors.toList()); |
178 | 184 | return orderEventJobVOList; |
... | ... | @@ -248,13 +254,15 @@ public class OrderOverTimeEventJob { |
248 | 254 | if (!ppConfirmResult.contains("ok") && org.apache.commons.lang3.StringUtils.countMatches(ppConfirmResult, "fail") == 3) { |
249 | 255 | return true; |
250 | 256 | } else if (ppConfirmResult.contains("ok") || org.apache.commons.lang3.StringUtils.countMatches(ppConfirmResult, "fail") < 3) { |
251 | - String[] parats = ppConfirmResult.split("\\+"); | |
252 | - String lastTime = parats[parats.length - 3]; | |
253 | - LocalDate parse1 = LocalDate.parse(lastTime, DateTimeFormatter.ofPattern("yyyy-M-d")); | |
254 | - LocalDate parse2 = LocalDate.parse(orderHodTime, DateTimeFormatter.ofPattern("yyyy-M-d")); | |
257 | + LocalDate parse1 = findLatestDateBeforeOk(ppConfirmResult); | |
258 | + //把订单中的Hod时间yyyy-mm-dd HH:mm:ss改成yyyy-mm-dd。 | |
259 | + String[] hodTime = orderHodTime.split(" "); | |
260 | + String orderhodTime = hodTime[0]; | |
261 | + LocalDate parse2 = DateUtils.parseDate(orderhodTime, dateFormatDay); | |
255 | 262 | long daysBetween = ChronoUnit.DAYS.between(parse1, parse2); |
256 | 263 | if (daysBetween == 21) { |
257 | 264 | return true; |
265 | + | |
258 | 266 | } |
259 | 267 | } |
260 | 268 | } |
... | ... | @@ -265,8 +273,13 @@ public class OrderOverTimeEventJob { |
265 | 273 | String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime(); |
266 | 274 | String esoSampleSendTime = eventJobVO.getTrackStageInfo().getEsoSampleSendTime(); |
267 | 275 | if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(esoSampleSendTime)) { |
268 | - LocalDate parse1 = LocalDate.parse(esoSampleSendTime, DateTimeFormatter.ofPattern("yyyy-M-d")); | |
269 | - LocalDate parse2 = LocalDate.parse(orderHodTime, DateTimeFormatter.ofPattern("yyyy-M-d")); | |
276 | + //把订单中的Hod时间yyyy-mm-dd HH:mm:ss改成yyyy-mm-dd。 | |
277 | + String[] hodTime = orderHodTime.split(" "); | |
278 | + String orderhodTime = hodTime[0]; | |
279 | + LocalDate parse2 = DateUtils.parseDate(orderhodTime, dateFormatDay); | |
280 | + LocalDateTime dateTime=LocalDateTime.parse(esoSampleSendTime, DateTimeFormatter.ofPattern(dateFormatSEC)); | |
281 | + String parse=dateTime.format(DateTimeFormatter.ofPattern(dateFormatDay)); | |
282 | + LocalDate parse1=DateUtils.parseDate(parse,dateFormatDay); | |
270 | 283 | if (ChronoUnit.DAYS.between(parse1, parse2) == 7) { |
271 | 284 | return true; |
272 | 285 | } |
... | ... | @@ -281,10 +294,11 @@ public class OrderOverTimeEventJob { |
281 | 294 | if (!shippmentSampleConfirmResult.contains("ok") && org.apache.commons.lang3.StringUtils.countMatches(shippmentSampleConfirmResult, "fail") == 3) { |
282 | 295 | return true; |
283 | 296 | } else if (shippmentSampleConfirmResult.contains("ok") || org.apache.commons.lang3.StringUtils.countMatches(shippmentSampleConfirmResult, "fail") < 3) { |
284 | - String[] parats = shippmentSampleConfirmResult.split("\\+"); | |
285 | - String lastTime = parats[parats.length - 3]; | |
286 | - LocalDate parse1 = LocalDate.parse(lastTime, DateTimeFormatter.ofPattern("yyyy-M-d")); | |
287 | - LocalDate parse2 = LocalDate.parse(orderHodTime, DateTimeFormatter.ofPattern("yyyy-M-d")); | |
297 | + //把订单中的Hod时间yyyy-mm-dd HH:mm:ss改成yyyy-mm-dd。 | |
298 | + String[] hodTime = orderHodTime.split(" "); | |
299 | + String orderhodTime = hodTime[0]; | |
300 | + LocalDate parse2 = DateUtils.parseDate(orderhodTime, dateFormatDay); | |
301 | + LocalDate parse1 = findLatestDateBeforeOk(shippmentSampleConfirmResult); | |
288 | 302 | long daysBetween = ChronoUnit.DAYS.between(parse1, parse2); |
289 | 303 | if (daysBetween == 7) { |
290 | 304 | return true; |
... | ... | @@ -306,13 +320,11 @@ public class OrderOverTimeEventJob { |
306 | 320 | return true; |
307 | 321 | } else if ((shippmentSampleConfirmResult.contains("ok") || org.apache.commons.lang3.StringUtils.countMatches(shippmentSampleConfirmResult, "fail") < 3) || |
308 | 322 | (sgsTestFinishResult.contains("ok") || org.apache.commons.lang3.StringUtils.countMatches(sgsTestFinishResult, "fail") < 3)) { |
309 | - String[] parats = shippmentSampleConfirmResult.split("\\+"); | |
310 | - String lastTime = parats[parats.length - 3]; | |
311 | - String[] parats1 = sgsTestFinishResult.split("\\+"); | |
312 | - String lastTime1 = parats1[parats1.length - 3]; | |
313 | - LocalDate parse1 = LocalDate.parse(lastTime, DateTimeFormatter.ofPattern("yyyy-M-d")); | |
314 | - LocalDate parse2 = LocalDate.parse(orderHodTime, DateTimeFormatter.ofPattern("yyyy-M-d")); | |
315 | - LocalDate parse3 = LocalDate.parse(lastTime1, DateTimeFormatter.ofPattern("yyyy-M-d")); | |
323 | + String[] hodTime = orderHodTime.split(" "); | |
324 | + String orderhodTime=hodTime[0]; | |
325 | + LocalDate parse1 = findLatestDateBeforeOk(shippmentSampleConfirmResult); | |
326 | + LocalDate parse2 = DateUtils.parseDate(orderhodTime, dateFormatDay); | |
327 | + LocalDate parse3 = findLatestDateBeforeOk(sgsTestFinishResult); | |
316 | 328 | long daysBetween = ChronoUnit.DAYS.between(parse1, parse2); |
317 | 329 | long daysBetween1 = ChronoUnit.DAYS.between(parse3, parse2); |
318 | 330 | if (daysBetween == 3 || daysBetween1 == 3) { |
... | ... | @@ -328,8 +340,12 @@ public class OrderOverTimeEventJob { |
328 | 340 | String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime(); |
329 | 341 | String lastArrivalTime = eventJobVO.getTrackStageInfo().getLatestArrivalTime(); |
330 | 342 | if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(lastArrivalTime)) { |
331 | - LocalDate parse1 = LocalDate.parse(lastArrivalTime, DateTimeFormatter.ofPattern("yyyy-M-d")); | |
332 | - LocalDate parse2 = LocalDate.parse(orderHodTime, DateTimeFormatter.ofPattern("yyyy-M-d")); | |
343 | + String[] hodTime = orderHodTime.split(" "); | |
344 | + String orderhodTime=hodTime[0]; | |
345 | + LocalDate parse2 = DateUtils.parseDate(orderhodTime, dateFormatDay); | |
346 | + LocalDateTime dateTime=LocalDateTime.parse(lastArrivalTime, DateTimeFormatter.ofPattern(dateFormatSEC)); | |
347 | + String parse=dateTime.format(DateTimeFormatter.ofPattern(dateFormatDay)); | |
348 | + LocalDate parse1=DateUtils.parseDate(parse,dateFormatDay); | |
333 | 349 | if (ChronoUnit.DAYS.between(parse1, parse2) == 7) { |
334 | 350 | return true; |
335 | 351 | } |
... | ... | @@ -341,8 +357,12 @@ public class OrderOverTimeEventJob { |
341 | 357 | String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime(); |
342 | 358 | String latestBkTime = eventJobVO.getTrackStageInfo().getLatestBkTime(); |
343 | 359 | if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(latestBkTime)) { |
344 | - LocalDate parse1 = LocalDate.parse(latestBkTime, DateTimeFormatter.ofPattern("yyyy-M-d")); | |
345 | - LocalDate parse2 = LocalDate.parse(orderHodTime, DateTimeFormatter.ofPattern("yyyy-M-d")); | |
360 | + String[] hodTime = orderHodTime.split(" "); | |
361 | + String orderhodTime=hodTime[0]; | |
362 | + LocalDate parse2 = DateUtils.parseDate(orderhodTime, dateFormatDay); | |
363 | + LocalDateTime dateTime=LocalDateTime.parse(latestBkTime, DateTimeFormatter.ofPattern(dateFormatSEC)); | |
364 | + String parse=dateTime.format(DateTimeFormatter.ofPattern(dateFormatDay)); | |
365 | + LocalDate parse1=DateUtils.parseDate(parse,dateFormatDay); | |
346 | 366 | if (ChronoUnit.DAYS.between(parse1, parse2) == 10) { |
347 | 367 | return true; |
348 | 368 | } |
... | ... | @@ -354,12 +374,39 @@ public class OrderOverTimeEventJob { |
354 | 374 | String orderHodTime = eventJobVO.getBaseInfo().getOrderHodTime(); |
355 | 375 | String endCheckApplyTime = eventJobVO.getInspectionStageInfo().getEndCheckApplyTime(); |
356 | 376 | if (StringUtils.isNotBlank(orderHodTime) && StringUtils.isNotBlank(endCheckApplyTime)) { |
357 | - LocalDate parse1 = LocalDate.parse(endCheckApplyTime, DateTimeFormatter.ofPattern("yyyy-M-d")); | |
358 | - LocalDate parse2 = LocalDate.parse(orderHodTime, DateTimeFormatter.ofPattern("yyyy-M-d")); | |
377 | + String[] hodTime = orderHodTime.split(" "); | |
378 | + String orderhodTime=hodTime[0]; | |
379 | + LocalDate parse2 = DateUtils.parseDate(orderhodTime, dateFormatDay); | |
380 | + LocalDateTime dateTime=LocalDateTime.parse(endCheckApplyTime, DateTimeFormatter.ofPattern(dateFormatSEC)); | |
381 | + String parse=dateTime.format(DateTimeFormatter.ofPattern(dateFormatDay)); | |
382 | + LocalDate parse1=DateUtils.parseDate(parse,dateFormatDay); | |
359 | 383 | if (ChronoUnit.DAYS.between(parse1, parse2) == 2) { |
360 | 384 | return true; |
361 | 385 | } |
362 | 386 | } |
363 | 387 | return false; |
364 | 388 | } |
389 | + | |
390 | + public LocalDate findLatestDateBeforeOk(String data){ | |
391 | + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormatSEC); | |
392 | + LocalDateTime latestDateBeforeOk = null; | |
393 | + // 正则表达式提取日期和状态 | |
394 | + Pattern pattern = Pattern.compile("(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2})\\s+(.*?)(?=\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}|$)"); | |
395 | + Matcher matcher = pattern.matcher(data); | |
396 | + while (matcher.find()) { | |
397 | + LocalDateTime eventDate = LocalDateTime.parse(matcher.group(1), formatter); | |
398 | + String status = matcher.group(2); | |
399 | + // 查找 "ok" 的位置 | |
400 | + int okIndex = data.indexOf("ok"); | |
401 | + if (okIndex != -1 && matcher.start() < okIndex) { | |
402 | + // 更新 latestDateBeforeOk 为当前事件的日期,如果当前日期晚于已知的日期 | |
403 | + if (latestDateBeforeOk == null || eventDate.isAfter(latestDateBeforeOk)) { | |
404 | + latestDateBeforeOk = eventDate; | |
405 | + } | |
406 | + } | |
407 | + } | |
408 | + // 转换为 LocalDate,去掉时分秒 | |
409 | + return (latestDateBeforeOk != null) ? latestDateBeforeOk.toLocalDate() : null; | |
410 | + } | |
411 | + | |
365 | 412 | } | ... | ... |