package com.czlis.interfaceCommon.utils; import com.czlis.common.utils.DateUtils; import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.time.Duration; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.Calendar; import java.util.Date; import java.util.Map; public class LisUtil { // 换行符常量(跨平台) public static final String LINE_SEPARATOR = System.lineSeparator(); /** * 生日格式为:yyyy-MM-dd * 根据出生日期计算年龄 * @param birthday * @return */ public static Map getAgeFromBirthDay(String birthday){ return AgeUtils.getAgeFromBirthDay(birthday); } /** * 根据年龄获取出生日期 * @param nl * @return */ public static Date getBirthDayFromAge(int nl, String nldw) { return AgeUtils.getBirthDayFromAge(nl,nldw); } /** * 按GBK编码的字节宽度截取字符串,最多取cutlens个字节(避免截取半个汉字) * @param str 原始字符串 * @param beginidx 起始位置 * @param cutlens 截取长度 * @return 截取后的字符串 */ public static String substringByGbkWidth(String str,int beginidx,int cutlens) { if (str == null || str.isEmpty()) { return ""; } int targetWidth = cutlens; // 目标字节宽度 int currentWidth =beginidx; // 当前累计字节宽度 StringBuilder result = new StringBuilder(); for (char c : str.toCharArray()) { // 计算当前字符在GBK编码下的字节数 int charWidth; try { // GBK编码中,汉字占2字节,英文等占1字节 charWidth = String.valueOf(c).getBytes("GBK").length; } catch (UnsupportedEncodingException e) { // 理论上GBK是Java默认支持的编码,不会走到这里 throw new RuntimeException("不支持GBK编码", e); } // 判断加上当前字符后是否超过目标宽度 if (currentWidth + charWidth > targetWidth) { break; // 超过则停止,不截取当前字符 } // 未超过则累加宽度并添加字符 currentWidth += charWidth; result.append(c); // 如果刚好达到目标宽度,提前结束 if (currentWidth == targetWidth) { break; } } return result.toString(); } /** * 使用正则表达式判断字符串是否为数字 * 支持:整数(123)、小数(123.45)、正负号(-123、+45.6) */ public static boolean isNumber(String str) { if (str == null || str.trim().isEmpty()) { return false; } // 正则表达式:匹配正负整数、正负小数 String regex = "^[+-]?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)$"; return str.matches(regex); } /** * 使用正则表达式判断字符串是否为数字 * 支持:整数(123)、小数(123.45),不包括带正负号的情况 */ public static boolean isTureNumber(String str) { if (str == null || str.trim().isEmpty()) { return false; } // 正则表达式:仅匹配正整数、正小数(不包含正负号) // 说明: // ^[0-9]+(\.[0-9]*)?$ 匹配整数(如123)或带整数部分的小数(如123.45) // |\.([0-9]+)$ 匹配纯小数(如.67) String regex = "^[0-9]+(\\.[0-9]*)?|\\.[0-9]+$"; return str.matches(regex); } /** * 将包含比较运算符的字符串转换为特定格式的数值字符串 * 不支持的格式或非数字内容将返回原值 * @param input 输入字符串,如">=123", ">123", "<=123", "<123" * @return 转换后的字符串或原值 */ public static String getOverNumber(String input) { // 输入为空时返回原值 if (input == null || input.trim().isEmpty()) { return input; } // 定义支持的运算符,按长度排序以便正确识别(先长后短) String[] operators = {">=", "<=", ">", "<"}; String operator = null; String numberPart = null; // 识别运算符和数字部分 for (String op : operators) { if (input.startsWith(op)) { operator = op; numberPart = input.substring(op.length()); break; } } // 未识别到支持的运算符,返回原值 if (operator == null) { return input; } // 尝试将数字部分转换为double double number; try { number = Double.parseDouble(numberPart); } catch (NumberFormatException e) { // 数字部分格式不正确,返回原值 return input; } // 根据运算符进行转换 switch (operator) { case ">=": case ">": return String.format("%.4f", number + 0.0001); case "<=": case "<": return String.format("%.4f", number - 0.0001); default: return input; } } /** 保留指定小数位数(四舍五入) 支持比较符号 (<=、>=、<、>) 和负号 (-) 同时存在的情况 @param input 输入字符串,如 "123.1234"、">123.252"、"<=123.252"、"-45.67"、">=-89.01" @param decimalPlaces 要保留的小数位数,需为非负整数 @return 格式化后的字符串,无法处理时返回原值 */ public static String round (String input, int decimalPlaces) { // 处理空输入或无效小数位数 if (input == null || input.trim ().isEmpty () || decimalPlaces < 0) { return input; } // 定义比较运算符前缀(按长度排序,确保正确识别) String [] comparisonPrefixes = {"<=", ">=", "<", ">"}; String comparisonPrefix = ""; String remainingPart = input.trim (); // 去除首尾空格 // 提取比较运算符前缀 for (String prefix : comparisonPrefixes) { if (remainingPart.startsWith (prefix)) { comparisonPrefix = prefix; remainingPart = remainingPart.substring (prefix.length ()).trim (); // 去除前缀后的空格 break; } } // 尝试解析剩余部分为数字(使用 BigDecimal 避免精度问题) try { // 解析为 BigDecimal(支持正负号和小数) BigDecimal number = new BigDecimal (remainingPart); // 设置四舍五入模式并保留指定小数位数 BigDecimal rounded = number.setScale (decimalPlaces, RoundingMode.HALF_UP); // 拼接比较前缀和格式化后的数字 return comparisonPrefix + rounded.toPlainString (); //toPlainString 避免科学计数法 } catch (NumberFormatException e) { // 数字部分无法解析时返回原值 return input; } } /** * 根据天数返回日期,正数往后推,负数往前推 * @param day * @return */ public static Date relativeDate(int day) { // 1. 获取当前时间(基于Calendar) Calendar calendar = Calendar.getInstance(); // 当前时间 calendar.add(Calendar.DAY_OF_MONTH, day); // 2重置时间为00:00:00 calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); // 3. 返回推算的出生日期 return calendar.getTime(); } public static Date relativeDate(Date date,int day) { // 1. 获取当前时间(基于Calendar) Calendar calendar =Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.DAY_OF_MONTH, day); // 2重置时间为00:00:00 calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); // 3. 返回推算的出生日期 return calendar.getTime(); } /** * 根据天数返回日期时间,正数往后推,负数往前推 * @param day * @return */ public static Date relativeDateTime(int day) { // 1. 获取当前时间(基于Calendar) Calendar calendar = Calendar.getInstance(); // 当前时间 // 2天:忽略小时,按整天推算 calendar.add(Calendar.DAY_OF_MONTH, day); // 3. 返回推算的时间 return calendar.getTime(); } public static Date relativeDateTime(Date date,int day) { // 1. 获取当前时间(基于Calendar) Calendar calendar = Calendar.getInstance(); // 当前时间 calendar.setTime(date); // 2天:忽略小时,按整天推算 calendar.add(Calendar.DAY_OF_MONTH, day); // 3. 返回推算的时间 return calendar.getTime(); } /** * 判断前一个时间与后面时间间隔几分钟 * @param pastDate * @param datenow * @return */ public static long relativeMinute(Date pastDate,Date datenow) { LocalDateTime pastTime = pastDate.toInstant() .atZone(ZoneId.systemDefault()) .toLocalDateTime(); LocalDateTime now = datenow.toInstant() .atZone(ZoneId.systemDefault()) .toLocalDateTime(); long minutesDiff = Duration.between(pastTime, now).toMinutes(); return minutesDiff; } /** * 判断一个时间与当前时间间隔几分钟 * @param pastDate * @return */ public static long relativeMinute(Date pastDate) { return relativeMinute(pastDate,new Date()); } /** * 获取实体类中指定字段的属性和值 * @param obj 实体类对象 * @param fieldName 要查询的字段名 * @return 字段信息字符串 */ public static String getFieldValue(Object obj, String fieldName) { if (obj == null || fieldName == null || fieldName.isEmpty()) { return "参数不能为空"; } Class clazz = obj.getClass(); try { // 获取指定字段(包括私有字段) Field field = clazz.getDeclaredField(fieldName); // 设置访问权限(私有字段需要开启) field.setAccessible(true); // 1. 获取字段属性信息 String fieldType = field.getType().getSimpleName(); // 字段类型(如String、Integer) // 2. 获取字段值 Object fieldValue = field.get(obj); // 获取字段值 String valueStr; // 处理特殊类型(如Date格式化) if (fieldValue instanceof Date) { valueStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) fieldValue); } else { valueStr = (fieldValue != null) ? fieldValue.toString() : "null"; } return valueStr; } catch (NoSuchFieldException e) { return "字段不存在:" + fieldName; } catch (IllegalAccessException e) { return "无法访问字段:" + fieldName + ",原因:" + e.getMessage(); } } public static String getFieldType(Object obj, String fieldName) { if (obj == null || fieldName == null || fieldName.isEmpty()) { return "参数不能为空"; } Class clazz = obj.getClass(); try { // 获取指定字段(包括私有字段) Field field = clazz.getDeclaredField(fieldName); // 设置访问权限(私有字段需要开启) field.setAccessible(true); // 1. 获取字段属性信息 return field.getType().getSimpleName(); // 字段类型(如String、Integer) } catch (NoSuchFieldException e) { return "字段不存在:" + fieldName; } } }