|
|
@@ -2,6 +2,7 @@ package com.ufo.project.data.service.impl;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
import java.math.RoundingMode;
|
|
|
+import java.time.Instant;
|
|
|
import java.time.LocalDate;
|
|
|
import java.time.LocalDateTime;
|
|
|
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 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");
|
|
|
|
|
|
@Autowired
|
|
|
@@ -69,7 +71,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
{
|
|
|
String type = query.getType();
|
|
|
String entityId = query.getEntityId();
|
|
|
- String startTime = query.getStartTime();
|
|
|
+ String startTime = query.getStartTime() + " 00:00:00";
|
|
|
String endTime = query.getEndTime() + " 23:59:59";
|
|
|
|
|
|
// 1. 获取实发功率数据
|
|
|
@@ -81,8 +83,10 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
}
|
|
|
|
|
|
// 2. 获取预测功率数据
|
|
|
+ long utcStartTime = parseLong(startTime);
|
|
|
+ long utcEndTime = parseLong(endTime);
|
|
|
List<DataShortTermPowerForecastIssued> forecastList = powerForecastIssuedService.selectByTimeRange(
|
|
|
- entityId, parseLong(startTime), parseLong(endTime));
|
|
|
+ entityId, utcStartTime, utcEndTime);
|
|
|
|
|
|
// 3. 按基准类型分组
|
|
|
switch (type)
|
|
|
@@ -233,7 +237,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
*/
|
|
|
private BigDecimal computeActualPower(List<DataElectricityLocal> records)
|
|
|
{
|
|
|
- double sum = 0.0;
|
|
|
+ BigDecimal sum = BigDecimal.ZERO;
|
|
|
int count = 0;
|
|
|
for (DataElectricityLocal r : records)
|
|
|
{
|
|
|
@@ -242,7 +246,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
Double ap = r.getActualPower();
|
|
|
if (ap != null)
|
|
|
{
|
|
|
- sum += ap;
|
|
|
+ sum = sum.add(BigDecimal.valueOf(ap));
|
|
|
count++;
|
|
|
}
|
|
|
}
|
|
|
@@ -251,7 +255,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
{
|
|
|
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)
|
|
|
{
|
|
|
- double sum = 0.0;
|
|
|
+ BigDecimal sum = BigDecimal.ZERO;
|
|
|
int count = 0;
|
|
|
for (DataShortTermPowerForecastIssued r : records)
|
|
|
{
|
|
|
@@ -268,7 +272,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
- sum += Double.parseDouble(power.trim());
|
|
|
+ sum = sum.add(new BigDecimal(power.trim()));
|
|
|
count++;
|
|
|
}
|
|
|
catch (NumberFormatException e)
|
|
|
@@ -281,7 +285,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
{
|
|
|
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()
|
|
|
.filter(r -> r.getForecastTime() != null)
|
|
|
.collect(Collectors.groupingBy(
|
|
|
- r -> LocalDate.ofEpochDay(r.getForecastTime() / 86400L)
|
|
|
+ r -> LocalDateTime.ofInstant(
|
|
|
+ Instant.ofEpochSecond(r.getForecastTime()), ZONE_SHANGHAI)
|
|
|
+ .toLocalDate()
|
|
|
.format(DATE_FMT),
|
|
|
LinkedHashMap::new,
|
|
|
Collectors.toList()));
|
|
|
@@ -590,7 +596,9 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
.collect(Collectors.groupingBy(
|
|
|
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);
|
|
|
},
|
|
|
LinkedHashMap::new,
|
|
|
@@ -606,13 +614,17 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
return records.stream()
|
|
|
.filter(r -> r.getForecastTime() != null)
|
|
|
.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,
|
|
|
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)
|
|
|
{
|
|
|
@@ -625,31 +637,31 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
}
|
|
|
catch (NumberFormatException e)
|
|
|
{
|
|
|
- // 尝试作为日期字符串解析为秒级时间戳
|
|
|
+ // 尝试作为日期字符串解析为 UTC epoch seconds
|
|
|
try
|
|
|
{
|
|
|
// 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);
|
|
|
- return zdt.toEpochSecond();
|
|
|
+ return zdt.toInstant().getEpochSecond();
|
|
|
}
|
|
|
catch (DateTimeParseException e2)
|
|
|
{
|
|
|
// yyyy-MM-dd
|
|
|
try
|
|
|
{
|
|
|
- ZonedDateTime zdt = LocalDate.parse(trimmed, DateTimeFormatter.ofPattern("yyyy-MM-dd"))
|
|
|
+ ZonedDateTime zdt = LocalDate.parse(trimmed, DATE_FMT)
|
|
|
.atStartOfDay(ZONE_SHANGHAI);
|
|
|
- return zdt.toEpochSecond();
|
|
|
+ return zdt.toInstant().getEpochSecond();
|
|
|
}
|
|
|
catch (DateTimeParseException e3)
|
|
|
{
|
|
|
// yyyy-MM(月末)
|
|
|
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);
|
|
|
- return zdt.toEpochSecond();
|
|
|
+ return zdt.toInstant().getEpochSecond();
|
|
|
}
|
|
|
catch (DateTimeParseException e4)
|
|
|
{
|