diff --git a/smtweb-framework/core/pom.xml b/smtweb-framework/core/pom.xml index 1c29d60..f277f76 100644 --- a/smtweb-framework/core/pom.xml +++ b/smtweb-framework/core/pom.xml @@ -85,6 +85,11 @@ commons-lang3 3.12.0 + + org.dom4j + dom4j + RELEASE + org.apache.commons diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/Consts.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/Consts.java new file mode 100644 index 0000000..aeb9e8f --- /dev/null +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/Consts.java @@ -0,0 +1,21 @@ +package cc.smtweb.framework.core.util; + +public class Consts { + public static final String BLANK_STRING = " "; + public static final String NULL_STRING = "-"; + public static final String TREE_ROOT_ID = "-1"; + public static final String WORD_LINE_BREAK = "" + (char) 11; + public static final String CLASS_ROOT_ID = "GB000"; + public static final String PERSON_TYPE_ROOT_ID = "GP000000"; + public final static String LEVELCODE_SEPARATOR = "-"; + public static final String DEF_PWD = "abc@123456"; //初始密码 + public static final String fileOperator = System.getProperty("file.separator"); + + public static final String TOP_PARTY_ID = "1"; //顶级机构主键 + public static final String TOP_PARTY_DEFAULT_CODE = "10000"; //顶级单位默认机构编码,初始化后可以到系统中进行修改; + + public final static String DEF_SCHEMA = "sys";//默认的数据库名 + + public final static String FIELD_LAST_TIME = "last_time";//最后更新时间,字段名 + public final static String FIELD_CREATE_PARTY = "create_party_id";//创建单位,字段名 +} diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/DateUtil.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/DateUtil.java index 46279e1..08667bd 100644 --- a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/DateUtil.java +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/DateUtil.java @@ -794,6 +794,15 @@ public class DateUtil { if (datetime == null) return null; return new java.sql.Date(datetime.getTime()); } + + //获取当前日期所处月,却掉了前置的0. + public static String nowMonth() { + String month = nowMonth2(); + if (month.charAt(0) == '0') { + return String.valueOf(month.charAt(1)); + } + return month; + } /** * 将字符串转换成Java.sql.Date,不能转换,这返回null * @@ -911,6 +920,52 @@ public class DateUtil { calendar.setTime(new Date()); return getSeasonBegin(calendar); } + public synchronized static java.sql.Date getAfterDate(Date dt, int days) { + if (dt == null) return null; + GregorianCalendar gc = new GregorianCalendar(); + gc.setTime(dt); + gc.add(GregorianCalendar.DATE, days); + return new java.sql.Date(gc.getTimeInMillis()); + } + + //获取季度结束年月,YYYYMM格式 + public static String getSeasonEndYm() { + return getDateYm(getAfterDate(getNextSeasonBegin(), -1)); + } + + //获取年度开始年月,YYYYMM格式 + public static String getYearBeginYm() { + return nowYear() + "01"; + } + + public static String getYearBeginYm(String ymPeriod) { + try { + return ymPeriod.substring(0, 4) + "01"; + } catch (Exception e) { + return nowYear() + "01"; + } + } + + /** + * 获取今日日期串,不带分隔符 + * + * @return 今日日期字符串 yyyyMMdd; + */ + public static String nowDateString() { + return simpleDateFormat.get().format(nowTimestamp()); + } + //获取年度结束年月,YYYYMM格式 + public static String getYearEndYm() { + return nowYear() + "12"; + } + + public static String getYearEndYm(String ymPeriod) { + try { + return ymPeriod.substring(0, 4) + "12"; + } catch (Exception e) { + return nowYear() + "12"; + } + } /** * 得到本季度的第一天 * @@ -979,9 +1034,97 @@ public class DateUtil { return getAfterDays(getAfterMonth(getMonthFirstDay(), 1), -1); } + /** + * 得到本季度最后一天 + * + * @return + */ + public static String getSeasonLastDay() { + String s = toStdDateString(getNextSeasonBegin()); + return getAfterDays(s, -1); + } + //下个季度开始 + public synchronized static Date getNextSeasonBegin() { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + return getNextSeasonBegin(calendar); + } + + public synchronized static Date getNextSeasonBegin(Calendar now) { + int curYear = now.get(Calendar.YEAR); + int curMonth = now.get(Calendar.MONTH); + int seasonMonth = m_seasonBeginTable[curMonth] + 3; + + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.YEAR, curYear); + calendar.set(Calendar.MONTH, seasonMonth); + calendar.set(Calendar.DAY_OF_MONTH, 1); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + calendar.set(Calendar.AM_PM, Calendar.AM); + return new Timestamp(calendar.getTime().getTime()); + } + + //获取季度开始年月,YYYYMM格式 + public static String getSeasonBeginYm() { + return getDateYm(getSeasonBegin()); + } + //获取年月,YYYYMM格式 + public static String getNowYm() { + return getDateYm(nowTimestamp()); + } + public static String getNextYear(String year, int add) { + if (PubUtil.isEmptyId(year)) return year; + int curYear = Integer.parseInt(year) - 1; + return curYear + ""; + } + //获取上一月,YYYYMM格式 + public static String getPrevYear(String year) { + return getNextYear(year, -1); + } + //获取上一月,YYYYMM格式 + public static String getPrevYm(String period_id) { + return getNextYm(period_id, -1); + } + //获取下一月,YYYYMM格式 + public static String getNextYm(String period_id) { + return getNextYm(period_id, 1); + } + //获取年月,YYYYMM格式 + public static String getPrevYm() { + return getPrevYm(getNowYm()); + } + + //获取上一年 YYYY格式 + public static String getPrevYear() { + return getPrevYear(nowYear()); + } + //获取年月,YYYYMM格式 + public static String getNextYm() { + return getNextYm(getNowYm()); + } + public static String getNextYm(String period_id, int add) { + if (PubUtil.isEmptyId(period_id)) return period_id; + int curYear = Integer.parseInt(period_id.substring(0, 4)); + int curMonth = Integer.parseInt(period_id.substring(4)) + add; + if (curMonth > 12) { + do { + curYear++; + curMonth -= 12; + } while (curMonth > 12); + } else if (curMonth <= 0) { + do { + curYear--; + curMonth += 12; + } while (curMonth <= 0); + } + return curYear + StringUtil.getRight("00" + curMonth, 2); + } /** * 得到当前日期所在周次的星期一 * diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/EmojiFilter.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/EmojiFilter.java new file mode 100644 index 0000000..9a2782b --- /dev/null +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/EmojiFilter.java @@ -0,0 +1,73 @@ +package cc.smtweb.framework.core.util; + +/** + * @Author: zhangyulong + * @Date: 2021/10/13 15:16 + */ + +public class EmojiFilter { + + /** + * 过滤emoji 或者 其他非文字类型的字符 + * @param source 需要过滤的字符串 + * @return + */ + public static String filterEmoji(String source) { + if(PubUtil.isEmpty(source)){ + return ""; + } + if (!containsEmoji(source)) { + return source; + } + + StringBuilder buf = null; + int len = source.length(); + for (int i = 0; i < len; i++) { + char codePoint = source.charAt(i); + if (notisEmojiCharacter(codePoint)) { + if (buf == null) { + buf = new StringBuilder(source.length()); + } + buf.append(codePoint); + } + } + + if (buf == null) { + return ""; + } else { + if (buf.length() == len) { + buf = null; + return source; + } else { + return buf.toString(); + } + } + } + + /** + * 检测是否有emoji字符 + * @param source 需要判断的字符串 + * @return 一旦含有就抛出 + */ + public static boolean containsEmoji(String source) { + int len = source.length(); + for (int i = 0; i < len; i++) { + char codePoint = source.charAt(i); + if (!notisEmojiCharacter(codePoint)) { + return true; + } + } + return false; + } + + /** + * 非emoji表情字符判断 + * @param codePoint + * @return + */ + public static boolean notisEmojiCharacter(char codePoint) { + return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA) || (codePoint == 0xD) + || ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) + || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF)); + } +} \ No newline at end of file diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/ListSQLParaHelper.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/ListSQLParaHelper.java new file mode 100644 index 0000000..1a1fcd9 --- /dev/null +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/ListSQLParaHelper.java @@ -0,0 +1,780 @@ +package cc.smtweb.framework.core.util; + +import cc.smtweb.framework.core.common.AbstractEnum; +import cc.smtweb.framework.core.common.IntEnum; +import cc.smtweb.framework.core.common.StrEnum; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +/** + * 注意:where参数表示是否已经加入了where关键字 + * + * @author : AKzz + * @version : $Revision:$ + */ +@SuppressWarnings("UnusedDeclaration") +public abstract class ListSQLParaHelper { + + + /** + * 补充SQL的字符串的==条件 + * + * @param where_is_exist 是否已经加入了where关键字 + */ + public static boolean addSql_EQUALE_Expr(boolean where_is_exist, StringBuilder sql, List args, String db_field_name, int condition_value) { + if (!where_is_exist) { + sql.append(" WHERE "); + } else { + sql.append(" AND "); + } + sql.append(db_field_name).append(" = ? \n"); + args.add(condition_value); + return true; + } + + /** + * 补充SQL的字符串的==条件 + * + * @param where_is_exist 是否已经加入了where关键字 + */ + public static boolean addSql_EQUALE_Expr(boolean where_is_exist, StringBuilder sql, List args, String db_field_name, String condition_value) { + if (PubUtil.isNotEmptyStr(condition_value)) { + if (!where_is_exist) { + sql.append(" WHERE "); + where_is_exist = true; + } else { + sql.append(" AND "); + } + sql.append(db_field_name).append(" = ? \n"); + args.add(condition_value); + } + return where_is_exist; + } + + public static boolean addSql_lesser(boolean where_is_exist, StringBuilder sql, List args, String db_field_name, String condition_value) { + if (PubUtil.isNotEmptyStr(condition_value)) { + if (!where_is_exist) { + sql.append(" WHERE "); + where_is_exist = true; + } else { + sql.append(" AND "); + } + sql.append(db_field_name).append(" <= ? \n"); + args.add(condition_value); + } + return where_is_exist; + } + + public static boolean addSql_greater(boolean where_is_exist, StringBuilder sql, List args, String db_field_name, String condition_value) { + if (PubUtil.isNotEmptyStr(condition_value)) { + if (!where_is_exist) { + sql.append(" WHERE "); + where_is_exist = true; + } else { + sql.append(" AND "); + } + sql.append(db_field_name).append(" >= ? \n"); + args.add(condition_value); + } + return where_is_exist; + } + + + /** + * 补充SQL的字符串Like条件(仅后匹配) %s + * + * @param where_is_exist 是否已经加入了where关键字 + */ + public static boolean addSql_LIKE_Pre(boolean where_is_exist, StringBuilder sql, List args, String db_field_name, String condition_value) { + if (PubUtil.isNotEmptyStr(condition_value)) { + //mysq _ 是一个占位符需要加\进行处理 + condition_value = condition_value.replaceAll("_", "\\\\_"); + if (!where_is_exist) { + sql.append(" WHERE "); + where_is_exist = true; + } else { + sql.append(" AND "); + } + sql.append(db_field_name).append(" LIKE ? \n"); + args.add(String.format("%%%s", condition_value)); + } + return where_is_exist; + } + + public static boolean addSql_LIKE_Pre(boolean where_is_exist, StringBuilder sql, List args, String[] db_field_names, String condition_value) { + if (PubUtil.isNotEmptyStr(condition_value)) { + //mysq _ 是一个占位符需要加\进行处理 + condition_value = condition_value.replaceAll("_", "\\\\_"); + if (!where_is_exist) { + sql.append(" WHERE "); + where_is_exist = true; + } else { + sql.append(" AND "); + } + sql.append("(").append(db_field_names[0]).append(" LIKE ? \n"); + args.add(String.format("%%%s", condition_value)); + for (int i = 1; i < db_field_names.length; ++i) { + sql.append(" or ").append(db_field_names[i]).append(" LIKE ? \n"); + args.add(String.format("%%%s", condition_value)); + } + sql.append(")"); + } + return where_is_exist; + } + + public static boolean addSql_LIKE_EX(boolean where_is_exist, StringBuilder sql, List args, String condition_value, String... db_field_name) { + if (db_field_name == null || db_field_name.length == 0) return where_is_exist; + if (PubUtil.isNotEmptyStr(condition_value)) { + //mysq _ 是一个占位符需要加\进行处理 + condition_value = condition_value.replaceAll("_", "\\\\_"); + if (!where_is_exist) { + sql.append(" WHERE "); + where_is_exist = true; + } else { + sql.append(" AND "); + } + if (db_field_name.length == 1) { + sql.append(db_field_name[0]).append(" LIKE ? \n"); + args.add(String.format("%%%s%%", condition_value)); + return where_is_exist; + } + sql.append(" ("); + for (String db_filed : db_field_name) { + sql.append(" ").append(db_filed).append(" LIKE ? \nOR"); + args.add(String.format("%%%s%%", condition_value)); + } + sql.delete(sql.length() - 2, sql.length()); + sql.append(")\n"); + + } + return where_is_exist; + } + + + /** + * 补充SQL的字符串Like条件(仅后匹配) s% + * + * @param where_is_exist 是否已经加入了where关键字 + */ + public static boolean addSql_LIKE_Expr(boolean where_is_exist, StringBuilder sql, List args, String db_field_name, String condition_value) { + if (PubUtil.isNotEmptyStr(condition_value)) { + //mysq _ 是一个占位符需要加\进行处理 + condition_value = condition_value.replaceAll("_", "\\\\_"); + if (!where_is_exist) { + sql.append(" WHERE "); + where_is_exist = true; + } else { + sql.append(" AND "); + } + sql.append(db_field_name).append(" LIKE ? \n"); + args.add(String.format("%s%%", condition_value)); + } + return where_is_exist; + } + + + public static boolean addSql_LIKE_Expr(boolean where_is_exist, StringBuilder sql, List args, String[] db_field_names, String condition_value) { + if (PubUtil.isNotEmptyStr(condition_value)) { + //mysq _ 是一个占位符需要加\进行处理 + condition_value = condition_value.replaceAll("_", "\\\\_"); + if (!where_is_exist) { + sql.append(" WHERE "); + where_is_exist = true; + } else { + sql.append(" AND "); + } + sql.append("(").append(db_field_names[0]).append(" LIKE ? \n"); + args.add(String.format("%s%%", condition_value)); + for (int i = 1; i < db_field_names.length; ++i) { + sql.append(" or ").append(db_field_names[i]).append(" LIKE ? \n"); + args.add(String.format("%s%%", condition_value)); + } + sql.append(")"); + } + return where_is_exist; + } + + /** + * 补充SQL的字符串Like条件(全模糊) %s% + * + * @param where_is_exist 是否已经加入了where关键字 + */ + public static boolean addSql_LIKE(boolean where_is_exist, StringBuilder sql, List args, String db_field_name, String condition_value) { + if (PubUtil.isNotEmptyStr(condition_value)) { + //mysq _ 是一个占位符需要加\进行处理 + condition_value = condition_value.replaceAll("_", "\\\\_"); + if (!where_is_exist) { + sql.append(" WHERE "); + where_is_exist = true; + } else { + sql.append(" AND "); + } + sql.append(db_field_name).append(" LIKE ? \n"); + args.add(String.format("%%%s%%", condition_value)); + } + return where_is_exist; + } + + public static boolean addSql_LIKE(boolean where_is_exist, StringBuilder sql, List args, String[] db_field_names, String condition_value) { + if (PubUtil.isNotEmptyStr(condition_value)) { + //mysq _ 是一个占位符需要加\进行处理 + condition_value = condition_value.replaceAll("_", "\\\\_"); + if (!where_is_exist) { + sql.append(" WHERE "); + where_is_exist = true; + } else { + sql.append(" AND "); + } + sql.append("(").append(db_field_names[0]).append(" LIKE ? "); + args.add(String.format("%%%s%%", condition_value)); + for (int i = 1; i < db_field_names.length; ++i) { + sql.append(" OR ").append(db_field_names[i]).append(" LIKE ? "); + args.add(String.format("%%%s%%", condition_value)); + } + sql.append(")"); + } + return where_is_exist; + } + + /** + * 补充SQL字符串的IN条件 + * + * @param where_is_exist 是否已经加入了where关键字 + */ + public static boolean addSql_IN_Expr(boolean where_is_exist, StringBuilder sql, String db_field_name, Object... expr) { + if (expr != null && expr.length > 0) { + if (!where_is_exist) { + sql.append(" WHERE "); + where_is_exist = true; + } else { + sql.append(" AND "); + } + sql.append(db_field_name).append(" IN (").append(StringUtils.join(expr, ',')).append(")\n"); + } + return where_is_exist; + } + + /** + * 补充SQL字符串的not IN条件 + * + * @param where_is_exist 是否已经加入了where关键字 + */ + public static boolean addSql_NOTIN_Expr(boolean where_is_exist, StringBuilder sql, String db_field_name, Object... expr) { + if (expr != null && expr.length > 0) { + if (!where_is_exist) { + sql.append(" WHERE "); + where_is_exist = true; + } else { + sql.append(" AND "); + } + sql.append(db_field_name).append(" NOT IN (").append(StringUtils.join(expr, ',')).append(")\n"); + } + return where_is_exist; + } + + /** + * 增加字符串字段条件,可能多选 + * + * @param field 查询的字段名 + * @param value 值,包含','为多选 + * @param sql sql + * @param paras 参数 + */ + public static void addStrConMulti(String field, String value, StringBuilder sql, List paras) { + if (PubUtil.isEmpty(value)) + return; + if (value.contains(",")) {//多选 + sql.append(" and ").append(field).append(" in ('").append(value.replaceAll(",", "','")).append("')"); + } else if (!Consts.NULL_STRING.equals(value)) {//单 + sql.append(" and ").append(field).append("=?"); + paras.add(value); + } + } + + /** + * 增加字符串字段条件,不判断多选 + * + * @param field 查询的字段名 + * @param value 值 + * @param paras 参数 + */ + public static void addStrConSingle(String field, String value, StringBuilder sb, List paras) { + addStrConSingle(field, "=", value, sb, paras); + } + + /** + * 增加字符串字段条件,不判断多选 + * + * @param field 查询的字段名 + * @param opt 逻辑运算符 + * @param value 值 + * @param paras 参数 + */ + public static void addStrConSingle(String field, String opt, String value, StringBuilder sb, List paras) { + if (PubUtil.isNotEmpty(value) && !Consts.NULL_STRING.equals(value)) {//单 + sb.append(" and ").append(field).append(" ").append(opt).append(" ? \n"); + paras.add(value); + } + } + + /** + * 增加字符串字段条件,包含 + * + * @param field 查询的字段名 + * @param value 值 + * @param paras 参数 + */ + public static void addStrConSingleLike(String field, String value, StringBuilder sb, List paras) { + if (PubUtil.isNotEmpty(value) && !Consts.NULL_STRING.equals(value)) {//单 + sb.append(" and ").append(field).append(" like ? \n"); + paras.add("%" + value + "%"); + } + } + + /** + * 增加字符串字段条件并且不区分大小写,包含 + * + * @param field 查询的字段名 + * @param value 值 + * @param paras 参数 + */ + public static void addStrConSingleLikeIgnoreCase(String field, String value, StringBuilder sb, List paras) { + if (PubUtil.isNotEmpty(value) && !Consts.NULL_STRING.equals(value)) { + String valueLower = value.toLowerCase(); + sb.append(" and ").append("lower(").append(field).append(")").append(" like ? \n"); + paras.add("%" + valueLower + "%"); + } + } + + /** + * 增加数字字段条件,可能多选 + * + * @param field 查询的字段名 + * @param value 值,包含','为多选 + * @param paras 参数 + */ + public static void addNumberConMulti(String field, String value, StringBuilder sb, List paras) { + if (PubUtil.isEmptyId(value)) + return; + if (value.contains(",")) {//多选 + sb.append(" and ").append(field).append(" in (").append(value).append(") \n"); + } else if (!Consts.NULL_STRING.equals(value)) {//单 + sb.append(" and ").append(field).append("=? \n"); + paras.add(value); + } + } + + /** + * 增加数字字段条件,单选 + * + * @param field 查询的字段名 + * @param value 值 + * @param paras 参数 + */ + public static void addNumConSingle(String field, Number value, StringBuilder sb, List paras) { + addNumConSingle(field, "=", value, sb, paras); + } + + /** + * 增加数字字段条件,单选 + * + * @param field 查询的字段名 + * @param opt 运算符 + * @param value 值 + * @param paras 参数 + */ + public static void addNumConSingle(String field, String opt, Number value, StringBuilder sb, List paras) { + sb.append(" and ").append(field).append(opt).append("? \n"); + paras.add(value); + } + + /** + * 增加日期字段条件,可能多选 + * + * @param field 查询的字段名 + * @param value 值 + * @param paras 参数 + */ + @Deprecated + public static void addDateCon(String field, String value, StringBuilder sb, List paras) { + if (PubUtil.isEmpty(value)) + return; + String[] st = value.split(","); + if (st.length == 0 || Consts.NULL_STRING.equals(st[0])) {//无 + return; + } + String s = PubUtil.getCurDateStr(); + if (st.length > 0) { + switch (st[0]) { + case "D": //当天 考虑日期时间的情况 + sb.append(" and ").append(field).append(">='").append(s).append("' and ").append(field).append("<'").append(DateUtil.getAfterDays(s, 1)).append("' \n"); + break; + case "W": //本周 + s = DateUtil.toStdDateString(DateUtil.getWeekStart()); + sb.append(" and ").append(field).append(">='").append(s).append("' and ").append(field).append("<'").append(DateUtil.getAfterDays(s, 8)).append("' \n"); + break; + case "M": //本月 + sb.append(" and ").append(field).append(">='").append(DateUtil.getMonthStart()).append("' and ").append(field).append("<='").append(DateUtil.getMonthEnd()).append(" 23:59:59' \n"); + break; + case "Q": //本季度 + sb.append(" and ").append(field).append(">='").append(DateUtil.getSeasonFirstDay()).append("' and ").append(field).append("<='").append(DateUtil.getSeasonLastDay()).append(" 23:59:59' \n"); + break; + case "Y": //本年 + sb.append(" and ").append(field).append(">='").append(DateUtil.getYearFirstDay()).append("' and ").append(field).append("<='").append(DateUtil.getYearLastDay()).append(" 23:59:59' \n"); + break; + default: //自定义 + String df, de; + if (st.length > 1) + df = st[1]; + else + df = ""; + if (st.length > 2) + de = st[2]; + else + de = ""; + if (PubUtil.isEmpty(df) && PubUtil.isEmpty(de)) + return; + if (PubUtil.isEmpty(df)) { + sb.append(" and ").append(field).append("<=?"); + paras.add(de); + } else if (PubUtil.isEmpty(de)) { + sb.append(" and ").append(field).append(">=?"); + paras.add(df); + } else { + sb.append(" and ").append(field).append(">=? and ").append(field).append("<=? \n"); + paras.add(df); + paras.add(de); + } + break; + } + } + } + + /** + * 增加日期字段条件,可能多选(huangxl:日期格式YYYYMMDD) + * + * @param field 查询的字段名 + * @param value 值 + * @param paras 参数 + */ + public static void addDateConEx(String field, String value, StringBuilder sb, List paras) { + if (PubUtil.isEmpty(value)) + return; + String[] st = value.split(","); + if (st.length == 0 || Consts.NULL_STRING.equals(st[0])) {//无 + return; + } + String s = PubUtil.getCurDateStr(); + if (st.length > 0) { + switch (st[0]) { + case "D": //当天 + sb.append(" and ").append(field).append("=").append(PubUtil.getDateLong(s)).append(" \n"); + break; + case "W": //本周 + s = DateUtil.toStdDateString(DateUtil.getWeekStart()); + sb.append(" and ").append(field).append(" between ").append(PubUtil.getDateLong(s)).append(" and ").append(PubUtil.getDateLong(DateUtil.getAfterDays(s, 7))).append(" \n"); + break; + case "M": //本月 + sb.append(" and ").append(field).append(" between ").append(PubUtil.getDateLong(DateUtil.getMonthStart())).append(" and ").append(PubUtil.getDateLong(DateUtil.getMonthEnd())).append(" \n"); + break; + case "Q": //本季度 + sb.append(" and ").append(field).append(" between ").append(PubUtil.getDateLong(DateUtil.getSeasonFirstDay())).append(" and ").append(PubUtil.getDateLong(DateUtil.getSeasonLastDay())).append(" \n"); + break; + case "Y": //本年 + sb.append(" and ").append(field).append(" between ").append(PubUtil.getDateLong(DateUtil.getYearFirstDay())).append(" and ").append(PubUtil.getDateLong(DateUtil.getYearLastDay())).append(" \n"); + break; + default: //自定义 + String df, de; + if (st.length > 1) + df = st[1]; + else + df = ""; + if (st.length > 2) + de = st[2]; + else + de = ""; + if (PubUtil.isEmpty(df) && PubUtil.isEmpty(de)) + return; + if (PubUtil.isEmpty(df)) { + sb.append(" and ").append(field).append("<=?"); + paras.add(PubUtil.getDateLong(de)); + } else if (PubUtil.isEmpty(de)) { + sb.append(" and ").append(field).append(">=?"); + paras.add(PubUtil.getDateLong(df)); + } else { + sb.append(" and ").append(field).append(" between ? and ? \n"); + paras.add(PubUtil.getDateLong(df)); + paras.add(PubUtil.getDateLong(de)); + } + break; + } + } + } + + /** + * 增加期间查询日期字段条件,可能多选(huangxl:日期格式YYYYMMDD) + * + * @param field 查询的字段名 + * @param value 值 + * @param paras 参数 + */ + public static void addPeriodDateConEx(String field, String value, StringBuilder sb, List paras) { + if (PubUtil.isEmpty(value)) + return; + String[] st = value.split(","); + if (st.length == 0 || Consts.NULL_STRING.equals(st[0])) {//无 + return; + } + String df, de; + if (st.length > 1) + df = st[1]; + else + df = ""; + if (st.length > 2) + de = st[2]; + else + de = ""; + + sb.append(" and ").append(field).append(" between ? and ? \n"); + paras.add(df + "01"); + paras.add(de + "31"); + } + + + /** + * 增加日期时间字段条件 + * + * @param field 查询的字段名 + * @param value 值 + * @param paras 参数 + */ + public static void addDateTimeConEx(String field, String value, StringBuilder sb, List paras) { + if (PubUtil.isEmpty(value)) + return; + String[] st = value.split(","); + if (st.length == 0 || Consts.NULL_STRING.equals(st[0])) {//无 + return; + } + String s = PubUtil.getCurDateStr(); + if (st.length > 0) { + switch (st[0]) { + case "D": //当天 + sb.append(" and ").append(field).append(" between ").append(PubUtil.getDateTimeLong(s)).append(" and ").append(PubUtil.getEndDateTimeLong(s)).append(" \n"); + break; + case "W": //本周 + s = DateUtil.toStdDateString(DateUtil.getWeekStart()); + sb.append(" and ").append(field).append(" between ").append(PubUtil.getDateTimeLong(s)).append(" and ").append(PubUtil.getEndDateTimeLong(DateUtil.getAfterDays(s, 6))).append(" \n"); + break; + case "M": //本月 + sb.append(" and ").append(field).append(" between ").append(PubUtil.getDateTimeLong(DateUtil.getMonthStart())).append(" and ").append(PubUtil.getEndDateTimeLong(DateUtil.getMonthEnd())).append(" \n"); + break; + case "Q": //本季度 + sb.append(" and ").append(field).append(" between ").append(PubUtil.getDateTimeLong(DateUtil.getSeasonFirstDay())).append(" and ").append(PubUtil.getEndDateTimeLong(DateUtil.getSeasonLastDay())).append(" \n"); + break; + case "Y": //本年 + sb.append(" and ").append(field).append(" between ").append(PubUtil.getDateTimeLong(DateUtil.getYearFirstDay())).append(" and ").append(PubUtil.getEndDateTimeLong(DateUtil.getYearLastDay())).append(" \n"); + break; + default: //自定义 + String df, de; + if (st.length > 1) + df = st[1]; + else + df = ""; + if (st.length > 2) + de = st[2]; + else + de = ""; + if (PubUtil.isEmpty(df) && PubUtil.isEmpty(de)) + return; + if (PubUtil.isEmpty(df)) { + sb.append(" and ").append(field).append("<=?"); + paras.add(PubUtil.getEndDateTimeLong(de)); + } else if (PubUtil.isEmpty(de)) { + sb.append(" and ").append(field).append(">=?"); + paras.add(PubUtil.getDateTimeLong(df)); + } else { + sb.append(" and ").append(field).append(" between ? and ? \n"); + paras.add(PubUtil.getDateTimeLong(df)); + paras.add(PubUtil.getEndDateTimeLong(de)); + } + break; + } + } + } + + /** + * 枚举状态字段,in方式 + * + * @param where_is_exist sql是否已包括where + * @param field sql字段名 + * @param value 前端传回来的查询值,格式:1,1,1,1 + * @param intEnum 枚举类型 + * @param sql 待构建的sql + */ + public static void addIntEnumCon(boolean where_is_exist, String field, String value, IntEnum intEnum, StringBuilder sql) { + if (PubUtil.isNotEmpty(value) && value.contains("1") && value.contains("0")) { + if (!where_is_exist) { + sql.append(" WHERE "); + where_is_exist = true; + } else { + sql.append(" AND "); + } + String s = ""; + String[] ss = value.split(","); + int i = 0; + for (AbstractEnum.IntEnumBean b : intEnum.values()) { + if (ss.length > i && "1".equals(ss[i])) s += "," + b.value; + i++; + } + sql.append(field + " in (" + s.substring(1) + ")"); + } + } + + /** + * 枚举状态字段,in方式 + * + * @param where_is_exist sql是否已包括where + * @param field sql字段名 + * @param value 前端传回来的查询值,格式:1,1,1,1 + * @param intEnum 枚举类型 + * @param sql 待构建的sql + */ + public static void addStrEnumCon(boolean where_is_exist, String field, String value, StrEnum intEnum, StringBuilder sql) { + if (PubUtil.isNotEmpty(value) && value.contains("1") && value.contains("0")) { + if (!where_is_exist) { + sql.append(" WHERE "); + where_is_exist = true; + } else { + sql.append(" AND "); + } + String s = ""; + String[] ss = value.split(","); + int i = 0; + for (AbstractEnum.StrEnumBean b : intEnum.values()) { + if (ss.length > i && "1".equals(ss[i])) s += ",'" + b.value + "'"; + i++; + } + sql.append(field + " in (" + s.substring(1) + ")"); + } + } + + public static void addTreeStateCon(String curPrefix, String value, String tableName, StringBuilder sb, List paras) { + if (PubUtil.isNotEmpty(value) && !Consts.NULL_STRING.equals(value) && !value.contains(",")) { + int v = PubUtil.getIntIgnoreErr(value); + if (v == 0) {//查启用 自己启用,且父亲未停用 + sb.append(" and ").append(curPrefix).append(".f_status=0 and not exists(select 1 from ").append(tableName).append(" p__ where p__.f_status=1 and ").append(curPrefix).append(".f_level_code like p__.f_level_code || '-%')"); + } else {//查停用 自己停用 或父亲被停用 + sb.append(" and (").append(curPrefix).append(".f_status=1 or exists(select 1 from ").append(tableName).append(" p__ where p__.f_status=1 and ").append(curPrefix).append(".f_level_code like p__.f_level_code || '-%'))"); + } + } + } + + /** + * 增加年月字段条件 + * + * @param field 查询的字段名 + * @param value 值 + * @param paras 参数 + */ + public static void addYmCon(String field, String value, StringBuilder sb, List paras) { + addYmConEx(field, field, value, sb, paras); + } + + public static void addYmConEx(String field_begin, String field_end, String value, StringBuilder sb, List paras) { + if (PubUtil.isEmpty(value)) + return; + String[] st = value.split(","); + if (st.length == 0 || Consts.NULL_STRING.equals(st[0])) {//无 + return; + } + String s = PubUtil.getCurDateStr(); + if (st.length > 1) { + switch (st[0]) { + case "M": //本月 + String nowYm = DateUtil.getNowYm(); + sb.append(" and ").append(field_end).append(">='").append(DateUtil.getNowYm()).append("' and ").append(field_begin).append("<='").append(nowYm).append("'"); + break; + case "Q": //本季度 + sb.append(" and ").append(field_end).append(">='").append(DateUtil.getSeasonBeginYm()).append("' and ").append(field_begin).append("<='").append(DateUtil.getSeasonEndYm()).append("'"); + break; + case "Y": //本年 + sb.append(" and ").append(field_end).append(">='").append(DateUtil.getYearBeginYm()).append("' and ").append(field_begin).append("<='").append(DateUtil.getYearEndYm()).append("'"); + break; + default: //自定义 + String df, de; + if (st.length > 1) + df = st[1]; + else + df = ""; + if (st.length > 2) + de = st[2]; + else + de = ""; + if (PubUtil.isEmpty(df) && PubUtil.isEmpty(de)) + return; + if (PubUtil.isEmpty(df)) { + sb.append(" and ").append(field_begin).append("<=?"); + paras.add(de); + } else if (PubUtil.isEmpty(de)) { + sb.append(" and ").append(field_end).append(">=?"); + paras.add(df); + } else { + sb.append(" and ").append(field_end).append(">=? and ").append(field_begin).append("<=?"); + paras.add(df); + paras.add(de); + } + break; + } + } else if (st.length == 1) { + sb.append(" and ").append(field_end).append(">='").append(value).append("' and ").append(field_begin).append("<='").append(value).append("'"); + } + } + + //构建年月范围的sql + public static String getYmConSql(String field, String value) { + return getYmConSqlEx(field, field, value); + } + + public static String getYmConSqlEx(String field_begin, String field_end, String value) { + if (PubUtil.isEmpty(value)) return ""; + String[] st = value.split(","); + if (st.length == 0 || Consts.NULL_STRING.equals(st[0])) return ""; + String s = PubUtil.getCurDateStr(); + StringBuilder sb = new StringBuilder(128); + + switch (st[0]) { + case "M": //本月 + String nowYm = DateUtil.getNowYm(); + sb.append(" and ").append(field_end).append(">='").append(DateUtil.getNowYm()).append("' and ").append(field_begin).append("<='").append(nowYm).append("'"); + break; + case "Q": //本季度 + sb.append(" and ").append(field_end).append(">='").append(DateUtil.getSeasonBeginYm()).append("' and ").append(field_begin).append("<='").append(DateUtil.getSeasonEndYm()).append("'"); + break; + case "Y": //本年 + sb.append(" and ").append(field_end).append(">='").append(DateUtil.getYearBeginYm()).append("' and ").append(field_begin).append("<='").append(DateUtil.getYearEndYm()).append("'"); + break; + default: //自定义 + String df, de; + if (st.length > 1) + df = st[1]; + else + df = ""; + if (st.length > 2) + de = st[2]; + else + de = ""; + if (PubUtil.isEmpty(df) && PubUtil.isEmpty(de)) + return ""; + if (PubUtil.isEmpty(df)) { + sb.append(" and ").append(field_begin).append("<='").append(de).append("'"); + } else if (PubUtil.isEmpty(de)) { + sb.append(" and ").append(field_end).append(">='").append(df).append("'"); + } else { + sb.append(" and ").append(field_end).append(">='").append(df).append("' and ").append(field_begin).append("<='").append(de).append("'"); + } + break; + } + return sb.substring(5); + } +} diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/MathUtil.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/MathUtil.java new file mode 100644 index 0000000..3e17961 --- /dev/null +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/MathUtil.java @@ -0,0 +1,463 @@ +package cc.smtweb.framework.core.util; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.DecimalFormat; + +/** + * Created with IntelliJ IDEA. + * User: AKhh + * Date: 12-12-25 下午1:02 + * To change this template use File | Settings | File Templates. + */ +public class MathUtil { + //整数 + private static DecimalFormat dfLng = new DecimalFormat("##############0"); + private static DecimalFormat dfLong = new DecimalFormat("###,###,###,###,##0"); + //一位小数 + private static DecimalFormat df1 = new DecimalFormat("##############0.0"); + private static DecimalFormat df1Format = new DecimalFormat("###,###,###,###,##0.0"); + //两位小数 + private static DecimalFormat df2 = new DecimalFormat("##############0.00"); + private static DecimalFormat df2Format = new DecimalFormat("###,###,###,###,##0.00"); + //四位小数 + private static DecimalFormat df4 = new DecimalFormat("###,###,###,###,##0.0000"); + //六位小数 + private static DecimalFormat df6Number = new DecimalFormat("#######################0.000000"); + private static DecimalFormat df6NumberF = new DecimalFormat("#,###,###,###,###,###,##0.000000"); + + public final static DecimalFormat stdAmountFormat = new DecimalFormat("###,###,###,###,##0.00"); + public final static DecimalFormat stdNumberFormat = new DecimalFormat("#0.00"); + public final static String DEF_NUM_TEN_THOUSAND = "10000";//万 + public static final double MAX_VALUE = 9999999999999.99D; + public static final double MIN_VALUE = -9999999999999.99D; + + private final static BigDecimal ONE_BIG = new BigDecimal(1.00D); + private static final String UNIT = "万仟佰拾亿仟佰拾万仟佰拾元角分"; + private static final String DIGIT = "零壹贰叁肆伍陆柒捌玖"; + + /** + * 4舍5入double,2位小数 + */ + public static double roundDouble(double src) { + return roundDouble(src, 2); + } + + /** + * 4舍5入double,N 位小数 + * @param src + * @param scale 小数位数 + * @return + */ + public static double roundDouble(Object src, int scale) { + if (src == null) return 0.0; + String v = src.toString(); + if (PubUtil.isEmpty(v)) return 0.0; + if (scale < 0) scale = 2; + + BigDecimal src_b = new BigDecimal(v); + BigDecimal src_v = src_b.divide(ONE_BIG, scale + 2, BigDecimal.ROUND_HALF_UP);// 4舍5入 + src_v = src_v.divide(ONE_BIG, scale, BigDecimal.ROUND_HALF_UP);// 4舍5入 + return src_v.doubleValue(); + } + + /** + * 舍位处理,原生floor有坑,部分浮点数记录为.99999999999形式,导致floor结果错误 + * @param d + * @return + */ + public static double floor(double d) { + return Math.floor(roundDouble(d, 2)); + } + + /** + * 比较两Double是否相等,将会吧他们专程BigDecimal进行比较; + * + * @param src double1 + * @param tag double2 + * @return src > tag 返回1, src < tag 返回-1, 否则返回0 + */ + public static int compare(double src, double tag) { + BigDecimal src_b = new BigDecimal(src); + BigDecimal src_v = src_b.divide(ONE_BIG, 2, BigDecimal.ROUND_HALF_UP);// 4舍5入 + + BigDecimal tag_b = new BigDecimal(tag); + BigDecimal tag_v = tag_b.divide(ONE_BIG, 2, BigDecimal.ROUND_HALF_UP);// 4舍5入 + + return src_v.compareTo(tag_v); + } + + /** + * 自动过滤金额中的逗号转换为double,如果出错,则返回0 + * + * @param s 源串,可能为带逗号的金额串; + * @return double + */ + public static Double toDouble(String s) { + return todouble(s); + } + + /** + * 自动过滤金额中的逗号转换为double,如果出错,则返回0 + * + * @param s 源串,可能为带逗号的金额串; + * @return double + */ + public static double todouble(String s) { + try { + return Double.parseDouble(s.replaceAll(",", "")); + } catch (Exception e) { + return 0.00; + } + } + + /** + * 获取double,主要过滤d为null的情况; + * + * @param d Double对象; + * @return double + */ + public static double todouble(Double d) { + if (d == null) return 0.0d; + return d.doubleValue(); + } + + /** + * 自动过滤金额中的逗号转换为float,如果出错,则返回0 + * + * @param s 源串,可能为带逗号的金额串; + * @return Float + */ + public static Float toFloat(String s) { + return tofloat(s); + } + + /** + * 自动过滤金额中的逗号转换为float,如果出错,则返回0 + * + * @param s 源串,可能为带逗号的金额串; + * @return Float + */ + public static float tofloat(String s) { + try { + return Float.parseFloat(s.replaceAll(",", "")); + } catch (Exception e) { + return 0.0f; + } + } + + public static long tolong(String src, long defaultvalue) { + try { + return Long.parseLong(src); + } catch (Exception e) { + return defaultvalue; + } + } + + public static int toint(String src, int defaultvalue) { + try { + return Integer.parseInt(src); + } catch (Exception e) { + return defaultvalue; + } + } + + /** + * 考虑使用中的精度,判断一个Value是否>0,实际是>0.00001 + * + * @param value double类型 + * @return boolean + */ + public static boolean isBigThanZero(double value) { + return (value > 0.00001); + } + + /** + * 考虑使用中的精度,判断一个Value是否>0,实际是>0.00001 + * + * @param value String类型 + * @return boolean + */ + public static boolean isBigThanZero(String value) { + return !PubUtil.isEmpty(value) && isBigThanZero(toDouble(value)); + } + + /** + * 考虑使用中的精度,判断一个Value是否=0,实际是给出一个值范围。 + * + * @param value double类型 + * @return boolean + */ + public static boolean isEqualsZero(double value) { + return (-0.00001 < value && value < 0.00001); + } + + /** + * 考虑使用中的精度,判断一个Value是否=0,实际是给出一个值范围。 + * + * @param value String类型 + * @return boolean + */ + public static boolean isEqualsZero(String value) { + return PubUtil.isEmpty(value) || isEqualsZero(toDouble(value)); + } + + /** + * 是否是负数 + * + * @param db_val 要判断的double + * @return 负数则返回true; + */ + public static boolean isNegative(double db_val) { + return (compare(db_val, 0.00D) == -1); + } + + /** + * 是否是正数 + * + * @param db_val 要判断的double + * @return 正数则返回true; + */ + public static boolean isPlus(double db_val) { + return (compare(db_val, 0.00D) == 1); + } + + /** + * 得到金额字符串,保持小数点2位 + * + * @param db 将double转换为金额字符串; + * @return 金额字符串#0.00; + */ + public static String toStdNumberString(double db) { + try { + return stdNumberFormat.format(db); + } catch (Exception e) { + return "0.00"; + } + } + + public static String toStdNumberStringEx(double db) { + try { + if (compare(db, -1d) == 0) return "-"; + return stdNumberFormat.format(db); + } catch (Exception e) { + return "0.00"; + } + } + + /** + * 将金额格式字符串,如23,333,093.01 去掉逗号 + * + * @param s 金额串 + * @return String 去掉逗号后的串,如果amount为空,则返回0.00 + */ + public static String toStdNumberString(String s) { + if (PubUtil.isEmpty(s)) + return "0.00"; + return stdNumberFormat.format(todouble(s)); + } + + /** + * 将数据转换为两位小数的数字格式; + * + * @param d 数据 + * @param isZeroToEmpty 如果未0,是否返回“”; + * @return 两位小数的字符串; + */ + public static String toStdNumberString(double d, boolean isZeroToEmpty) { + if (isEqualsZero(d)) { + return isZeroToEmpty ? "": "0.00"; + } + return stdNumberFormat.format(d); + } + + public static String toStdNumberString(String s, boolean isZeroToEmpty) { + return toStdNumberString(todouble(s), isZeroToEmpty); + } + + public static String toStdNumberString(double d, int scale) { + DecimalFormat dfn = null; + if (scale == 1) dfn = df1Format; + if (scale == 2) dfn = df2Format; + else if (scale == 4) dfn = df4; + else if (scale == 6) dfn = df6NumberF; + else if (scale <= 0) dfn = dfLong; + else { + StringBuilder sb = new StringBuilder("###,###,###,###,##0."); + for (int i = 0; i < scale; i++) sb.append("0"); + dfn = new DecimalFormat(sb.toString()); + } + return dfn.format(d); + } + + /** + * 将数字乘100,保留小数点后两位, 然后后面添加% + * + * @param d 值 + * @param isZeroToEmpty,如果值为0,是否返回空; + * @return 字符串; + */ + public static String toStdPercentNumberStr(double d, boolean isZeroToEmpty) { + if (d > -0.00000000001 && d < 0.00000000001) { + return isZeroToEmpty ? "": "0.00%"; + } + return toStdNumberString(d * 100) + "%"; + } + + + public static String toStdAmountString(double d) { + return toStdAmountString(d, false); + } + + /** + * 将数据转换为两位小数的金额格式,带逗号; + * + * @param d 数据 + * @param isZeroToEmpty 如果未0,是否返回“”; + * @return 金额格式的字符串; + */ + public static String toStdAmountString(double d, boolean isZeroToEmpty) { + if (isEqualsZero(d)) { + return isZeroToEmpty ? "": "0.00"; + } + return stdAmountFormat.format(d); + } + + public static String toStdAmountString(String s) { + return toStdAmountString(todouble(s), false); + } + + public static String toStdAmountString(String s, boolean isZeroToEmpty) { + return toStdAmountString(todouble(s), isZeroToEmpty); + } + + + /** + * 将小写金额转换为人民币大写金额 + * + * @param s 金额格式的串 + * @return String 转换结果 + */ + public static String toCapsAmountString(String s) { + if (PubUtil.isEmpty(s)) return ""; + return toCapsAmountString(todouble(s)); + } + + /** + * 将小写金额转换为人民币大写金额 + * + * @param v double + * @return String 转换结果 + */ + public static String toCapsAmountString(double v) { + if (v < MIN_VALUE || v > MAX_VALUE) return "参数非法!"; + + boolean negative = isNegative(v); + + if (negative) v = Math.abs(v); + long l = Math.round(v * 100); + if (l == 0) return "零元整"; + + String strValue = String.valueOf(l); + // i用来控制数 + int i = 0; + // j用来控制单位 + int j = UNIT.length() - strValue.length(); + StringBuilder rs = new StringBuilder(32); + boolean isZero = false; + for (; i < strValue.length(); i++, j++) { + char ch = strValue.charAt(i); + if (ch == '0') { + isZero = true; + if (UNIT.charAt(j) == '亿' || UNIT.charAt(j) == '万' || UNIT.charAt(j) == '元') { + rs.append(UNIT.charAt(j)); + isZero = false; + } + } else { + if (isZero) { + rs.append('零'); + isZero = false; + } + rs.append(DIGIT.charAt(ch - '0')).append(UNIT.charAt(j)); + } + } + if (rs.charAt(rs.length() - 1) != '分') + rs.append('整'); + + i = rs.indexOf("亿万"); + if (i > 0) rs.delete(i + 1, i + 2); // i+1 ->万 + + if (negative) + return rs.insert(0, '负').toString(); + else + return rs.toString(); + } + + /** + * 返回0 到 maxvalue的随机数 + * + * @param maxvalue 随机数的最大值 + * @return int + */ + public static int rnd(int maxvalue) { + return (int) (Math.random() * (maxvalue + 1)); + } + + + public static double chkDbNull(Double v) { + return v == null ? 0: v; + } + + public static double max(double d1, double d2) { + return compare(d1, d2) < 0 ? d2 : d1; + } + + public static double min(double d1, double d2) { + return compare(d1, d2) < 0 ? d1 : d2; + } + + + public static void main(String[] args) { + double aa=123456789.345678900005; + System.out.println("args0 = " + upDouble(aa,0)); + System.out.println("args1 = " + upDouble(aa,1)); + System.out.println("args2 = " + upDouble(aa,2)); + System.out.println("args3 = " + upDouble(aa,3)); + System.out.println("args4 = " + upDouble(aa,4)); + System.out.println("args5 = " + upDouble(aa,5)); + System.out.println("args5 = " + upDouble(aa,6)); + System.out.println("args5 = " + upDouble(aa,7)); + System.out.println("args5 = " + upDouble(aa,8)); + + } + + /** + * double 去尾法 + * @param src 待处理数据 + * @param scale 保留小数位数 + * @return + */ + public static double cutDouble(double src, int scale){ + String v = toStdNumberString(src, 6);//先到6位小数,再去计算,否则容易出错,如8.3成8.29999999999,舍位就成了8.29了 + DecimalFormat formater = new DecimalFormat(); + formater.setMaximumFractionDigits(scale); + formater.setGroupingSize(0); + formater.setRoundingMode(RoundingMode.FLOOR); + return new BigDecimal(formater.format(toDouble(v))).doubleValue(); + } + + /** + * double 进位法 + * @param src 待处理数据 + * @param scale 保留小数位数 + * @return + */ + public static double upDouble(double src, int scale){ + String v = toStdNumberString(src, 6);//先到6位小数,再去计算 + DecimalFormat formater = new DecimalFormat(); + formater.setMaximumFractionDigits(scale); + formater.setGroupingSize(0); + formater.setRoundingMode(RoundingMode.UP); + return new BigDecimal(formater.format(toDouble(v))).doubleValue(); + } +} diff --git a/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/PersonUIDUtil.java b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/PersonUIDUtil.java new file mode 100644 index 0000000..52bc69c --- /dev/null +++ b/smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/PersonUIDUtil.java @@ -0,0 +1,377 @@ +package cc.smtweb.framework.core.util; + + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * 个人身份证帮助类 + * + * @author : AKzz + * @version : $Revision:$ + */ +public final class PersonUIDUtil { + private final static String uid_chars = "0123456789XZ"; + private static Map map_uid_chars; + + static { + map_uid_chars = new HashMap<>(); + map_uid_chars.put("0", "0"); + map_uid_chars.put("1", "1"); + map_uid_chars.put("2", "2"); + map_uid_chars.put("3", "3"); + map_uid_chars.put("4", "4"); + map_uid_chars.put("5", "5"); + map_uid_chars.put("6", "6"); + map_uid_chars.put("7", "7"); + map_uid_chars.put("8", "8"); + map_uid_chars.put("9", "9"); + map_uid_chars.put("X", "X"); + map_uid_chars.put("x", "X"); + map_uid_chars.put("Z", "Z"); + map_uid_chars.put("z", "Z"); + } + + /* + 大陆的身份证为18位,老的身份证是15位。 + + 地址码(身份证前六位)第一、第二数字表示公民所在地的省份(或自治区、直辖市); + 第三、第四位数字表示公民 所在地的市(或州); + 第五、第六位数字表示公民所在地的县(或县级市); + 生日期码(身份证第七位到第十四位)接下来的8位数字表示公民的出生年、月、日; + 顺序码(身份证第十五位到十七位)为同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号 + 第17位:奇数为男性,偶数为女性) + 第十八位数字的计算方法为: + 1.将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 + 2.将这17位数字和系数相乘的结果相加。 + 3.用加出来和除以11,看余数是多少? + 4.余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2' + */ + public final static int NEW_CARD_NUMBER_LENGTH = 18; + public final static int OLD_CARD_NUMBER_LENGTH = 15; + // 18位身份证中,各个数字的生成校验码时的权值 + private final static int[] VERIFY_CODE_WEIGHT = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; + // 18位身份证中最后一位校验码 + private final static char[] VERIFY_CODE = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}; + + public static boolean checkPersonUID(String uid) { + return checkPersonUIDA(uid, false); + } + + /** + * 检查身份证是否合法. + */ + public static boolean checkPersonUIDA(String uid, boolean include15) { + String uid_15_ex = "^\\d{6}\\d{2}(0[1-9]|10|11|12)(0[1-9]|1[0-9]|2[0-9]|3[0-1])\\d{3}$"; + String uid_18_ex = "^\\d{6}(19|20)\\d{2}(0[1-9]|10|11|12)(0[1-9]|1[0-9]|2[0-9]|3[0-1])\\d{3}[0-9X]{1}$"; + String regx, bdate; + if (include15 && uid.length() == 15) { + regx = uid_15_ex; // 15位 地址码 + (年+月+日) + 顺序号 + bdate = "19" + uid.substring(6, 12); + } else if (uid.length() == NEW_CARD_NUMBER_LENGTH) { + regx = uid_18_ex; // 18位 身份证 + bdate = uid.substring(6, 14); + } else { + return false; + } + if (!DateUtil.isDateFormat(bdate, "YYYYMMDD")) return false; + Pattern pattern = Pattern.compile(regx); + boolean ret = pattern.matcher(uid).matches(); + if (ret && uid.length() == NEW_CARD_NUMBER_LENGTH) { + return calculateVerifyCode(uid) == uid.charAt(NEW_CARD_NUMBER_LENGTH - 1); + } + return ret; + } + + /** + * 检查身份证是否合法 + * + * @param uid 要检查的身份证号; + * @return 对于可以转换的自动验证转换为正确的身份证号,如18位51012719731204001X,则能自动转换为正确的,15位自动转换为18位,返回的message中。 + */ + public static boolean checkPersonUIDEx(String uid) { + return checkPersonUIDExA(uid, false); + } + + public static boolean checkPersonUIDExA(String uid, boolean include15) { + String uid_15_ex = "^\\d{6}\\d{2}(0[1-9]|10|11|12)(0[1-9]|1[0-9]|2[0-9]|3[0-1])\\d{3}$"; + String uid_18_ex = "^\\d{6}(19|20)\\d{2}(0[1-9]|10|11|12)(0[1-9]|1[0-9]|2[0-9]|3[0-1])\\d{3}[0-9A-Z]{1}$"; + String regx, bdate; //11011720031031501Z + + if (include15 && uid.length() == 15) { + regx = uid_15_ex; // 15位 地址码 + (年+月+日) + 顺序号 + bdate = "19" + uid.substring(6, 12); + } else if (uid.length() == NEW_CARD_NUMBER_LENGTH) { + regx = uid_18_ex; // 18位 身份证 + bdate = uid.substring(6, 14); + } else { + return false; + } + if (!DateUtil.isDateFormat(bdate, "YYYYMMDD")) { + return false; + } + Pattern pattern = Pattern.compile(regx); + boolean ret = pattern.matcher(uid).matches(); + if (!ret) { + return false; + } + + if (uid.length() == NEW_CARD_NUMBER_LENGTH) {//18位 + char c = calculateVerifyCode(uid); + if (c == uid.charAt(NEW_CARD_NUMBER_LENGTH - 1)) + return true;//正确 + return false;//错误 + } else {//15位则换算成18位 + return true; + } + } + + /** + * 校验码(第十八位数): + * 十七位数字本体码加权求和公式 S = Sum(Ai * Wi), i = 0...16 ,先对前17位数字的权求和; + * Ai:表示第i位置上的身份证号码数字值 Wi:表示第i位置上的加权因子 Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 + * 2; + * 计算模 Y = mod(S, 11)< + * 通过模得到对应的校验码 Y: 0 1 2 3 4 5 6 7 8 9 10 校验码: 1 0 X 9 8 7 6 5 4 3 2 + */ + public static char calculateVerifyCode(CharSequence uid) { + int sum = 0; + for (int i = 0; i < NEW_CARD_NUMBER_LENGTH - 1; i++) { + char ch = uid.charAt(i); + sum += (ch - '0') * VERIFY_CODE_WEIGHT[i]; + } + return VERIFY_CODE[sum % 11]; + } + + /** + * 获取身份证的第17位,奇数为男性,偶数为女性 + * + * @param uid 身份证号; + * @return 0: 女; 1.男; + */ + public static int getPersonSex(CharSequence uid) { + char genderCode; + if (uid.length() == NEW_CARD_NUMBER_LENGTH) + genderCode = uid.charAt(NEW_CARD_NUMBER_LENGTH - 2); + /*else if (uid.length() == OLD_CARD_NUMBER_LENGTH) + genderCode = uid.charAt(OLD_CARD_NUMBER_LENGTH - 1);*/ + else + return -1;//throw new IllegalArgumentException("非法的居民身份证号[" + uid + "]!"); + return (genderCode - '0' & 0x1) == 0x01 ? 1 : 0; + } + + /** + * 从身份证中取得出身日期 + */ + public static String getBirthday(CharSequence uid) { + StringBuilder birthday = new StringBuilder(10); + /*if (uid.length() == OLD_CARD_NUMBER_LENGTH) { + birthday.append("19").append(uid.subSequence(6, 8)).append('-'); + birthday.append(uid.subSequence(8, 10)).append('-'); + birthday.append(uid.subSequence(10, 12)); + } else */ + if (uid.length() == NEW_CARD_NUMBER_LENGTH) { + birthday.append(uid.subSequence(6, 10)).append('-'); + birthday.append(uid.subSequence(10, 12)).append('-'); + birthday.append(uid.subSequence(12, 14)); + } else { + throw new IllegalArgumentException("非法的居民身份证号[" + uid + "]!"); + } + return birthday.toString(); + } + + /** + * 把15位身份证号码转换到18位身份证号码
+ * 15位身份证号码与18位身份证号码的区别为:
+ * 1、15位身份证号码中,"出生年份"字段是2位,转换时需要补入"19",表示20世纪
+ * 2、15位身份证无最后一位校验码。18位身份证中,校验码根据根据前17位生成 + */ + public static String contertToNewCardNumber(String oldUID) { + if (oldUID.length() != 15) { + char c = calculateVerifyCode(oldUID); + return oldUID.substring(0, NEW_CARD_NUMBER_LENGTH - 1) + c; + } + + StringBuilder buf = new StringBuilder(NEW_CARD_NUMBER_LENGTH); + buf.append(oldUID.substring(0, 6)); + buf.append("19"); + buf.append(oldUID.substring(6)); + buf.append(calculateVerifyCode(buf)); + return buf.toString().toUpperCase(); + } + + /** + * 根据身份证和传入的年月,计算人员年龄; + * + * @param person_uid 身份证号 + * @param curYear 年度 + * @param curMonth 月份 + */ + public static int getPersonAge(String person_uid, int curYear, int curMonth) { + String birth_date = getBirthday(person_uid); + int year = Integer.parseInt(birth_date.substring(0, 4)); + int month = Integer.parseInt(birth_date.substring(5, 7)); + int age = curYear - year; + if (curMonth < month) + age--; + return age; + } + + public static int getPersonAge(String person_uid, String period) { + int y = Integer.parseInt(period.substring(0, 4)); + int m = Integer.parseInt(period.substring(4)); + return getPersonAge(person_uid, y, m); + } + + /** + * 根据身份证和传入的年月,计算人员年龄; + * + * @param person_uid 身份证号 + * @param nowDate 比较日期 2017-01-01 + */ + public static int getPersonAgeEx(String person_uid, String nowDate, int ageType) { + int y = Integer.parseInt(nowDate.substring(0, 4)); + int m = Integer.parseInt(nowDate.substring(5, 7)); + int d = Integer.parseInt(nowDate.substring(8, 10)); + + String birth_date = getBirthday(person_uid); + int year = Integer.parseInt(birth_date.substring(0, 4)); + int month = Integer.parseInt(birth_date.substring(5, 7)); + int day = Integer.parseInt(birth_date.substring(8, 10)); + + int age = y - year; + if (ageType == 0) { + if (m < month) age--; + } else if (ageType == 4) { + if (m < month || (m == month && d < day)) age--; + else age++; + } else if (ageType == 2) { + age++; + } else if (ageType == 3) { + age--; + } + return age; + } + + public static int getPersonAge(String person_uid, String period, int ageType) { + int y = Integer.parseInt(period.substring(0, 4)); + int m = Integer.parseInt(period.substring(4)); + + String birth_date = getBirthday(person_uid); + int year = Integer.parseInt(birth_date.substring(0, 4)); + int month = Integer.parseInt(birth_date.substring(5, 7)); + + int age = y - year; + if (ageType == 0) { + if (m < month) age--; + } else if (ageType == 2) { + age++; + } else if (ageType == 3) { + age--; + } + return age; + } + + public static int getPersonAge(String person_uid, int year, int month, int ageType) { + + String birth_date = getBirthday(person_uid); + int y = Integer.parseInt(birth_date.substring(0, 4)); + int m = Integer.parseInt(birth_date.substring(5, 7)); + + int age = year - y; + if (ageType == 0) { + if (month < m) age--; + } else if (ageType == 2) { + age++; + } else if (ageType == 3) { + age--; + } + return age; + } + + //计算年龄,按年算 + public static int getPersonAgeYear(String person_uid, int curYear) { + String birth_date = getBirthday(person_uid); + int year = Integer.parseInt(birth_date.substring(0, 4)); + return curYear - year; + } + + public static int getPersonAgeYear(String person_uid, String period) { + int y = Integer.parseInt(period.substring(0, 4)); + return getPersonAgeYear(person_uid, y); + } + + /** + * 根据身份证,根据当前年月,计算人员年龄; + * + * @param person_uid 身份证号 + */ + public static int getPersonAge(String person_uid) { + String birth_date = getBirthday(person_uid); + int year = Integer.parseInt(birth_date.substring(0, 4)); + int month = Integer.parseInt(birth_date.substring(5, 7)); + int age = Integer.parseInt(DateUtil.nowYear()) - year; + if (Integer.parseInt(DateUtil.nowMonth()) < month) + age--; + return age; + } + + //去掉非法字符 + public static String cleanPersonUid(String personUid) { + if (personUid == null) return ""; + personUid = personUid.trim().toUpperCase(); + StringBuilder sb = new StringBuilder(personUid.length()); + for (int len = personUid.length(), i = 0; i < len; i++) { + char c = personUid.charAt(i); + if (c == 'X' || (c >= '0' && c <= '9')) sb.append(c); + } + return sb.toString(); + } + + //去掉非法字符,含z + public static String cleanPersonUidEx(String personUid) { + if (personUid == null) return ""; + personUid = personUid.trim().toUpperCase(); + StringBuilder sb = new StringBuilder(18); + String s; + for (int len = personUid.length(), i = 0; i < len; i++) { + char c = personUid.charAt(i); + if (uid_chars.indexOf(c) >= 0) sb.append(c); + else { + s = String.valueOf(c); + if (map_uid_chars.containsKey(s)) sb.append(map_uid_chars.get(s)); + } + } + return sb.toString(); + } + + + /** + * 显示uid的时候保密,用一些**符号 + * @param person_uid + * @return + */ + public static String secretPersonUID(String person_uid){ + return secretPersonUID(person_uid,8); + } + + public static String secretPersonUID(String person_uid,int secretLength){ + if(person_uid.length()>14){ + String head = person_uid.substring(0,6); + String tail = person_uid.substring(14,person_uid.length()); + StringBuilder sb = new StringBuilder(); + sb.append(head); + int i=0; + while (i getAttributeMap(Element e) { + Map map = new HashMap<>(); + for (Iterator as = e.attributeIterator(); as.hasNext(); ) { + Attribute a = (Attribute) as.next(); + map.put(a.getName(), a.getValue()); + } + return map; + } + + public static void removeAttribute(Element e, String attrName) { + Attribute a = e.attribute(attrName); + if (a != null) e.remove(a); + } + + //设置节点属性 + public static void setAttribute(Element e, String attrName, String attrValue) { + if (PubUtil.isNotEmpty(attrValue)) e.addAttribute(attrName, attrValue); + else removeAttribute(e, attrName); + } + + //设置节点属性 + public static void setAttribute(Element e, String attrName, int attrValue) { + if (attrValue != 0) e.addAttribute(attrName, String.valueOf(attrValue)); + else removeAttribute(e, attrName); + } + + //设置节点属性 + public static void setAttribute(Element e, String attrName, double attrValue) { + if (!MathUtil.isEqualsZero(attrValue)) e.addAttribute(attrName, String.valueOf(attrValue)); + else removeAttribute(e, attrName); + } + + //设置节点属性 + public static void setAttribute(Element e, String attrName, boolean attrValue) { + if (attrValue) e.addAttribute(attrName, "1"); + else removeAttribute(e, attrName); + } + + //设置节点属性 + public static void removeElement(Element parent, String name) { + Element e = parent.element(name); + if (e != null) parent.remove(e); + } + + //解析节点到Map + public static void decodeForMap(Element pnode, Map map) { + for (Iterator it = pnode.elementIterator(); it.hasNext(); ) { + Element el = (Element) it.next(); + String nodename = el.getName(); + map.put(nodename, el.getTextTrim()); + } + } + + //解析节点到Map + public static void writeMap(Element pnode, Map map) { + for (String s: map.keySet()) { + Element e = pnode.addElement(s); + final Object o = map.get(s); + e.setText(o != null ? o.toString() : ""); + } + } + + //添加节点 + public static void addNode(Element pnode, String name, Object value){ + Element e = pnode.addElement(name); + e.setText(value != null ? value.toString() : ""); + } + + public static void main(String[] args) { + try { + Document doc = readXmlDocument("f:\\temp\\plugin-developer.xml"); + Element e = doc.getRootElement(); + System.out.println("id:::::::" + getAttribute(e, "id")); + System.out.println("name:::::::" + getAttribute(e, "name")); + System.out.println("vvvv:::::::" + getAttribute(e, "呵呵")); +// e.accept(new VisitorSupport() { +// public void visit(Element element) { +// System.out.println(element.getName() + ":::eee:::" + element.getText()); +// } +// +// public void visit(Attribute a) { +// System.out.println(a.getName() + ":::aaa:::" + a.getValue()); +// } +// }); + // 枚举所有子节点 + Element e1 = e.element("fields"); + e1 = e1.element("field"); + System.out.println(getAttributeIgnoreNull(e1, "id")); + + setAttribute(e, "vvvv", "tttttttt"); + //e.addCDATA("asdasd"); + saveToFileCompact(doc, "f:\\temp\\plugin-developer1.xml"); + saveToFilePretty(doc, "f:\\temp\\plugin-developer2.xml"); + saveToFile(doc, "f:\\temp\\plugin-developer3.xml"); + } catch (Exception e1) { + e1.printStackTrace(); + } + } +}