Browse Source

[0917] 短期、超短期功率预测时区

taosj 4 weeks ago
parent
commit
0370ec9dec

+ 2 - 3
forecast-backend-server/src/main/java/com/ufo/project/forecast/shortterm/power/controller/ShortTermPowerForecastingController.java

@@ -26,7 +26,6 @@ import com.ufo.base.framework.web.domain.AjaxResult;
 import com.ufo.project.forecast.shortterm.power.domain.DataShortTermPowerForecastIssued;
 import com.ufo.project.forecast.shortterm.power.domain.ShortTermPowerForecastData;
 import com.ufo.project.forecast.shortterm.power.service.IDataShortTermPowerForecastIssuedService;
-import com.ufo.project.forecast.shortterm.power.util.ExcelForecastFileUtil;
 
 /**
  * 短期功率预测Controller
@@ -85,10 +84,10 @@ public class ShortTermPowerForecastingController extends BaseController
     private List<ShortTermPowerForecastData> queryForecastData(Long stationId, Integer forecastHours)
     {
         List<ShortTermPowerForecastData> result = new ArrayList<>();
-        long now = System.currentTimeMillis() / 1000L;
+        long now = System.currentTimeMillis() / 1000;
         long end = now + (long) forecastHours * 3600L;
         List<DataShortTermPowerForecastIssued> issuedList = dataShortTermPowerForecastIssuedService
-                .selectByTimeRange(stationId.toString(), TimeUtils.gmt8ToUtc(now), TimeUtils.gmt8ToUtc(end));
+                .selectByTimeRange(stationId.toString(), now, end);
         if (issuedList == null || issuedList.isEmpty())
         {
             return result;

+ 74 - 33
forecast-backend-server/src/main/java/com/ufo/project/forecast/shortterm/power/controller/UltraShortTermPowerForecastingController.java

@@ -1,11 +1,21 @@
 package com.ufo.project.forecast.shortterm.power.controller;
 
 import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.net.URLEncoder;
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 import javax.servlet.http.HttpServletResponse;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -16,13 +26,13 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import com.alibaba.excel.EasyExcel;
+import com.ufo.base.common.utils.TimeUtils;
 import com.ufo.base.framework.aspectj.lang.annotation.Log;
 import com.ufo.base.framework.aspectj.lang.enums.BusinessType;
 import com.ufo.base.framework.web.controller.BaseController;
 import com.ufo.base.framework.web.domain.AjaxResult;
 import com.ufo.project.forecast.shortterm.power.domain.UltraShortTermPowerForecastData;
 import com.ufo.project.forecast.shortterm.power.domain.UltraShortTermPowerSingleExport;
-import com.ufo.project.forecast.shortterm.power.util.ExcelForecastFileUtil;
 import com.ufo.project.forecast.supershort.domain.DataUltraShortTermPowerForecasting;
 import com.ufo.project.forecast.supershort.service.IDataUltraShortTermPowerForecastingService;
 
@@ -39,6 +49,8 @@ public class UltraShortTermPowerForecastingController extends BaseController
 
     private static final String PATTERN_SECOND = "yyyy-MM-dd HH:mm:ss";
     private static final String PATTERN_COMPACT = "yyyyMMddHHmm";
+    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+    private static final ZoneId GMT8 = ZoneId.of("GMT+8");
 
     @Autowired
     private IDataUltraShortTermPowerForecastingService dataUltraShortTermPowerForecastingService;
@@ -109,21 +121,30 @@ public class UltraShortTermPowerForecastingController extends BaseController
         List<UltraShortTermPowerForecastData> result = new ArrayList<>();
         try
         {
-            SimpleDateFormat sdf = new SimpleDateFormat(PATTERN_SECOND);
-            Date startTime = sdf.parse(startTimeStr);
-            Date endTime = sdf.parse(endTimeStr);
+            LocalDateTime startLdt = LocalDateTime.parse(startTimeStr, FORMATTER);
+        LocalDateTime endLdt   = LocalDateTime.parse(endTimeStr, FORMATTER);
+
+        long startUnix = startLdt.atZone(GMT8).toEpochSecond();
+        long endUnix   = endLdt.atZone(GMT8).toEpochSecond();
 
-            long startUnix = startTime.getTime() / 1000;
-            long endUnix = endTime.getTime() / 1000;
             List<DataUltraShortTermPowerForecasting> dataList = dataUltraShortTermPowerForecastingService
                     .selectByTimeRange(stationId.toString(), startUnix, endUnix);
-            if (dataList == null)
+            if (dataList == null || dataList.isEmpty())
             {
                 return result;
             }
-            for (DataUltraShortTermPowerForecasting data : dataList)
+
+            // 按 forecast_time 分组,同一时间点取平均值
+            Map<Long, List<DataUltraShortTermPowerForecasting>> groupedByTime = dataList.stream()
+                    .filter(data -> data.getForecastTime() != null)
+                    .collect(Collectors.groupingBy(
+                            DataUltraShortTermPowerForecasting::getForecastTime,
+                            LinkedHashMap::new,
+                            Collectors.toList()));
+
+            for (Map.Entry<Long, List<DataUltraShortTermPowerForecasting>> entry : groupedByTime.entrySet())
             {
-                result.add(toData(data));
+                result.add(toData(entry.getKey(), entry.getValue()));
             }
         }
         catch (Exception e)
@@ -134,27 +155,28 @@ public class UltraShortTermPowerForecastingController extends BaseController
         return result;
     }
 
-    private UltraShortTermPowerForecastData toData(DataUltraShortTermPowerForecasting data)
+    private UltraShortTermPowerForecastData toData(Long forecastTime, List<DataUltraShortTermPowerForecasting> items)
     {
         UltraShortTermPowerForecastData result = new UltraShortTermPowerForecastData();
-        result.setTime(ExcelForecastFileUtil.formatTime(String.valueOf(data.getStartTime())));
-        result.setMonitoredPower(parseDouble(data.getPower()));
-        result.setPower15(parseDouble(data.getPower15()));
-        result.setPower30(parseDouble(data.getPower30()));
-        result.setPower45(parseDouble(data.getPower45()));
-        result.setPower60(parseDouble(data.getPower60()));
-        result.setPower75(parseDouble(data.getPower75()));
-        result.setPower90(parseDouble(data.getPower90()));
-        result.setPower105(parseDouble(data.getPower105()));
-        result.setPower120(parseDouble(data.getPower120()));
-        result.setPower135(parseDouble(data.getPower135()));
-        result.setPower150(parseDouble(data.getPower150()));
-        result.setPower165(parseDouble(data.getPower165()));
-        result.setPower180(parseDouble(data.getPower180()));
-        result.setPower195(parseDouble(data.getPower195()));
-        result.setPower210(parseDouble(data.getPower210()));
-        result.setPower225(parseDouble(data.getPower225()));
-        result.setPower240(parseDouble(data.getPower240()));
+        // forecast_time 为 UTC unix 秒,展示时格式化为 GMT+8 时间
+        result.setTime(TimeUtils.utcToGmt8Format(forecastTime));
+        result.setMonitoredPower(avgPower(items, DataUltraShortTermPowerForecasting::getPower));
+        result.setPower15(avgPower(items, DataUltraShortTermPowerForecasting::getPower15));
+        result.setPower30(avgPower(items, DataUltraShortTermPowerForecasting::getPower30));
+        result.setPower45(avgPower(items, DataUltraShortTermPowerForecasting::getPower45));
+        result.setPower60(avgPower(items, DataUltraShortTermPowerForecasting::getPower60));
+        result.setPower75(avgPower(items, DataUltraShortTermPowerForecasting::getPower75));
+        result.setPower90(avgPower(items, DataUltraShortTermPowerForecasting::getPower90));
+        result.setPower105(avgPower(items, DataUltraShortTermPowerForecasting::getPower105));
+        result.setPower120(avgPower(items, DataUltraShortTermPowerForecasting::getPower120));
+        result.setPower135(avgPower(items, DataUltraShortTermPowerForecasting::getPower135));
+        result.setPower150(avgPower(items, DataUltraShortTermPowerForecasting::getPower150));
+        result.setPower165(avgPower(items, DataUltraShortTermPowerForecasting::getPower165));
+        result.setPower180(avgPower(items, DataUltraShortTermPowerForecasting::getPower180));
+        result.setPower195(avgPower(items, DataUltraShortTermPowerForecasting::getPower195));
+        result.setPower210(avgPower(items, DataUltraShortTermPowerForecasting::getPower210));
+        result.setPower225(avgPower(items, DataUltraShortTermPowerForecasting::getPower225));
+        result.setPower240(avgPower(items, DataUltraShortTermPowerForecasting::getPower240));
         return result;
     }
 
@@ -164,15 +186,34 @@ public class UltraShortTermPowerForecastingController extends BaseController
     }
 
     /**
-     * 字符串转 Double,空值返回 null
+     * 统计同一组内指定功率字段的平均值,保留3位小数(四舍五入),无有效值返回 0
      */
-    private Double parseDouble(String value)
+    private Double avgPower(List<DataUltraShortTermPowerForecasting> items,
+            Function<DataUltraShortTermPowerForecasting, String> extractor)
     {
-        if (value == null || value.trim().isEmpty())
+        BigDecimal sum = BigDecimal.ZERO;
+        int validCount = 0;
+        for (DataUltraShortTermPowerForecasting item : items)
+        {
+            String value = extractor.apply(item);
+            if (value == null || value.trim().isEmpty())
+            {
+                continue;
+            }
+            try
+            {
+                sum = sum.add(new BigDecimal(value.trim()));
+                validCount++;
+            }
+            catch (NumberFormatException ignored)
+            {
+            }
+        }
+        if (validCount == 0)
         {
-            return null;
+            return 0D;
         }
-        return Double.parseDouble(value);
+        return sum.divide(BigDecimal.valueOf(validCount), 3, RoundingMode.HALF_UP).doubleValue();
     }
 
     private String buildFileName(String startTime, String endTime)