Просмотр исходного кода

[0917] 修复短期报表经度

taosj 1 месяц назад
Родитель
Сommit
5efde9f556

+ 31 - 19
forecast-backend-server/src/main/java/com/ufo/project/data/service/impl/ShortTermPowerForecastReportServiceImpl.java

@@ -2,6 +2,7 @@ package com.ufo.project.data.service.impl;
 
 
 import java.math.BigDecimal;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.math.RoundingMode;
+import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 import java.time.YearMonth;
 import java.time.YearMonth;
@@ -44,6 +45,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
 
 
     private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
     private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
     private static final DateTimeFormatter MONTH_FMT = DateTimeFormatter.ofPattern("yyyy-MM");
     private static final DateTimeFormatter MONTH_FMT = DateTimeFormatter.ofPattern("yyyy-MM");
+    private static final DateTimeFormatter DATE_TIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
     private static final ZoneId ZONE_SHANGHAI = ZoneId.of("Asia/Shanghai");
     private static final ZoneId ZONE_SHANGHAI = ZoneId.of("Asia/Shanghai");
 
 
     @Autowired
     @Autowired
@@ -69,7 +71,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
     {
     {
         String type = query.getType();
         String type = query.getType();
         String entityId = query.getEntityId();
         String entityId = query.getEntityId();
-        String startTime = query.getStartTime();
+        String startTime = query.getStartTime() + " 00:00:00";
         String endTime = query.getEndTime() + " 23:59:59";
         String endTime = query.getEndTime() + " 23:59:59";
 
 
         // 1. 获取实发功率数据
         // 1. 获取实发功率数据
@@ -81,8 +83,10 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
         }
         }
 
 
         // 2. 获取预测功率数据
         // 2. 获取预测功率数据
+        long utcStartTime = parseLong(startTime);
+        long utcEndTime = parseLong(endTime);
         List<DataShortTermPowerForecastIssued> forecastList = powerForecastIssuedService.selectByTimeRange(
         List<DataShortTermPowerForecastIssued> forecastList = powerForecastIssuedService.selectByTimeRange(
-                entityId, parseLong(startTime), parseLong(endTime));
+                entityId, utcStartTime, utcEndTime);
 
 
         // 3. 按基准类型分组
         // 3. 按基准类型分组
         switch (type)
         switch (type)
