YYMMDD转换成4位字符压缩表示算法java实现——应用各位不等进制的思想

来源:互联网 发布:linux iic架构 编辑:程序博客网 时间:2024/06/05 19:07
</pre><pre name="code" class="java">先上代码。
package com.yundaex.open.basic;public final class YYMMDDDUtil {public static void main(String[] args) {System.out.println(new YYMMDDDUtil().dateDecode("NJJJ"));System.out.println(new YYMMDDDUtil().dateEncode("001231"));}private String MAX_YYMMDD = null;public YYMMDDDUtil() {MAX_YYMMDD = dateEncode("001231");}/** * 压缩年月日 *  * @param yymmdd *            日期 * @return 压缩后年月日 */public String dateEncode(String yymmdd) {if (yymmdd == null || yymmdd.length() != 6) {throw new IllegalArgumentException(yymmdd + " is not [yymmdd] formated");}int y1 = Integer.parseInt(yymmdd.substring(0, 1));int y2 = Integer.parseInt(yymmdd.substring(1, 2));if (y1 == 0 && y2 == 0) {y1 = 10;}int mm = Integer.parseInt(yymmdd.substring(2, 4));if (mm > 12 || mm < 1) {throw new IllegalArgumentException(yymmdd.substring(2, 4) + " is not [mm] formated");}int dd = Integer.parseInt(yymmdd.substring(4, 6));if (dd > 31 || dd < 1) {throw new IllegalArgumentException(yymmdd.substring(4, 6) + " is not [dd] formated");}// 转换成10进制int total = y1 * (10 * 12 * 31) + y2 * (12 * 31) + (mm - 1) * (31) + (dd - 1);return int2str(total);}/** * 10进制转换成压缩后形式 *  * @param num * @return */private String int2str(int num) {int ext = 0;ext = num % (factor * factor * factor);int n1 = (num - ext) / (factor * factor * factor);num = ext;ext = num % (factor * factor);int n2 = (num - ext) / (factor * factor);num = ext;ext = num % (factor);int n3 = (num - ext) / factor;int n4 = ext;return "" + chars[n1] + chars[n2] + chars[n3] + chars[n4];}private int factor = 14;private char[] chars = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N' };/** * 解压年月日 *  * @param ssss *            四位压缩的年月日 * @return 解压压后年月日 */public String dateDecode(String ssss) {if (ssss == null || ssss.length() != 4) {throw new IllegalArgumentException("\"" + ssss + "\" is not [ssss] formated");}if (ssss.compareTo(MAX_YYMMDD) > 0) {throw new IllegalArgumentException("\"" + ssss + "\" has exceed MAX_YYMMDD: " + MAX_YYMMDD);}int total = 0;int f = factor * factor * factor;// 转换到10进制for (char c : ssss.toCharArray()) {for (int j = 0; j < chars.length; j++) {if (c == chars[j]) {total += j * f;f = f / factor;break;}if (j == chars.length - 1) {throw new IllegalArgumentException(c + " in \"" + ssss + "\" is not illeagle");}}}return int2date(total);}/** * 10进制转换成年月日 *  * @param num * @return */private String int2date(int num) {int ext = 0;ext = num % (10 * 12 * 31);int n1 = (num - ext) / (10 * 12 * 31);num = ext;ext = num % (12 * 31);int n2 = (num - ext) / (12 * 31);num = ext;ext = num % (31);int n3 = (num - ext) / 31 + 1;int n4 = ext + 1;if (n1 == 10 && n2 == 0) {n1 = 0;}return "" + n1 + n2 + formatInt(n3) + formatInt(n4);}private String formatInt(int num) {if (num < 10) {return "0" + num;}return "" + num;}}

我的思路是根据以前学过的10进制和2进制的互转,只不过不同的是,这里的YYMMDD中,Y表示0-9,这一位就相当于1个10进制位,而MM这两位相当于12进制位,DD相当于32进制位。

因为加减乘除算法都是建立在10进制的基础上,所以中间都要变换成为10进制,这时候,YYMMDD能够表示的最大的10进制数字也就是10*12*31-1了,再将它转换成诸如16进制,15进制,14进制都可以,(经过测试,用4位字符表示的话,至少需要有14个元字符)。


这里的chars是可以自由定义的,而且还有一个factor来控制进制。



  最后说明下这个算法的利用场景:

      在大数据的年代,项目中生成流水号,可能会因为系统一轮分配结束,重新初始化流水号的时候,到底流水号冲突,会产生财务问题。所以需要在流水号之前加上了一个与年月日一一对应的字符表示,最后为了节省字符,就采取了这种算法。



0 0
原创粉丝点击