修复util

This commit is contained in:
yuejiajun 2025-09-28 15:06:51 +08:00
parent 42b3f26e73
commit cea42fdfbd
2 changed files with 134 additions and 162 deletions

View File

@ -627,110 +627,109 @@ public class FormatUtil {
* 坐标系转换 - 经纬度格式转换
*
* <p>支持不同格式的经纬度坐标转换如度分秒转十进制十进制转度分秒等</p>
* 转换逻辑说明
* 1. 度分秒格式(dms)通常表示为°'"例如116°23'45.67"
* 2. 十进制格式(decimal)表示为小数形式例如116.396019
* 3. 转换精度通过参数控制默认为6位小数
*
* @param coordinate 原始坐标字符串
* @param coordinate 原始坐标字符串不能为空
* @param params 参数映射包含
* - fromFormat: 原始格式"dms"-度分秒, "decimal"-十进制
* - toFormat: 目标格式"dms"-度分秒, "decimal"-十进制
* - precision: 精度小数位数默认6
* @return 转换后的坐标字符串
* - fromFormat: 原始格式"dms"-度分秒, "decimal"-十进制默认"decimal"
* - toFormat: 目标格式"dms"-度分秒, "decimal"-十进制默认"decimal"
* - precision: 精度小数位数默认6用于十进制结果或作为秒小数位的默认值
* - secondsPrecision: 秒的小数位数仅用于度分秒结果优先级高于precision
* @return 转换后的坐标字符串转换失败时返回原始坐标
*/
public static String coordinateConvert(String coordinate, Map<String, Object> params) {
// 校验输入坐标是否为空
if (coordinate == null || coordinate.trim().isEmpty()) {
return coordinate;
}
// 获取转换参数使用默认值处理未提供的参数
String fromFormat = params.containsKey("fromFormat") ?
params.get("fromFormat").toString() : "decimal";
String toFormat = params.containsKey("toFormat") ?
params.get("toFormat").toString() : "decimal";
int precision = params.containsKey("precision") ?
Integer.parseInt(params.get("precision").toString()) : 6;
// 秒的小数位数优先使用secondsPrecision否则使用precision
int secondsPrecision = params.containsKey("secondsPrecision") ?
Integer.parseInt(params.get("secondsPrecision").toString()) : precision;
try {
// 格式相同则直接返回原始坐标
if (fromFormat.equals(toFormat)) {
return coordinate; // 格式相同直接返回
return coordinate;
}
if (fromFormat.equals("dms") && toFormat.equals("decimal")) {
// 度分秒转十进制
if (fromFormat.equals("dms") && toFormat.equals("decimal")) {
return dmsToDecimal(coordinate, precision);
} else if (fromFormat.equals("decimal") && toFormat.equals("dms")) {
}
// 十进制转度分秒
return decimalToDms(coordinate, precision);
else if (fromFormat.equals("decimal") && toFormat.equals("dms")) {
return decimalToDms(coordinate, secondsPrecision);
}
return coordinate; // 不支持的转换类型
// 不支持的转换类型返回原始坐标
return coordinate;
} catch (Exception e) {
return coordinate; // 转换失败返回原字符串
// 转换过程中发生异常返回原始坐标
return coordinate;
}
}
/**
* 度分秒转十进制
* 度分秒格式坐标换为十进制格式
*
* @param dms 度分秒格式字符串116°23'45.67"
* @param precision 精度
* @return 十进制格式坐标
* @param dmsStr 度分秒格式字符串例如116°23'45.67"
* @param precision 十进制结果的小数位数
* @return 十进制格式的坐标字符串
* @throws NumberFormatException 当输入格式不正确时抛出
*/
private static String dmsToDecimal(String dms, int precision) {
try {
// 提取度
Pattern pattern = Pattern.compile("([+-]?\\d+)[°]?\\s*([\\d.]+)?[']?\\s*([\\d.]+)?[\"″]?");
Matcher matcher = pattern.matcher(dms);
private static String dmsToDecimal(String dmsStr, int precision) throws NumberFormatException {
// 移除所有非数字和小数点的特殊字符保留度数符号前的数字
String[] parts = dmsStr.replaceAll("[°′'\"]", ",").split(",");
if (matcher.find()) {
double degrees = Double.parseDouble(matcher.group(1));
double minutes = 0;
double seconds = 0;
// 解析度秒的值
double degrees = Double.parseDouble(parts[0].trim());
double minutes = Double.parseDouble(parts[1].trim());
double seconds = Double.parseDouble(parts[2].trim());
if (matcher.group(2) != null) {
minutes = Double.parseDouble(matcher.group(2));
}
if (matcher.group(3) != null) {
seconds = Double.parseDouble(matcher.group(3));
}
// 计算十进制度数 + /60 + /3600
double decimal = degrees + minutes / 60 + seconds / 3600;
// 计算十进制
double decimal = degrees + minutes/60.0 + seconds/3600.0;
// 格式化输出
String format = "%." + precision + "f";
return String.format(format, decimal);
}
} catch (Exception e) {
// 解析失败
}
return dms;
// 格式化输出精度
return String.format("%." + precision + "f", decimal);
}
/**
* 十进制转度分秒
* 将十进制格式坐标转换为度分秒格式
*
* @param decimal 十进制格式坐标
* @param precision 精度
* @return 度分秒格式字符串
* @param decimalStr 十进制格式字符串例如116.396019
* @param secondsPrecision 秒的小数位数
* @return 度分秒格式的坐标字符串例如116°23'45.67"
* @throws NumberFormatException 当输入不是有效的数字时抛出
*/
private static String decimalToDms(String decimal, int precision) {
try {
double value = Double.parseDouble(decimal);
boolean isNegative = value < 0;
value = Math.abs(value);
private static String decimalToDms(String decimalStr, int secondsPrecision) throws NumberFormatException {
// 解析十进制数值
double decimal = Double.parseDouble(decimalStr.trim());
// 提取度
int degrees = (int) Math.floor(value);
double minutesDecimal = (value - degrees) * 60;
int minutes = (int) Math.floor(minutesDecimal);
double seconds = (minutesDecimal - minutes) * 60;
// 获取度数部分整数部分
int degrees = (int) Math.floor(Math.abs(decimal));
// 格式化输出
String sign = isNegative ? "-" : "";
String format = "%s%d°%d'%." + Math.max(0, precision-2) + "f\"";
return String.format(format, sign, degrees, minutes, seconds);
} catch (Exception e) {
// 解析失败
}
return decimal;
// 计算剩余的小数部分并转换为分
double remaining = Math.abs(decimal) - degrees;
double totalMinutes = remaining * 60;
int minutes = (int) Math.floor(totalMinutes);
// 计算剩余的秒数
double seconds = (totalMinutes - minutes) * 60;
// 格式化输出添加度数符号分符号和秒符号使用指定的秒小数位数
String format = "%d°%d'%." + secondsPrecision + "f\"";
return String.format(format, degrees, minutes, seconds);
}
/**

View File

@ -74,7 +74,7 @@ public class FormatUtilTest {
* <p><b>预期结果</b>转换后的时间格式正确</p>
*/
@Test
@DisplayName("formatTime方法测试 - 正常格式转换")
@DisplayName("formatTime方法测试 - 正常格式转换 - 【已验证】")
void testFormatTime_NormalConversion() {
System.out.println();
log.info("========== 时间格式化模块测试 - 正常格式转换 ==========");
@ -89,17 +89,13 @@ public class FormatUtilTest {
log.info(" - 源格式: {}", params.get("fromFormat"));
log.info(" - 目标格式: {}", params.get("toFormat"));
// 预期结果
String expectedResult = "2024/01/15";
log.info("预期结果: {}", expectedResult);
// 执行测试
Object result = FormatUtil.formatTime(inputTime, params);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证
String expectedResult = "2024/01/15";
log.info("预期结果: {}", expectedResult);
log.info("实际结果: {}", result);
assertEquals(expectedResult, result);
log.info("✓ 测试通过 - 格式转换结果正确");
}
@ -112,7 +108,7 @@ public class FormatUtilTest {
* <p><b>预期结果</b>返回空字符串或默认值</p>
*/
@Test
@DisplayName("formatTime方法测试 - 空值处理")
@DisplayName("formatTime方法测试 - 空值处理 - 【已验证】")
void testFormatTime_EmptyInput() {
System.out.println();
log.info("========== 时间格式化模块测试 - 空值处理 ==========");
@ -185,7 +181,7 @@ public class FormatUtilTest {
* <p><b>预期结果</b>正确提取开始时间</p>
*/
@Test
@DisplayName("extractTimeRange方法测试 - 正常提取开始时间")
@DisplayName("extractTimeRange方法测试 - 正常提取开始时间 - 【已验证】")
void testExtractTimeRange_ExtractStartTime() {
System.out.println();
log.info("========== 时间范围提取模块测试 - 正常提取开始时间 ==========");
@ -198,17 +194,11 @@ public class FormatUtilTest {
log.info(" - 时间范围字符串: {}", inputTimeRange);
log.info(" - 提取类型: {}", params.get("type"));
// 预期结果
String expectedResult = "2024-01-15 14:30:25";
log.info("预期结果: {}", expectedResult);
// 执行测试
Object result = FormatUtil.extractTimeRange(inputTimeRange, params);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证
String expectedResult = "2024-01-15 14:30:25";
log.info("预期结果:'{}'", expectedResult);
log.info("实际结果:'{}'", result);
assertEquals(expectedResult, result);
@ -220,10 +210,10 @@ public class FormatUtilTest {
*
* <p><b>测试目的</b>验证extractTimeRange方法对无分隔符情况的处理</p>
* <p><b>测试场景</b>时间范围字符串中无分隔符</p>
* <p><b>预期结果</b>返回原始字符串或错误信息</p>
* <p><b>预期结果</b>返回原始字符串</p>
*/
@Test
@DisplayName("extractTimeRange方法测试 - 无分隔符处理")
@DisplayName("extractTimeRange方法测试 - 无分隔符处理 - 【已验证】")
void testExtractTimeRange_NoSeparator() {
System.out.println();
log.info("========== 时间范围提取模块测试 - 无分隔符处理 ==========");
@ -490,7 +480,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>替换结果正确</p>
*/
@Test
@DisplayName("regexReplace方法测试 - 正则替换")
@DisplayName("regexReplace方法测试 - 正则替换 - 【已验证】")
void testRegexReplace_NormalCase() {
System.out.println();
log.info("========== 正则表达式替换模块测试 - 正则替换 ==========");
@ -507,17 +497,13 @@ public class FormatUtilTest {
log.info(" - 正则表达式: {}", regex);
log.info(" - 替换字符串: {}", replacement);
// 预期结果
String expectedResult = "abc*def*";
log.info("预期结果: {}", expectedResult);
// 执行测试
Object result = FormatUtil.regexReplace(inputString, params);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证
String expectedResult = "abc*def*";
log.info("预期结果: {}", expectedResult);
log.info("实际结果: {}", result);
assertEquals(expectedResult, result);
log.info("✓ 测试通过 - 正则替换正确");
}
@ -530,7 +516,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>替换结果正确</p>
*/
@Test
@DisplayName("regexReplace方法测试 - 三种测试")
@DisplayName("regexReplace方法测试 - 三种测试 - 【已验证】")
void testRegexReplace_NormalCase3() {
System.out.println();
log.info("========== 正则表达式替换模块测试 - 正则替换 ==========");
@ -624,7 +610,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>去除空格后结果正确</p>
*/
@Test
@DisplayName("trim方法测试 - 去除空格")
@DisplayName("trim方法测试 - 去除空格 - 【已验证】")
void testTrim_NormalCase() {
System.out.println();
log.info("========== 字符串空格处理模块测试 - 去除空格 ==========");
@ -636,17 +622,13 @@ public class FormatUtilTest {
log.info(" - 输入字符串: '{}'", inputString);
log.info(" - 注意: 字符串前后有空格");
// 预期结果
String expectedResult = "hello world";
log.info("预期结果: '{}'", expectedResult);
// 执行测试
Object result = FormatUtil.trim(inputString, params);
// 实际结果
log.info("实际结果: '{}'", result);
// 断言验证
String expectedResult = "hello world";
log.info("预期结果: '{}'", expectedResult);
log.info("实际结果: '{}'", result);
assertEquals(expectedResult, result);
log.info("✓ 测试通过 - 空格去除正确");
}
@ -697,7 +679,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>大小写敏感替换结果正确</p>
*/
@Test
@DisplayName("stealBeamsAndReplacePillars方法测试 - 大小写敏感")
@DisplayName("stealBeamsAndReplacePillars方法测试 - 大小写敏感 - 【已验证】")
void testStealBeamsAndReplacePillars_CaseSensitive() {
System.out.println();
log.info("========== 字符串替换模块测试 - 大小写敏感替换 ==========");
@ -715,17 +697,13 @@ public class FormatUtilTest {
log.info(" - 大小写敏感: {}", caseSensitive);
log.info(" - 注意: 'Hello'与'hello'大小写不匹配");
// 预期结果
String expectedResult = "hello universe";
log.info("预期结果:'{}'", expectedResult);
// 执行测试
String result = FormatUtil.stealBeamsAndReplacePillars(inputString, replacementMap, caseSensitive);
// 实际结果
log.info("实际结果:'{}'", result);
// 断言验证
String expectedResult = "hello universe";
log.info("预期结果:'{}'", expectedResult);
log.info("实际结果:'{}'", result);
assertEquals(expectedResult, result);
log.info("✓ 测试通过 - 大小写敏感替换正确");
}
@ -820,31 +798,26 @@ public class FormatUtilTest {
* <p><b>预计结果</b>转换结果正确</p>
*/
@Test
@DisplayName("coordinateConvert方法测试 - 十进制转度分秒")
@DisplayName("coordinateConvert方法测试 - 十进制转度分秒 - 【已验证】")
void testCoordinateConvert_DecimalToDms() {
System.out.println();
log.info("========== 坐标系转换模块测试 - 十进制转度分秒 ==========");
// 输入参数
String coordinate = "116.396019";
params.put("fromType", "decimal");
params.put("toType", "dms");
params.put("fromFormat", "decimal");
params.put("toFormat", "dms");
params.put("precision", "2");
log.info("输入参数:");
log.info(" - 坐标值: {}", coordinate);
log.info(" - 源格式: {}", params.get("fromType"));
log.info(" - 目标格式: {}", params.get("toType"));
log.info(" - 源格式: {}", params.get("fromFormat"));
log.info(" - 目标格式: {}", params.get("toFormat"));
log.info(" - 注意: 116.396019 ≈ 116°23'45.67\"");
// 预期结果
log.info("预期结果: 非空转换结果");
// 执行测试
Object result = FormatUtil.coordinateConvert(coordinate, params);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证
String expectedResult = "116°23'45.67\"";
log.info("预期结果:'{}'", expectedResult);
@ -1106,7 +1079,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>转换结果正确</p>
*/
@Test
@DisplayName("kvMapping方法测试 - 键名格式转换")
@DisplayName("kvMapping方法测试 - 键名格式转换 - 【验证中】")
void testKvMapping_KeyFormatConversion() {
System.out.println();
log.info("========== 数据KV映射模块测试 - 键名格式转换 ==========");
@ -1186,7 +1159,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>排序结果正确</p>
*/
@Test
@DisplayName("kvMapping方法测试 - 分组排序")
@DisplayName("kvMapping方法测试 - 分组排序 - 【已验证】")
void testKvMapping_GroupingSorting() {
System.out.println();
log.info("========== 数据KV映射模块测试 - 分组排序 ==========");
@ -1384,17 +1357,17 @@ public class FormatUtilTest {
}
/**
* 异常处理测试 - 无效参数组合
* 默认参数值
*
* <p><b>测试目的</b>验证方法对无效参数组合的容错能力</p>
* <p><b>测试场景</b>提供相互冲突的参数</p>
* <p><b>预计结果</b>返回合理的错误信息或默认值</p>
* <p><b>预计结果</b>返回合理的默认值</p>
*/
@Test
@DisplayName("异常处理测试 - 无效参数组合")
@DisplayName("formatTime - 默认参数值 - 【已验证】")
void testErrorHandling_InvalidParameterCombination() {
System.out.println();
log.info("========== 异常处理测试 - 无效参数组合 ==========");
log.info("========== 默认参数值 ==========");
// 输入参数
String inputTime = "2024-01-15";
@ -1408,16 +1381,16 @@ public class FormatUtilTest {
log.info(" - 注意: 日期格式到时间格式的无效转换");
// 预期结果
log.info("预期结果: 返回合理的错误信息或默认值");
log.info("预期结果: 返回默认值");
// 执行测试
Object result = FormatUtil.formatTime(inputTime, params);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证
assertNotNull(result);
String expectedResult = "00:00:00";
log.info("预期结果: {}", expectedResult);
log.info("实际结果: {}", result);
assertEquals(expectedResult, result);
log.info("✓ 测试通过 - 异常处理正确");
}