@@ -233,7 +237,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
      */
      */
     private BigDecimal computeActualPower(List<DataElectricityLocal> records)
     private BigDecimal computeActualPower(List<DataElectricityLocal> records)
     {
     {
-        double sum = 0.0;
+        BigDecimal sum = BigDecimal.ZERO;
         int count = 0;
         int count = 0;
         for (DataElectricityLocal r : records)
         for (DataElectricityLocal r : records)
         {
         {
@@ -242,7 +246,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
                 Double ap = r.getActualPower();
                 Double ap = r.getActualPower();
                 if (ap != null)
                 if (ap != null)
                 {
                 {
-                    sum += ap;
+                    sum = sum.add(BigDecimal.valueOf(ap));
                     count++;
                     count++;
                 }
                 }
             }
             }
@@ -251,7 +255,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
         {
         {
             return BigDecimal.ZERO;
             return BigDecimal.ZERO;
         }
         }
-        return BigDecimal.valueOf(sum / count / 1000.0).setScale(3, RoundingMode.HALF_UP);
+        return sum.divide(new BigDecimal(1000)).divide(BigDecimal.valueOf(count), 3, RoundingMode.HALF_UP);
     }
     }
 
 
     /**
     /**
@@ -259,7 +263,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
      */
      */
     private BigDecimal computeForecastPower(List<DataShortTermPowerForecastIssued> records)
     private BigDecimal computeForecastPower(List<DataShortTermPowerForecastIssued> records)
     {
     {
-        double sum = 0.0;
+        BigDecimal sum = BigDecimal.ZERO;
         int count = 0;
         int count = 0;
         for (DataShortTermPowerForecastIssued r : records)
         for (DataShortTermPowerForecastIssued r : records)
         {
         {
@@ -268,7 +272,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
             {
             {
                 try
                 try
                 {
                 {
-                    sum += Double.parseDouble(power.trim());
+                    sum = sum.add(new BigDecimal(power.trim()));
                     count++;
                     count++;
                 }
                 }
                 catch (NumberFormatException e)
                 catch (NumberFormatException e)
@@ -281,7 +285,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
         {
         {
             return BigDecimal.ZERO;
             return BigDecimal.ZERO;
         }
         }
-        return BigDecimal.valueOf(sum / count / 1000.0).setScale(3, RoundingMode.HALF_UP);
+        return sum.divide(new BigDecimal(1000)).divide(BigDecimal.valueOf(count), 3, RoundingMode.HALF_UP);
     }
     }
 
 
     /**
     /**
@@ -573,7 +577,9 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
         return records.stream()
         return records.stream()
                 .filter(r -> r.getForecastTime() != null)
                 .filter(r -> r.getForecastTime() != null)
                 .collect(Collectors.groupingBy(
                 .collect(Collectors.groupingBy(
-                        r -> LocalDate.ofEpochDay(r.getForecastTime() / 86400L)
+                        r -> LocalDateTime.ofInstant(
+                                Instant.ofEpochSecond(r.getForecastTime()), ZONE_SHANGHAI)
+                                .toLocalDate()
                                 .format(DATE_FMT),
                                 .format(DATE_FMT),
                         LinkedHashMap::new,
                         LinkedHashMap::new,
                         Collectors.toList()));
                         Collectors.toList()));
@@ -590,7 +596,9 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
                 .collect(Collectors.groupingBy(
                 .collect(Collectors.groupingBy(
                         r ->
                         r ->
                         {
                         {
-                            LocalDate ld = LocalDate.ofEpochDay(r.getForecastTime() / 86400L);
+                            LocalDate ld = LocalDateTime.ofInstant(
+                                    Instant.ofEpochSecond(r.getForecastTime()), ZONE_SHANGHAI)
+                                    .toLocalDate();
                             return YearMonth.of(ld.getYear(), ld.getMonth()).format(MONTH_FMT);
                             return YearMonth.of(ld.getYear(), ld.getMonth()).format(MONTH_FMT);
                         },
                         },
                         LinkedHashMap::new,
                         LinkedHashMap::new,
@@ -606,13 +614,17 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
         return records.stream()
         return records.stream()
                 .filter(r -> r.getForecastTime() != null)
                 .filter(r -> r.getForecastTime() != null)
                 .collect(Collectors.groupingBy(
                 .collect(Collectors.groupingBy(
-                        r -> String.valueOf(LocalDate.ofEpochDay(r.getForecastTime() / 86400L).getYear()),
+                        r -> String.valueOf(LocalDateTime.ofInstant(
+                                        Instant.ofEpochSecond(r.getForecastTime()), ZONE_SHANGHAI)
+                                .toLocalDate()
+                                .getYear()),
                         LinkedHashMap::new,
                         LinkedHashMap::new,
                         Collectors.toList()));
                         Collectors.toList()));
     }
     }
 
 
     /**
     /**
-     * 安全解析Long,支持纯数字时间戳或日期字符串(yyyy-MM-dd、yyyy-MM-dd HH:mm:ss、yyyy-MM)
+     * 安全解析Long,支持纯数字时间戳或日期字符串(yyyy-MM-dd、yyyy-MM-dd HH:mm:ss、yyyy-MM)。
+     * 输入的日期字符串均为 GMT+8 时间,解析为 UTC epoch seconds 供查询使用。
      */
      */
     private Long parseLong(String value)
     private Long parseLong(String value)
     {
     {
@@ -625,31 +637,31 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
         }
         }
         catch (NumberFormatException e)
         catch (NumberFormatException e)
         {
         {
-            // 尝试作为日期字符串解析为秒级时间戳
+            // 尝试作为日期字符串解析为 UTC epoch seconds
             try
             try
             {
             {
                 // yyyy-MM-dd HH:mm:ss
                 // yyyy-MM-dd HH:mm:ss
-                ZonedDateTime zdt = LocalDateTime.parse(trimmed, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
+                ZonedDateTime zdt = LocalDateTime.parse(trimmed, DATE_TIME_FMT)
                         .atZone(ZONE_SHANGHAI);
                         .atZone(ZONE_SHANGHAI);
-                return zdt.toEpochSecond();
+                return zdt.toInstant().getEpochSecond();
             }
             }
             catch (DateTimeParseException e2)
             catch (DateTimeParseException e2)
             {
             {
                 // yyyy-MM-dd
                 // yyyy-MM-dd
                 try
                 try
                 {
                 {
-                    ZonedDateTime zdt = LocalDate.parse(trimmed, DateTimeFormatter.ofPattern("yyyy-MM-dd"))
+                    ZonedDateTime zdt = LocalDate.parse(trimmed, DATE_FMT)
                             .atStartOfDay(ZONE_SHANGHAI);
                             .atStartOfDay(ZONE_SHANGHAI);
-                    return zdt.toEpochSecond();
+                    return zdt.toInstant().getEpochSecond();
                 }
                 }
                 catch (DateTimeParseException e3)
                 catch (DateTimeParseException e3)
                 {
                 {
                     // yyyy-MM(月末)
                     // yyyy-MM(月末)
                     try
                     try
                     {
                     {
-                        YearMonth ym = YearMonth.parse(trimmed, DateTimeFormatter.ofPattern("yyyy-MM"));
+                        YearMonth ym = YearMonth.parse(trimmed, MONTH_FMT);
                         ZonedDateTime zdt = ym.atDay(ym.lengthOfMonth()).atTime(23, 59, 59).atZone(ZONE_SHANGHAI);
                         ZonedDateTime zdt = ym.atDay(ym.lengthOfMonth()).atTime(23, 59, 59).atZone(ZONE_SHANGHAI);
-                        return zdt.toEpochSecond();
+                        return zdt.toInstant().getEpochSecond();
                     }
                     }
                     catch (DateTimeParseException e4)
                     catch (DateTimeParseException e4)
                     {
                     {