|
|
@@ -10,14 +10,12 @@ import java.time.format.DateTimeParseException;
|
|
|
import java.util.*;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
*@author: zhao yue yue
|
|
|
*@create: 2025-12-08 10:05
|
|
|
*/
|
|
|
public class CostDataUtil {
|
|
|
|
|
|
-
|
|
|
private static final List<DateTimeFormatter> FORMATTERS = Arrays.asList(
|
|
|
DateTimeFormatter.ofPattern("yyyy-MM-dd"),
|
|
|
DateTimeFormatter.ofPattern("yyyy/MM/dd"),
|
|
|
@@ -28,27 +26,24 @@ public class CostDataUtil {
|
|
|
DateTimeFormatter.ofPattern("yyyy年MM月dd日")
|
|
|
);
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* 将查询结果转换为目标格式
|
|
|
- * @param maps 查询结果:包含序号(xuhao)、项目名称(xiangmu)、年份(nianfen)、数值(shuzhi)和rowid
|
|
|
- * @return 转换后的数据结构
|
|
|
*/
|
|
|
public Map<String, Object> convertToCostFormat(List<Map<String, Object>> maps) {
|
|
|
if (maps == null || maps.isEmpty()) {
|
|
|
return createEmptyResult();
|
|
|
}
|
|
|
|
|
|
- // 1. 提取所有年份(从nianfen字段中提取年份数字)
|
|
|
+ // 1. 提取所有年份
|
|
|
Set<String> years = extractYearsFromData(maps);
|
|
|
|
|
|
// 2. 按序号和项目名称分组
|
|
|
- Map<String, Map<String, String>> groupedData = groupBySerialAndProject(maps, years);
|
|
|
+ Map<String, Map<String, Object>> groupedData = groupBySerialAndProject(maps, years);
|
|
|
|
|
|
- // 3. 构建costItems列表(按序号排序)
|
|
|
+ // 3. 构建costItems列表(完全按照orderNum数值排序)
|
|
|
List<Map<String, Object>> costItems = buildCostItems(groupedData, years);
|
|
|
|
|
|
- // 4. 添加合计行(可选)
|
|
|
+ // 4. 添加合计行
|
|
|
addTotalItem(costItems, groupedData, years);
|
|
|
|
|
|
// 5. 返回最终结果
|
|
|
@@ -60,28 +55,20 @@ public class CostDataUtil {
|
|
|
*/
|
|
|
private Set<String> extractYearsFromData(List<Map<String, Object>> maps) {
|
|
|
return maps.stream()
|
|
|
- .map(row -> {
|
|
|
- String nianfen = (String) row.get("nianfen");
|
|
|
- if (nianfen != null) {
|
|
|
- // 提取年份数字,如从"2024年核定值"中提取"2024"
|
|
|
- return extractYearNumber(nianfen);
|
|
|
- }
|
|
|
- return null;
|
|
|
- })
|
|
|
+ .map(row -> extractYearNumber((String) row.get("nianfen")))
|
|
|
.filter(Objects::nonNull)
|
|
|
.filter(year -> !year.isEmpty())
|
|
|
- .collect(Collectors.toCollection(TreeSet::new)); // 自动排序
|
|
|
+ .collect(Collectors.toCollection(TreeSet::new));
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 按序号和项目名称分组
|
|
|
+ * 按序号和项目名称分组,同时保存orderNum
|
|
|
*/
|
|
|
- private Map<String, Map<String, String>> groupBySerialAndProject(
|
|
|
+ private Map<String, Map<String, Object>> groupBySerialAndProject(
|
|
|
List<Map<String, Object>> maps,
|
|
|
Set<String> years) {
|
|
|
|
|
|
- // 使用LinkedHashMap保持插入顺序
|
|
|
- Map<String, Map<String, String>> result = new LinkedHashMap<>();
|
|
|
+ Map<String, Map<String, Object>> result = new HashMap<>();
|
|
|
|
|
|
for (Map<String, Object> row : maps) {
|
|
|
try {
|
|
|
@@ -89,23 +76,42 @@ public class CostDataUtil {
|
|
|
String xiangmu = (String) row.get("xiangmu");
|
|
|
String nianfen = (String) row.get("nianfen");
|
|
|
Object shuzhiObj = row.get("shuzhi");
|
|
|
+ Object orderNumObj = row.get("orderNum");
|
|
|
|
|
|
if (xuhao == null || xiangmu == null || nianfen == null) {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- // 生成唯一键:序号 + "|" + 项目名称
|
|
|
String key = xuhao + "|" + xiangmu;
|
|
|
|
|
|
- // 初始化项目数据
|
|
|
if (!result.containsKey(key)) {
|
|
|
result.put(key, new HashMap<>());
|
|
|
+
|
|
|
+ // 保存orderNum(字符串)
|
|
|
+ String orderNumStr = null;
|
|
|
+ Long orderNumValue = null;
|
|
|
+
|
|
|
+ if (orderNumObj != null) {
|
|
|
+ orderNumStr = orderNumObj.toString().trim();
|
|
|
+ if (!orderNumStr.isEmpty()) {
|
|
|
+ // 将orderNum转换为数值用于排序
|
|
|
+ try {
|
|
|
+ orderNumValue = Long.parseLong(orderNumStr);
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ // 如果不是纯数字,按字符串处理
|
|
|
+ orderNumValue = Long.MAX_VALUE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ result.get(key).put("orderNumStr", orderNumStr);
|
|
|
+ result.get(key).put("orderNumValue", orderNumValue);
|
|
|
+ result.get(key).put("yearData", new HashMap<String, String>());
|
|
|
}
|
|
|
|
|
|
// 提取年份
|
|
|
String year = extractYearNumber(nianfen);
|
|
|
if (year != null && years.contains(year)) {
|
|
|
- // 转换值为字符串
|
|
|
String value = "";
|
|
|
if (shuzhiObj != null) {
|
|
|
String strValue = shuzhiObj.toString().trim();
|
|
|
@@ -113,11 +119,13 @@ public class CostDataUtil {
|
|
|
value = strValue;
|
|
|
}
|
|
|
}
|
|
|
- result.get(key).put(year, value);
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ Map<String, String> yearData = (Map<String, String>) result.get(key).get("yearData");
|
|
|
+ yearData.put(year, value);
|
|
|
}
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
- // 跳过错误数据
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
|
@@ -126,25 +134,34 @@ public class CostDataUtil {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 构建costItems列表,按序号排序
|
|
|
+ * 构建costItems列表,完全按照orderNum数值排序
|
|
|
*/
|
|
|
private List<Map<String, Object>> buildCostItems(
|
|
|
- Map<String, Map<String, String>> groupedData,
|
|
|
+ Map<String, Map<String, Object>> groupedData,
|
|
|
Set<String> years) {
|
|
|
|
|
|
List<Map<String, Object>> costItems = new ArrayList<>();
|
|
|
|
|
|
- // 按序号排序(先按中文序号,再按数字序号)
|
|
|
+ // 按照orderNumValue排序(从小到大)
|
|
|
List<String> sortedKeys = groupedData.keySet().stream()
|
|
|
.sorted((key1, key2) -> {
|
|
|
- // 分割键:序号|项目名称
|
|
|
- String[] parts1 = key1.split("\\|");
|
|
|
- String[] parts2 = key2.split("\\|");
|
|
|
- String xuhao1 = parts1[0];
|
|
|
- String xuhao2 = parts2[0];
|
|
|
-
|
|
|
- // 自定义排序:先中文序号,后数字序号
|
|
|
- return compareChineseAndNumber(xuhao1, xuhao2);
|
|
|
+ Map<String, Object> data1 = groupedData.get(key1);
|
|
|
+ Map<String, Object> data2 = groupedData.get(key2);
|
|
|
+
|
|
|
+ Long orderNum1 = (Long) data1.get("orderNumValue");
|
|
|
+ Long orderNum2 = (Long) data2.get("orderNumValue");
|
|
|
+
|
|
|
+ // 处理null值:null值排到最后
|
|
|
+ if (orderNum1 == null && orderNum2 == null) {
|
|
|
+ return key1.compareTo(key2);
|
|
|
+ } else if (orderNum1 == null) {
|
|
|
+ return 1; // orderNum1为null,排到后面
|
|
|
+ } else if (orderNum2 == null) {
|
|
|
+ return -1; // orderNum2为null,排到后面
|
|
|
+ } else {
|
|
|
+ // 按照数值大小排序
|
|
|
+ return Long.compare(orderNum1, orderNum2);
|
|
|
+ }
|
|
|
})
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
@@ -153,20 +170,26 @@ public class CostDataUtil {
|
|
|
String xuhao = parts[0];
|
|
|
String xiangmu = parts[1];
|
|
|
|
|
|
+ Map<String, Object> itemData = groupedData.get(key);
|
|
|
+
|
|
|
Map<String, Object> item = new HashMap<>();
|
|
|
|
|
|
- // 使用项目名称作为costItemName
|
|
|
item.put("costItemName", xiangmu);
|
|
|
- // 如果需要,也可以添加序号字段
|
|
|
item.put("serialNumber", xuhao);
|
|
|
|
|
|
+ String orderNumStr = (String) itemData.get("orderNumStr");
|
|
|
+ if (orderNumStr != null) {
|
|
|
+ item.put("orderNum", orderNumStr);
|
|
|
+ }
|
|
|
+
|
|
|
// 添加年份数据
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ Map<String, String> yearData = (Map<String, String>) itemData.get("yearData");
|
|
|
Map<String, String> yearValues = new HashMap<>();
|
|
|
- Map<String, String> projectYearData = groupedData.get(key);
|
|
|
|
|
|
for (String year : years) {
|
|
|
- String value = projectYearData != null ?
|
|
|
- projectYearData.getOrDefault(year, "") : "";
|
|
|
+ String value = yearData != null ?
|
|
|
+ yearData.getOrDefault(year, "") : "";
|
|
|
yearValues.put(year, value);
|
|
|
}
|
|
|
item.put("yearValues", yearValues);
|
|
|
@@ -178,26 +201,28 @@ public class CostDataUtil {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 添加合计行
|
|
|
+ * 添加合计行(合计行不参与排序,总是放在最后)
|
|
|
*/
|
|
|
private void addTotalItem(
|
|
|
List<Map<String, Object>> costItems,
|
|
|
- Map<String, Map<String, String>> groupedData,
|
|
|
+ Map<String, Map<String, Object>> groupedData,
|
|
|
Set<String> years) {
|
|
|
|
|
|
Map<String, Object> totalItem = new HashMap<>();
|
|
|
totalItem.put("costItemName", "合计");
|
|
|
+ totalItem.put("serialNumber", ""); // 合计行没有序号
|
|
|
|
|
|
Map<String, String> totalValues = new HashMap<>();
|
|
|
|
|
|
for (String year : years) {
|
|
|
BigDecimal total = BigDecimal.ZERO;
|
|
|
|
|
|
- for (Map<String, String> projectYearData : groupedData.values()) {
|
|
|
- String valueStr = projectYearData.get(year);
|
|
|
+ for (Map<String, Object> itemData : groupedData.values()) {
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ Map<String, String> yearData = (Map<String, String>) itemData.get("yearData");
|
|
|
+ String valueStr = yearData != null ? yearData.get(year) : null;
|
|
|
if (valueStr != null && !valueStr.trim().isEmpty()) {
|
|
|
try {
|
|
|
- // 移除逗号等分隔符
|
|
|
String cleanValue = valueStr.replaceAll("[^\\d.-]", "");
|
|
|
if (!cleanValue.isEmpty()) {
|
|
|
BigDecimal value = new BigDecimal(cleanValue);
|
|
|
@@ -209,7 +234,7 @@ public class CostDataUtil {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 格式化合计值(添加千分位)
|
|
|
+ // 格式化合计值
|
|
|
String totalStr = total.compareTo(BigDecimal.ZERO) > 0 ?
|
|
|
formatNumberWithCommas(total) : "";
|
|
|
totalValues.put(year, totalStr);
|
|
|
@@ -235,7 +260,6 @@ public class CostDataUtil {
|
|
|
private String extractYearNumber(String nianfen) {
|
|
|
if (nianfen == null) return null;
|
|
|
|
|
|
- // 匹配4位数字年份
|
|
|
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("\\d{4}");
|
|
|
java.util.regex.Matcher matcher = pattern.matcher(nianfen);
|
|
|
if (matcher.find()) {
|
|
|
@@ -245,46 +269,6 @@ public class CostDataUtil {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 比较中文序号和数字序号
|
|
|
- */
|
|
|
- private int compareChineseAndNumber(String xuhao1, String xuhao2) {
|
|
|
- // 中文序号映射
|
|
|
- Map<String, Integer> chineseMap = new HashMap<>();
|
|
|
- chineseMap.put("一", 1);
|
|
|
- chineseMap.put("二", 2);
|
|
|
- chineseMap.put("三", 3);
|
|
|
- chineseMap.put("四", 4);
|
|
|
- chineseMap.put("五", 5);
|
|
|
- chineseMap.put("六", 6);
|
|
|
- chineseMap.put("七", 7);
|
|
|
- chineseMap.put("八", 8);
|
|
|
- chineseMap.put("九", 9);
|
|
|
- chineseMap.put("十", 10);
|
|
|
-
|
|
|
- // 尝试将字符串转换为数字
|
|
|
- Integer num1 = chineseMap.get(xuhao1);
|
|
|
- Integer num2 = chineseMap.get(xuhao2);
|
|
|
-
|
|
|
- if (num1 == null) {
|
|
|
- try {
|
|
|
- num1 = Integer.parseInt(xuhao1);
|
|
|
- } catch (NumberFormatException e) {
|
|
|
- num1 = Integer.MAX_VALUE; // 无法转换的排到最后
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (num2 == null) {
|
|
|
- try {
|
|
|
- num2 = Integer.parseInt(xuhao2);
|
|
|
- } catch (NumberFormatException e) {
|
|
|
- num2 = Integer.MAX_VALUE; // 无法转换的排到最后
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return Integer.compare(num1, num2);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
* 格式化数字(添加千分位)
|
|
|
*/
|
|
|
private String formatNumberWithCommas(BigDecimal number) {
|
|
|
@@ -303,76 +287,100 @@ public class CostDataUtil {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 使用示例
|
|
|
+ * 测试方法 - 模拟您的数据
|
|
|
*/
|
|
|
public static void main(String[] args) {
|
|
|
- // 模拟你的查询数据
|
|
|
+ // 模拟您的查询数据(orderNum不是按顺序查询出来的)
|
|
|
List<Map<String, Object>> maps = new ArrayList<>();
|
|
|
|
|
|
- // 添加测试数据(根据你提供的数据)
|
|
|
- addRow(maps, "一", "人数", "2024年核定值", "");
|
|
|
- addRow(maps, "一", "人数", "2025年核定值", "");
|
|
|
- addRow(maps, "1", "1班", "2024年核定值", "");
|
|
|
- addRow(maps, "1", "1班", "2025年核定值", "");
|
|
|
- addRow(maps, "2", "2班", "2024年核定值", "");
|
|
|
- addRow(maps, "2", "2班", "2025年核定值", "");
|
|
|
- addRow(maps, "二", "1班费用", "2024年核定值", "");
|
|
|
- addRow(maps, "二", "1班费用", "2025年核定值", "");
|
|
|
- addRow(maps, "1", "押金", "2024年核定值", "");
|
|
|
- addRow(maps, "1", "押金", "2025年核定值", "");
|
|
|
- addRow(maps, "2", "缴纳", "2024年核定值", "");
|
|
|
- addRow(maps, "2", "缴纳", "2025年核定值", "");
|
|
|
- addRow(maps, "三", "班级乘法", "2024年核定值", "556");
|
|
|
- addRow(maps, "三", "班级乘法", "2025年核定值", "85");
|
|
|
- addRow(maps, "四", "人均费用", "2024年核定值", "223");
|
|
|
- addRow(maps, "四", "人均费用", "2025年核定值", "225");
|
|
|
+ // 注意:这里故意不按orderNum顺序添加数据
|
|
|
+ addRow(maps, "一", "人数", "2025年核定值", "2", "1");
|
|
|
+ addRow(maps, "一", "人数", "2026年核定值", "2", "1");
|
|
|
+ addRow(maps, "2", "2班", "2025年核定值", "2", "3");
|
|
|
+ addRow(maps, "2", "2班", "2026年核定值", "6", "3");
|
|
|
+ addRow(maps, "二", "电费", "2025年核定值", "2", "4");
|
|
|
+ addRow(maps, "二", "电费", "2026年核定值", "8", "4");
|
|
|
+ addRow(maps, "1", "1班", "2025年核定值", "2", "2");
|
|
|
+ addRow(maps, "1", "1班", "2026年核定值", "4", "2");
|
|
|
+ addRow(maps, "四", "班费率", "2025年核定值", "2", "9");
|
|
|
+ addRow(maps, "四", "班费率", "2026年核定值", "18", "9");
|
|
|
+ addRow(maps, "2", "押金", "2025年核定值", "2", "6");
|
|
|
+ addRow(maps, "2", "押金", "2026年核定值", "12", "6");
|
|
|
+ addRow(maps, "三", "总班费", "2025年核定值", "2", "7");
|
|
|
+ addRow(maps, "三", "总班费", "2026年核定值", "14", "7");
|
|
|
+ addRow(maps, "1", "总支出", "2025年核定值", "2", "5");
|
|
|
+ addRow(maps, "1", "总支出", "2026年核定值", "10", "5");
|
|
|
+ addRow(maps, "1", "个人班费", "2025年核定值", "2", "8");
|
|
|
+ addRow(maps, "1", "个人班费", "2026年核定值", "16", "8");
|
|
|
+
|
|
|
+ System.out.println("原始查询数据(不按orderNum顺序):");
|
|
|
+ System.out.println("=================================");
|
|
|
+ for (int i = 0; i < maps.size(); i += 2) {
|
|
|
+ Map<String, Object> row = maps.get(i);
|
|
|
+ System.out.printf("序号:%s 项目:%s orderNum:%s\n",
|
|
|
+ row.get("xuhao"),
|
|
|
+ row.get("xiangmu"),
|
|
|
+ row.get("orderNum"));
|
|
|
+ }
|
|
|
|
|
|
CostDataUtil converter = new CostDataUtil();
|
|
|
Map<String, Object> result = converter.convertToCostFormat(maps);
|
|
|
|
|
|
// 输出结果
|
|
|
- System.out.println("Years: " + result.get("years"));
|
|
|
+ System.out.println("\n\n转换后结果(按orderNum排序):");
|
|
|
+ System.out.println("================================");
|
|
|
+ System.out.println("成本项目\t行次\t2025年度\t2026年度");
|
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
List<Map<String, Object>> costItems = (List<Map<String, Object>>) result.get("costItems");
|
|
|
|
|
|
- System.out.println("\nCost Items:");
|
|
|
for (Map<String, Object> item : costItems) {
|
|
|
String costItemName = (String) item.get("costItemName");
|
|
|
- System.out.println("\n项目: " + costItemName);
|
|
|
+ String serialNumber = (String) item.get("serialNumber");
|
|
|
+ String orderNum = (String) item.get("orderNum");
|
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
Map<String, String> yearValues = (Map<String, String>) item.get("yearValues");
|
|
|
|
|
|
- @SuppressWarnings("unchecked")
|
|
|
- List<String> years = (List<String>) result.get("years");
|
|
|
-
|
|
|
- for (String year : years) {
|
|
|
- String value = yearValues.get(year);
|
|
|
- System.out.println(" " + year + "年: " + (value != null && !value.isEmpty() ? value : ""));
|
|
|
+ String year2025 = yearValues.get("2025");
|
|
|
+ String year2026 = yearValues.get("2026");
|
|
|
+
|
|
|
+ if ("合计".equals(costItemName)) {
|
|
|
+ System.out.printf("%s\t%s\t%s\t%s\n",
|
|
|
+ costItemName,
|
|
|
+ serialNumber,
|
|
|
+ year2025 != null ? year2025 : "",
|
|
|
+ year2026 != null ? year2026 : "");
|
|
|
+ } else {
|
|
|
+ System.out.printf("%s\t%s\t%s\t%s\t(orderNum=%s)\n",
|
|
|
+ costItemName,
|
|
|
+ serialNumber,
|
|
|
+ year2025 != null ? year2025 : "",
|
|
|
+ year2026 != null ? year2026 : "",
|
|
|
+ orderNum);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ System.out.println("\n排序说明:完全按照orderNum数值大小排序,与查询顺序无关");
|
|
|
}
|
|
|
|
|
|
private static void addRow(List<Map<String, Object>> list,
|
|
|
String xuhao, String xiangmu,
|
|
|
- String nianfen, String shuzhi) {
|
|
|
+ String nianfen, String shuzhi, String orderNum) {
|
|
|
Map<String, Object> row = new HashMap<>();
|
|
|
row.put("xuhao", xuhao);
|
|
|
row.put("xiangmu", xiangmu);
|
|
|
row.put("nianfen", nianfen);
|
|
|
row.put("shuzhi", shuzhi);
|
|
|
+ row.put("orderNum", orderNum);
|
|
|
list.add(row);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+ // 原有的日期转换方法保持不变...
|
|
|
public static String convertToChineseDate(String dateStr) {
|
|
|
if(StringUtil.isEmpty(dateStr)){
|
|
|
return dateStr;
|
|
|
}
|
|
|
- // 定义多种可能的日期格式
|
|
|
List<String> patterns = Arrays.asList(
|
|
|
"yyyy-MM-dd",
|
|
|
"yyyy/MM/dd",
|
|
|
@@ -387,33 +395,25 @@ public class CostDataUtil {
|
|
|
try {
|
|
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
|
|
LocalDate date = LocalDate.parse(dateStr, formatter);
|
|
|
-
|
|
|
- // 转换为中文格式
|
|
|
DateTimeFormatter chineseFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
|
|
|
return date.format(chineseFormatter);
|
|
|
} catch (DateTimeParseException e) {
|
|
|
- // 继续尝试其他格式
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 如果不是日期,返回原字符串
|
|
|
return dateStr;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
public static String convert(String input) {
|
|
|
- // 先尝试精确匹配日期格式
|
|
|
for (DateTimeFormatter formatter : FORMATTERS) {
|
|
|
try {
|
|
|
LocalDate date = LocalDate.parse(input, formatter);
|
|
|
return date.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"));
|
|
|
} catch (DateTimeParseException e) {
|
|
|
- // 继续尝试下一个格式
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 如果不是标准格式,可以添加正则表达式检测
|
|
|
if (isLikelyDate(input)) {
|
|
|
return tryParseUnusualDate(input);
|
|
|
}
|
|
|
@@ -422,29 +422,21 @@ public class CostDataUtil {
|
|
|
}
|
|
|
|
|
|
private static boolean isLikelyDate(String str) {
|
|
|
- // 简单的日期特征检测
|
|
|
return str.matches(".*\\d{4}.*\\d{1,2}.*\\d{1,2}.*") ||
|
|
|
str.matches("\\d{1,2}[-/.]\\d{1,2}[-/.]\\d{4}");
|
|
|
}
|
|
|
|
|
|
private static String tryParseUnusualDate(String str) {
|
|
|
- // 尝试清理和转换非标准日期
|
|
|
try {
|
|
|
- // 移除非数字字符,保留数字
|
|
|
String numbers = str.replaceAll("[^0-9]", "");
|
|
|
-
|
|
|
if (numbers.length() == 8) {
|
|
|
- // 假设是 yyyyMMdd 格式
|
|
|
String year = numbers.substring(0, 4);
|
|
|
String month = numbers.substring(4, 6);
|
|
|
String day = numbers.substring(6, 8);
|
|
|
return year + "年" + month + "月" + day + "日";
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
- // 转换失败
|
|
|
}
|
|
|
return str;
|
|
|
}
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
+}
|