【流水号】java生成流水编号实现,格式【四位前缀+yyyyMMdd+4位流水】

本文介绍了一种流水号生成机制,格式为四位前缀+日期+四位流水,流水部分采用特殊递增规则,如从9999进位到A001,直至ZZZA-ZZZZ。提供了Java实现代码,包括生成流水号、解析日期等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.由于业务需求需要生成流水单号:

1.格式为:四位前缀+yyyyMMdd+4位流水
2.示例:XXXX202003210123
3.要求:同一天内4位流水顺序递增,递增规则如下:
	·0001 - 9999 【达到9999进一位首位为A001】
	·A001 - A999 【进位为B001】
	·B001 - B999
	...
	·Z001 - Z999 【进位为ZA01】
	·ZZ01 - ZZ99
	·ZZZ1 - ZZZ9
	·ZZZA - ZZZZ

2.代码OddUtils.java

package org.jingniu.utils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 流水号生成管理:
 * <p>
 * 请购申请     QGSQ+日期+4位流水
 * 采购申请     CGSQ+日期+4位流水
 * 采购接收     CGRK+日期+4位流水
 * 采购 退货直接更新采购申请  不生成新单据
 **/
public class OddUtil {
	    /**
	     * 采购申请     CGSQ+日期+4位流水
	     */
	    public static final String ODDNUM_CGSQ = "CGSQ";
	    /**
	     * 采购接收     CGRK+日期+4位流水
	     */
	    public static final String ODDNUM_CGRK = "CGRK";
	    /**
	     * 请购申请     QGSQ+日期+4位流水
	     */
	    public static final String ODDNUM_QGSQ = "QGSQ";
	
	    /**
	     * 编写测试流水订单号
	     * @param num
	     * @return
	     */
	    public static String getBody(Integer num) {
	
	        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
	        String str = String.format("%04d", num);
	        return sdf.format(new Date()).substring(0, 8) + str;
	
	    }
	
	    /**
	     * 截取流水单号入库日期
	     *
	     * @param string
	     * @return
	     */
	    public static int getOddSenttime(String string) {
	        int oddSenttime = Integer.parseInt(string.substring(4, 12));
	        return oddSenttime;
	
	    }
	
	    public static int getNowTimeCode() {
	        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
	        int nowTimeCode = Integer.parseInt(simpleDateFormat.format(new Date()).substring(0, 8));
	        return nowTimeCode;
	    }
	
	    public static Map<String, String> splitNum(String str, int i) {
	        HashMap<String, String> om = new HashMap<>();
	        if (i <= str.toCharArray().length) {
	            String suffix = str.substring(0, i);
	            String currStr = str.substring(i);
	            if (isNumeric(currStr)) {
	                om.put("suffix", suffix);
	                om.put("number", currStr);
	                return om;
	            } else {
	                return splitNum(str, i + 1);
	            }
	        } else {
	            return null;
	        }
	    }
	
	    /**
	     * 判断字符串并加一
	     *
	     * @param str
	     * @param i
	     * @return
	     */
	    public static String splitNumNext(String str, int i) {
	        String suffix = str.substring(0, i);
	        String currStr = str.substring(i);
	        if (isNumeric(currStr)) {
	            if (suffix.equals("")) {
	                suffix = null;
	            }
	            if (currStr.equals("")) {
	                currStr = null;
	            }
	            //9999
	            if (suffix == null) {
	                //头
	                if (currStr.equals("9999")) {
	                    return "A001";
	                } else {
	                    return getConvertNum(currStr);
	                }
	            } else if (currStr == null) {
	                if (suffix.equals("ZZZZ")) {
	                    //当天流水号已用完,返回null
	                    return null;
	                } else {//ZZZA-ZZZY 只剩25个加一
	                    String s = getNextChar(suffix);
	                    return s;
	                }
	            } else if (suffix != null && currStr != null) {
	                //suffix长度为0或4的已经在上面处理,此处处理1-3
	                return getNextOdd(suffix.length(), suffix, currStr);
	            }
	        } else {
	            return splitNumNext(str, i + 1);
	        }
	        return null;
	    }
	
