Java实现Oracle的to_char函数
/** * 将int、long、double、float、String、Date等类型format成字符类型 * * 一、数字format格式处理: * 01)99.99的实现,小数位四舍五入不够位数补0,整数位超出位数补空格; * 02)00.00的实现,小数位四舍五入不够位数补0,整数位超出位数补0; * 03)9099.99的实现,小数位四舍五入不够位数补0,整数位超出位数的长度 - indexOf("0")的长度补0,剩余位数补空格; * 04)FM99.99:去除整数位补位的空格和小数位补位的0 * 05)FM99099.99:去除整数位补位的空格和小数位补位的0 * 06)FM99099.99099:去除整数位补位的空格和从小数点最右边那个0之后的9补位的0 * 07)9G999或9G09G99G9G:分组处理(format带G不带小数),只要是带G的地方就替换为,号,在补0之后补空格之前处理。format从左往右出现第一个0之前的补空格中的G不做处理。固定位替换没有出现的位置不做替换和java中的DecimalFormat有所区别。G分组和,号分组不可同时出现。 * 08)9,999.99:分组(千)分隔符处理,和上面G分组处理一样,只是,号分组format可带小数部分,要做特殊处。G分组和,号分组不可同时出现。 * 09)999D999:小数点,按照正常.处理,但是含D不含. * 10)999S或S999:带-或者+的处理,在出现在末尾就将-或者+放数字末尾,出现在首位负数不做处理,整数没有带+号的得带上。S只能出现在首尾位置且只能出现一次。 * 11)999MI:如果数字 < 0 将负号置于末尾位置,MI与S不能同时出现; * 12)999PR:尖括号内负值,不能和S、MI同时存在,且只能出现在末尾位置,如果转换的数字为负数则去掉负号然后<>括起来; * 13)L999:货币符号(使用本地化),在数字前面加上本地化的货币化符号,只能出现在首位位置; * 14)RN:将阿拉伯数字转为罗马数字(输入在 1 和 3999 之间,否则返回:###############); * 15)99V999:移动n位小数,不能和D、.符号共存,最终可以将V换成.计算后再去掉.符号即为移动的位数; * * 二、日期format格式处理: * 01)年份: * Y,YYY:四位带逗号的年,如:2,018 * YYYY:四位的年,如:2018 * YYY:年的后三位,如:018 * YY:年的后两位,如:18 * Y:年的最后一位,如:8 * 02)月份(中文下取值都一样,都是:十一月): * month:全长小写月份名,如:november * Month:全长混合大小写月份名,如:November * MONTH:全长大写月份名,如:NOVEMBER * mon:小写缩写月份名,如:nov * Mon:缩写混合大小写月份名,如:Nov * MON:大写缩写月份名,如:NOV * MM:月份 (01-12) ,如:08、11 * 03)日: * DDD:一年里的日子(001-366) ,如:311 * DD:一个月里的日子(01-31) ,如:07 * D:一周里的日子(1-7;SUN=1),如:4 * 04)时: * HH、HH12:一天的小时数 (01-12) 12小时制,如:02 * HH24:一天的小时数 (00-23) 24小时制,如:15 * 05)分: * MI:分钟 (00-59),如:50 * 06)秒 * SS:秒 (00-59),如:12 * 07)星期(中文下都一样,取值都是:星期四): * DAY:全长大写日期名,如:THURSDAY * Day:全长混合大小写日期名,如:Thursday * day:全长小写日期名,如:thursday * DY:缩写大写日期名,如:THU * Dy:缩写混合大小写日期名,如:Thu * dy:缩写小写日期名,如:thu * 08)午夜00:00到当前时间的秒 * SSSSS:午夜后的秒 (0-86399),如:55302 * 09)正午标识 * AM、A.M.、am、a.m.、PM、P.M.、pm、p.m.:如:中文显示:上午、下午;英文显示:给定值相同的格式和大小写,只是am、pm的区别 * 10)年标识 * BC、B.C.、bc、b.c.、AD、A.D.、ad、a.d.:如:中文显示:公元、公元前,英文显示:AD、BC * 11)当月第几周 * W:如:1 * 12)当年第几周 * WW:如:45 * 13)世纪(2 位) * CC:如:21 * 14)儒略日 * J:Julian 日期(自公元前4712年1月1日来的日期),如:2458430 * 15)季度 * Q:当前是第几季度,例如:4 * 16)罗马数字的月份 * RM:大写罗马月份,如:XI * rm:小写罗马月份,如:xi * * * * @return 转换后的字符串 */ public static <T> String to_char(T data, String format) { if(data instanceof Date || data instanceof Instant || data instanceof LocalDateTime) {//日期格式化 LocalDateTime localDateTime; if(data instanceof Date) { localDateTime = LocalDateTime.ofInstant(((Date) data).toInstant(), ZoneId.systemDefault()); } else if(data instanceof Instant) { localDateTime = LocalDateTime.ofInstant(((Instant) data), ZoneId.systemDefault()); } else { localDateTime = (LocalDateTime) data; } Locale locale = Locale.UK; //年 String year = String.valueOf(localDateTime.getYear()); //月,如:十一月 November String month_full = localDateTime.getMonth().getDisplayName(TextStyle.FULL, locale); //月,如:十一月 Nov String month_short = localDateTime.getMonth().getDisplayName(TextStyle.SHORT, locale); //月,如:11 String month_num = String.valueOf(localDateTime.getMonthValue() > 9 ? localDateTime.getMonthValue() : "0" + localDateTime.getMonthValue()); //当月第几天,如:8 String dayOfMonth = String.valueOf(localDateTime.getDayOfMonth() > 9 ? localDateTime.getDayOfMonth() : "0" + localDateTime.getDayOfMonth()); //当年第几天,如:312 String dayOfYear = String.valueOf(localDateTime.getDayOfYear()); //当周第几天,如:5(localdatetime获取的都是本地化的,老外的一周是从周日开始的,所以加一) String dayOfWeek = String.valueOf(localDateTime.getDayOfWeek().getValue() + 1); //小时HH24 String hour24 = String.valueOf(localDateTime.getHour() > 9 ? localDateTime.getHour() : "0" + localDateTime.getHour()); //小时12 int hour12_temp = localDateTime.getHour(); if(localDateTime.getHour() > 12) { hour12_temp -= 12; } String hour12 = String.valueOf(hour12_temp > 9 ? hour12_temp : "0" + hour12_temp); //分 String minute = String.valueOf(localDateTime.getMinute() > 9 ? localDateTime.getMinute() : "0" + localDateTime.getMinute()); //秒 String second = String.valueOf(localDateTime.getSecond() > 9 ? localDateTime.getSecond() : "0" + localDateTime.getSecond()); //星期 String week_short = localDateTime.getDayOfWeek().getDisplayName(TextStyle.SHORT, locale); String week_full = localDateTime.getDayOfWeek().getDisplayName(TextStyle.FULL, locale); //午夜0点到现在的秒数 String mid_second = String.valueOf(ChronoUnit.SECONDS.between(LocalDateTime.of(localDateTime.getYear(), localDateTime.getMonthValue(), localDateTime.getDayOfMonth(), 0, 0, 0), localDateTime)); //正午标识AM or PM String high_noon_symbol = localDateTime.format(DateTimeFormatter.ofPattern("a", locale)); String ampm_dot = high_noon_symbol; if(locale.getLanguage().equals("en")) { ampm_dot = (new StringBuilder(ampm_dot).insert(1, ".").insert(3, ".")).toString(); } //世纪标识 AD or BC String century_symbol = localDateTime.format(DateTimeFormatter.ofPattern("G", locale)); String adbc_dot = century_symbol; if(locale.getLanguage().equals("en")) { adbc_dot = (new StringBuilder(adbc_dot).insert(1, ".").insert(3, ".")).toString(); } //当月第几周 String weekOfMonth = localDateTime.format(DateTimeFormatter.ofPattern("W", locale)); //当年第几周 String weekOfYear = localDateTime.format(DateTimeFormatter.ofPattern("w", locale)); //获取给定的时间是第几世纪 String century = String.valueOf((int) Math.ceil(localDateTime.getYear() / 100.0)); //儒略日 int a = (14 - localDateTime.getMonthValue()) / 12; int y = localDateTime.getYear() + 4800 - a; int m = localDateTime.getMonthValue() + 12 * a - 3; String julian = String.valueOf(localDateTime.getDayOfMonth() + (153 * m + 2) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 32045); //季度 String quarterOfYear = localDateTime.format(DateTimeFormatter.ofPattern("Q", locale)); //罗马数字的月份 String rm_month = to_char(localDateTime.getMonthValue(), "RN"); String date_format = format.replaceAll("((?i)Y),(?i)YYY", new StringBuilder(year).insert(1, ",").toString())//处理年:y,yyy 带逗号的年(4 和更多位) .replaceAll("(?i)YYYY", year)//处理年:yyyy 年(4和更多位) .replaceAll("(?i)YYY", year.substring(1))//处理年:yyy 年的后三位 .replaceAll("(?i)YY", year.substring(2))//处理年:yy 年的后两位 .replaceAll("(?<!DA|Da|da|D|d)(?i)Y", year.substring(3))//处理年:y 年的最后一位 .replaceAll("(?i)J", julian)//Julian日(自公元前4712年1月1日来的日期) .replaceAll("MONTH", month_full.toUpperCase())//处理月份:MONTH 全长大写月份名(9字符) .replaceAll("Month", month_full)//处理月份:Month 全长混合大小写月份名(9字符) .replaceAll("month", month_full.toLowerCase())//处理月份:month 全长小写月份名(9字符) .replaceAll("MON", month_short.toUpperCase())//处理月份:MON 大写缩写月份名(3字符) .replaceAll("Mon", month_short)//处理月份:Mon 缩写混合大小写月份名(3字符) .replaceAll("mon", month_short.toLowerCase())//处理月份:mon 小写缩写月份名(3字符) .replaceAll("(?i)MM", month_num)//处理月:MM 月份 (01-12) .replaceAll("(?i)DDD", dayOfYear)//处理日:DDD 一年里的日子(001-366) .replaceAll("(?i)DD", dayOfMonth)//处理日:DD 一个月里的日子(01-31) .replaceAll("(?<!a|A)(?i)D(?!ay|y|\\.|ecember)", dayOfWeek)//处理日:D 一周里的日子(1-7;SUN=1) .replaceAll("(?i)HH24", hour24)//小时处理:HH24 一天的小时数 (00-23) .replaceAll("(?i)HH12", hour12)//小时处理:HH12 一天的小时数 (01-12) .replaceAll("(?i)HH", hour12)//小时处理:HH 一天的小时数 (01-12) .replaceAll("(?i)MI", minute)//分钟处理:MI 分钟 (00-59) .replaceAll("(?i)SSSSS", mid_second)//处理午夜后的秒:SSSSS (0-86399) .replaceAll("(?i)SS", second)//秒处理:SS 秒 (00-59) .replaceAll("WW", weekOfYear)//当年第几周 .replaceAll("W", weekOfMonth)//当月第几周 .replaceAll("DAY", week_full.toUpperCase())//处理星期:DAY 全长大写日期名(9字符) .replaceAll("day", week_full.toLowerCase())//处理星期:day 全长小写日期名(9字符) .replaceAll("Day", week_full)//处理星期:Day 全长混合大小写日期名(9字符) .replaceAll("DY", week_short.toUpperCase())//处理星期:DY 缩写大写日期名(3字符) .replaceAll("Dy", week_short)//处理星期:Dy 缩写混合大小写日期名(3字符) .replaceAll("dy", week_short.toLowerCase())//处理星期:dy 缩写小写日期名(3字符) .replaceAll("AM", high_noon_symbol)//正午标识:AM .replaceAll("A.M.", ampm_dot)//正午标识:A.M. .replaceAll("am", high_noon_symbol.toLowerCase())//正午标识:am .replaceAll("a.m.", ampm_dot.toLowerCase())//正午标识:a.m. .replaceAll("PM", high_noon_symbol)//正午标识:PM .replaceAll("P.M.", ampm_dot)//正午标识:P.M. .replaceAll("pm", high_noon_symbol.toLowerCase())//正午标识:pm .replaceAll("p.m.", ampm_dot.toLowerCase())//正午标识:p.m. .replaceAll("AM", high_noon_symbol)//正午标识:AM .replaceAll("BC", century_symbol)//世纪标识:BC .replaceAll("bc", century_symbol.toLowerCase())//世纪标识:bc .replaceAll("B.C.", adbc_dot)//世纪标识:B.C. .replaceAll("b.c.", adbc_dot.toLowerCase())//世纪标识:b.c. .replaceAll("AD", century_symbol)//世纪标识:AD .replaceAll("A.D.", adbc_dot)//世纪标识:A.D. .replaceAll("ad", century_symbol.toLowerCase())//世纪标识:ad .replaceAll("a.d.", adbc_dot.toLowerCase())//世纪标识:a.d. .replaceAll("(?i)CC", century)//世纪:CC .replaceAll("(?i)Q", quarterOfYear)//当前是第几季度:Q .replaceAll("RM", rm_month)//大写罗马月份:RM .replaceAll("rm", rm_month.toLowerCase())//小写罗马月份:rm ; return date_format; } else {//数字格式化 try { format = format.toUpperCase(); //format合法性判断:FM只能出现在首位位置、G不能出现在首位位置 if(!format.matches("^[FM]*[0|9|.|,|PR|S|L|D|G|MI|RN|V]*")) { throw new IllegalArgumentException("无效的数字格式模型"); } //判断是否含G(分组)处理,含G不含小数位,且和,不能同时存在 if(format.contains("G") && (format.contains(".") || format.contains(",") || format.startsWith("G"))) { throw new IllegalArgumentException("无效的数字格式模型"); } //判断D和.不能同时存在,且只能出现一次 if(format.contains("D") && (CommonUtil.count(format, "D") > 1 || format.contains("."))) { throw new IllegalArgumentException("无效的数字格式模型"); } //判断S只能出现在首位位置且只能出现一次 if(format.contains("S") && (CommonUtil.count(format, "S") > 1 || (!format.startsWith("S") && !format.endsWith("S")))) { throw new IllegalArgumentException("无效的数字格式模型"); } //判断MI和S不能同时出现,且只能出现在末尾位置 if(format.contains("MI") && (CommonUtil.count(format, "MI") > 1 || format.contains("S") || !format.endsWith("MI"))) { throw new IllegalArgumentException("无效的数字格式模型"); } //判断PR和S、MI不能同时存在,且只能出现在末尾位置 if(format.contains("PR") && (CommonUtil.count(format, "PR") > 1 || format.contains("S") || format.contains("MI") || !format.endsWith("PR"))) { throw new IllegalArgumentException("无效的数字格式模型"); } //判断L货币符号,只能出现在首位位置 if(format.contains("L") && !format.startsWith("L")) { throw new IllegalArgumentException("无效的数字格式模型"); } //判断V,不能和D、.符号共存,且只能出现一次 if(format.contains("V") && (CommonUtil.count(format, "V") > 1 || format.contains("D") || format.contains("."))) { throw new IllegalArgumentException("无效的数字格式模型"); } //处理D,换成.运算 format = format.replace("D", "."); //处理V,换成.运算 boolean v_symbol = false; if(format.contains("V")) { v_symbol = true; format = format.replace("V", "."); } String data_str = to_char(data); //处理RN,转换为罗马数字 if (format.equals("RN")) { int[] numArray = new int[]{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; String[] romaArray = new String[]{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; StringBuffer stringBuffer = new StringBuffer(); int num = (int) Math.round(Double.valueOf(data_str)); if (num < 0 || num > 3999) { return "###############"; } for (int i = 0; i < numArray.length; i++) { int temp = num / numArray[i]; while (temp > 0) { stringBuffer.append(romaArray[i]); temp--; } num = num % numArray[i]; } return stringBuffer.toString(); } //按照plsql执行结果,当format整数部分位数不够data整数部分位数的时候返回format整数位数+1位的# + format小数位+1的# String[] format_num = format.replaceAll("[A-Za-z,]", "").split("\\."); String[] data_num = data_str.replace("-", "").replace("+", "").split("\\."); if(format_num[0].length() < data_num[0].length()) { String result = format_num[0].replaceAll("[9|0]", "#") + "#"; if(format_num.length == 2) { result += format_num[1].replaceAll("[9|0]", "#") + "#"; } return result; } //将9处理成#和0让DecimalFormat可以识别 BigDecimal bigDecimal = new BigDecimal(data_str); String pattern = format_num[0].replace("9", "#").replace("0", "#");//#是不参与补位的 if(format_num.length == 2) { if (format.startsWith("FM")) { //去除小数点后除0补位的0之后由9补位的0 pattern += "." + format_num[1].substring(0, format_num[1].lastIndexOf("0") + 1).replace("9", "0"); pattern += format_num[1].substring(format_num[1].lastIndexOf("0") + 1).replace("9", "#"); } else { pattern += "." + format_num[1].replace("9", "0");//小数点右边转换成0好补位 } } DecimalFormat decimalFormat = new DecimalFormat(pattern); decimalFormat.setRoundingMode(RoundingMode.HALF_UP); String result = decimalFormat.format(bigDecimal); //处理整数部位多余的9补空格、0补0 int beyond_length = format_num[0].length() - data_num[0].length();//整数位格式化超出位数6 format=909909000000.00 data=123456.123456 String sub_format = format_num[0].substring(0, beyond_length);//获取超出位数的格式字符0-6 sub_format=909909 int zero_pos = sub_format.indexOf("0");//从左到右第一次出现0的位置 zero_pos=1 int zero_patch_len = 0, blank_patch_len = 0; if (zero_pos > -1) { zero_patch_len = sub_format.length() - zero_pos;//计算补0的个数 6 - 1 = 5 } blank_patch_len = beyond_length - zero_patch_len;//计算补空格个数 6 - 5 = 1 //整数位补0 while (zero_patch_len > 0) { if (result.contains("+")) { result = result.replace("+", "+0"); } else if (result.contains("-")) { result = result.replace("-", "-0"); } else { result = "0" + result; } zero_patch_len -= 1; } //处理带G和,的分组 int sub_index = 0, total_index = 0; //通过原始format中整数数字的位数和最终格式化后数字的整数位数对比获取真实的format的作用长度,也就是将format中的G对应到结果数字中的位置,并替换成, String integer_format = format.indexOf(".") == -1 ? format : format.substring(0, format.indexOf("."));//防止,号分组会出现小数位的问题 for (int i = integer_format.toCharArray().length - 1; i >= 0 ; i--) { if(Character.isDigit(integer_format.charAt(i))) { sub_index += 1; } total_index += 1; if(sub_index == result.replace("-", "").replace("+", "").split("\\.")[0].length()) { break; } } String format_temp = integer_format.substring((integer_format.length() - total_index)); //将,号分组处理换成G分组一起处理 format_temp = format_temp.replace(",", "G"); int g_index = format_temp.indexOf("G");//G第一个出现的索引位置 StringBuilder sb = new StringBuilder(result); while (g_index != -1) { int insert_index = g_index; if(sb.indexOf("-") != -1 || sb.indexOf("+") != -1) { insert_index += 1; } sb.insert(insert_index, ","); g_index = format_temp.indexOf("G", g_index + 1);//*从这个索引往后开始第一个出现的位置 } result = sb.toString(); System.out.println("format=" + format); //处理S,断定只出现首位位置 if(format.startsWith("S")) { if(!result.startsWith("+") && !result.startsWith("-")) { result = "+" + result; } } else if(format.endsWith("S")) { if(!result.startsWith("+") && !result.startsWith("-")) { result += "+"; } else if(result.startsWith("+")) { result = result.replace("+", ""); result += "+"; } else if(result.startsWith("-")) { result = result.replace("-", ""); result += "-"; } } //处理MI,断定只出现末尾位置,且为负数的时候才处理 if(format.endsWith("MI") && result.startsWith("-")) { result = result.replace("-", ""); result += "-"; } //处理PR,断定只出现在末尾位置,且为负数的时候才做处理 if(format.endsWith("PR") && result.startsWith("-")) { result = result.replace("-", ""); result = "<" + result + ">"; } //处理L,断定只出现在首位位置 if(format.startsWith("L")) { //获取本地货币符号 String currency_format = DecimalFormat.getCurrencyInstance(Locale.getDefault()).format(1); String currency_symbol = currency_format.substring(0, 1); if(result.startsWith("-")) { result = result.replace("-", "-" + currency_symbol); } else { result = currency_symbol + result; } } //处理V,上面是作为小数点处理的,只需要去掉小数点就相当于移动的小数 if(v_symbol) { result = result.replace(".", ""); } //FM处理,判断是否去空格 if (!format.startsWith("FM")) { //最左边补空格 while (blank_patch_len > 0) { result = " " + result; blank_patch_len -= 1; } } return result; } catch (NumberFormatException nfe) { throw new IllegalArgumentException("无效的数字"); } } }