	    private static String getNextOdd(int length, String suffix, String currStr) {
	        //前缀长度不可能为4,只处理1,2,3
	        String zNum = length == 2 ? "Z" : length == 3 ? "ZZ" : "";
	        suffix = suffix.substring(length - 1);
	        //不是Z就是A-Y,取得是最后一个字母
	        if (suffix.equals("Z")) {
	            if (currStr.equals("999")) {
	                return "ZA01";
	            } else if (currStr.equals("99")) {
	                return "ZZA1";
	            } else if (currStr.equals("9")) {
	                return "ZZZA";
	            } else {
	                String str = getConvertNum(currStr);
	                return zNum + suffix + str;
	            }
	        } else {
	            //如果不是Z,每个字母满999都要将前缀加一
	            if (currStr.equals("999")) {
	                return zNum + getNextChar(suffix) + "001";
	            } else if (currStr.equals("99")) {
	                return zNum + getNextChar(suffix) + "01";
	            } else if (currStr.equals("9")) {
	                return zNum + getNextChar(suffix) + "1";
	            } else {
	                String str = getConvertNum(currStr);
	                return zNum + suffix + str;
	            }
	        }
	    }
	
	    private static String getConvertNum(String currStr) {
	        return String.format("%0" + currStr.length() + "d", (Integer.parseInt(currStr) + 1));
	    }
	
	    private static String getNextChar(String suffix) {
	        char[] chars = suffix.toCharArray();
	        char last = (char) (chars[chars.length - 1] + 1);
	        chars[chars.length - 1] = last;
	        return String.valueOf(chars);
	    }
	
	
	    public static boolean isNumeric(String str) {
	        Pattern pattern = Pattern.compile("[0-9]*");
	        return pattern.matcher(str).matches();
	    }
	
	
	    /**
	     * 生成流水单号
	     *
	     * @param suffix:     请购申请     QGSQ+日期+4位流水
	     *                    采购申请     CGSQ+日期+4位流水
	     *                    采购接收     CGRK+日期+4位流水
	     * @param oddMaxCode: QGSQ202003010023
	     * @return
	     */
	    public static String createOdd(String suffix, String oddMaxCode) {
	        String nowOdd = null;
	        //如果最大流水单号不为空
	        if (oddMaxCode != null) {
	            //如果当前时间不相同,例如:20181009=!20180809,重新开始以当天日期拼流水单号201810100001
	            if (getNowTimeCode() != getOddSenttime(oddMaxCode)) {
	                int number = 1;
	                nowOdd = new StringBuffer(suffix).append(getBody(number)).toString();
	                //相同,则加1,例如:201810100002
	            } else {
	                //TODO 处理当天超过9999,然后进位 为 A001-A999 B001-B999   ZA01-ZA99
                //获取最后四位流水号
                String odd = oddMaxCode.substring(12, 16);
                String s = splitNumNext(odd, 0);
                nowOdd = new StringBuffer(suffix).append(oddMaxCode.substring(4,12)).append(s).toString();
            }
        } else {
            //如果没有流水单号,以当前日期重新开始生成流水单号
            int number = 1;
            nowOdd = new StringBuffer(suffix).append(getBody(number)).toString();
        }
    	return nowOdd;
	}
}

3.测试:test.java

    public static void main(String[] args) {
        System.err.println(createOdd("QGSQ", "QGSQ202003210123"));
        System.err.println(createOdd("QGSQ", "QGSQ20200321ZZ23"));
        System.err.println(createOdd("QGSQ", "QGSQ20200321ZZZ3"));
        System.err.println(createOdd("QGSQ", "QGSQ20200321ZZ99"));
        System.err.println(createOdd("QGSQ", "QGSQ20200321A013"));
        String name1 = "9998";
        String name2 = "9999";
        String name3 = "A001";
        String name4 = "A998";
        String name5 = "Z001";
        String name6 = "Z999";
        String name7 = "ZA01";
        String name8 = "ZA99";
        String name9 = "ZZ09";
        String name10 = "ZZ99";
        String name11 = "ZZZ1";
        String name12 = "ZZZZ";

        System.err.println(splitNumNext(name1, 0));
        System.err.println(splitNumNext(name2, 0));
        System.err.println(splitNumNext(name3, 0));
        System.err.println(splitNumNext(name4, 0));
        System.err.println(splitNumNext(name5, 0));
        System.err.println(splitNumNext(name6, 0));
        System.err.println(splitNumNext(name7, 0));
        System.err.println(splitNumNext(name8, 0));
        System.err.println(splitNumNext(name9, 0));
        System.err.println(splitNumNext(name10, 0));
        System.err.println(splitNumNext(name11, 0));
        System.err.println(splitNumNext(name12, 0));

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皇夜_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值