java开发中常用工具类的汇总(二)

通用工具类

AES加密解密工具类

作用:防止明文前后端传输密码和账号
使用方法: 按照规则定义好key和iv,然后将定义的key和iv告知前端,让前端进行加密,对应的后端进行解密(代码里已写入测试方法,可测试key和iv是否可用)

import cn.hutool.crypto.digest.DigestUtil;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class AesDecryptUtil {

    private static final String KEY_ALGORITHM = "AES";
    private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";

    /**
     * AES解密
     * @param content 待解密的内容,Base64编码字符串
     * @param key 密钥,需要是16位、24位或32位长度的字符串
     * @param iv 初始化向量,16位长度的字符串,CBC模式下需要
     * @return 解密后的明文字符串
     * @throws Exception 加解密异常
     */
    public static String decrypt(String content, String key, String iv) throws Exception {
        // 将密钥和初始化向量转换为字节数组
        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
        byte[] ivBytes = iv.getBytes(StandardCharsets.UTF_8);

        // 创建密钥规范
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, KEY_ALGORITHM);

        // 创建初始化向量规范
        IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);

        // 获取Cipher实例
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);

        // 初始化Cipher为解密模式,并设置密钥和初始化向量
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

        // Base64解码待解密内容
        byte[] encryptedBytes = Base64.getDecoder().decode(content);

        // 执行解密操作
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);

        // 返回解密后的字符串
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }

    /**
     * <h2>加密 - 自定义加密模式</h2>
     * @param text 需要加密的文本内容
     * @param key 加密的密钥 key
     * @param iv 初始化向量
     * */
    public static String encrypt(String text, String key, String iv){
        try {
            byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
            byte[] ivBytes = iv.getBytes(StandardCharsets.UTF_8);

            // 创建AES加密器
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            SecretKeySpec keySpec = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(ivBytes));

            // 加密字节数组
            byte[] encryptedBytes = cipher.doFinal(text.getBytes());

            // 将密文转换为 Base64 编码字符串
            return Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        try {
//            String ciphertext = "UWs+WmaY3/bwsBW7oHXLAQ==";
//            String key = "12345678ABCDEFGH"; // 请确保密钥长度为16、24或32位
//            String iv = "12345678ABCDEFGH"; // 对于CBC模式,IV长度通常为16位
//            String plaintext = decrypt(ciphertext, key, iv);
//            System.out.println("解密后的明文: " + plaintext);

            // 测试加密
            String password = "123456abc";
            String key2 = "12345678ABCDEFGH";
            String iv2 = "12345678ABCDEFGH";
            String encrypt = encrypt(password, key2, iv2);
            System.out.println("加密后的密文: " + encrypt);
            System.out.println("解密后的密文:" + decrypt("NL6KVcpTyjdATRWr0MeaEw==", key2, iv2));
            System.out.println("对明文进行MD5加密: " + DigestUtil.md5Hex(password));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

脱敏工具类

作用:对一些敏感数据进行脱敏,例如身份证号,手机号,车牌号
使用:在对应的返回类的具体变量上加上注解,根据类型使用不同注解
例如

#这个代码是举例如何使用的参考代码,具体工具类代码在下面
    @ApiModelProperty("手机号")
    @DataMasking(type = DataMaskingType.MOBILE_PHONE)
    private String phone;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.util.Objects;

/**
 * @author Bummon
 * @description
 * @date 2023-09-01 18:14
 */
@AllArgsConstructor
@NoArgsConstructor
public class DataMaskingSerialize extends JsonSerializer implements ContextualSerializer {

    private DataMaskingType type;

    private Integer start;

    private Integer end;

    @Override
    public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        String value = (String) o;
        switch (type) {

            //中文名
            case CHINESE_NAME:
                if(value.length()>2){
                    jsonGenerator.writeString(StrUtil.isBlank(value) ? "" : StrUtil.hide(value, 1, value.length()-1));
                }else {
                    jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.CHINESE_NAME));
                }
                break;
            //身份证号
            case ID_CARD:
                jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.ID_CARD));
                break;
            //手机号
            case MOBILE_PHONE:
                jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.MOBILE_PHONE));
                break;
            //地址
            case ADDRESS:
                jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.ADDRESS));
                break;
            //密码
            case PASSWORD:
                jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.PASSWORD));
                break;
            //中国大陆车牌号
            case CAR_LICENSE:
                jsonGenerator.writeString(StrUtil.isBlank(value) ? "" : StrUtil.hide(value, 2, value.length()));
                //jsonGenerator.writeString(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.CAR_LICENSE));
                break;
            //自定义
            case VIN:
                jsonGenerator.writeString(CharSequenceUtil.hide(value, start, end));
                break;
            //自定义
            case CUSTOM:
                jsonGenerator.writeString(CharSequenceUtil.hide(value, start, end));
                break;
            default:
                break;
        }
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        if (Objects.nonNull(beanProperty)) {
            //判断是否为string类型
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
                DataMasking anno = beanProperty.getAnnotation(DataMasking.class);
                if (Objects.isNull(anno)) {
                    anno = beanProperty.getContextAnnotation(DataMasking.class);
                }
                if (Objects.nonNull(anno)) {
                    return new DataMaskingSerialize(anno.type(), anno.start(), anno.end());
                }
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }
}
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author Bummon
 * @description 数据脱敏自定义注解
 * @date 2023-09-01 18:01
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = DataMaskingSerialize.class)
public @interface DataMasking {

    /**
     * 数据脱敏类型
     */
    DataMaskingType type() default DataMaskingType.CUSTOM;

    /**
     * 脱敏开始位置(包含)
     */
    int start() default 0;

    /**
     * 脱敏结束位置(不包含)
     */
    int end() default 0;

}
public enum DataMaskingType {

    /**
     * 中文名
     */
    CHINESE_NAME,
    /**
     * 身份证号
     */
    ID_CARD,
    /**
     * 手机号
     */
    MOBILE_PHONE,
    /**
     * 地址
     */
    ADDRESS,
    /**
     * 密码
     */
    PASSWORD,
    /**
     * 中国大陆车牌号
     */
    CAR_LICENSE,
    /**
     * VIN
     */
    VIN,
    /**
     * 自定义类型
     */
    CUSTOM;

}

Http请求工具类

作用:向指定的url发送http请求
使用说明:直接调用工具类的对应方法,配置好相应请求参数



import lombok.extern.slf4j.Slf4j;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;

/**
 * RequestHttp概要说明:Http请求工具类
 */
@Slf4j
public class RequestHttp {
 
	/**
	 * 向指定URL发送GET方法的请求
	 * 
	 * @param url   发送请求的URL
	 * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return URL 所代表远程资源的响应结果
	 */
	public static String sendGet(String url, String param) {
		String result = "";
		BufferedReader in = null;
		try {
			String urlNameString = url + "?" + param;
			URL realUrl = new URL(urlNameString);
			// 打开和URL之间的连接
			URLConnection connection = realUrl.openConnection();
			// 设置通用的请求属性
			connection.setRequestProperty("accept", "*/*");
			connection.setRequestProperty("connection", "Keep-Alive");
			connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// 建立实际的连接
			connection.connect();
			// 定义 BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(connection.getInputStream(),"UTF-8"));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			log.error("发送GET请求出现异常!" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输入流
		finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return result;
	}
 
	
	/**
	 * 向指定 URL 发送POST方法的请求
	 * 
	 * @param url   发送请求的 URL
	 * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendPost(String url, String param) {
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 发送请求参数
			out.print(param);
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			System.out.println("发送 POST 请求出现异常!" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输出流、输入流
		finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}
 
	
	
	/**
	 * asUrlParams方法慨述: 将map转化key=123&v=456格式 为只要确保你的编码输入是正确的,就可以忽略掉
	 * UnsupportedEncodingException 创 建 人:dyt 创建时间:2022年1月14日 上午10:13:42 修 改 人:dyt
	 * 修改日期:2022年1月14日 上午10:13:42 @param source @return String @throws
	 */
	public static String asUrlParams(Map<String, String> source) {
		Iterator<String> it = source.keySet().iterator();
		StringBuilder paramStr = new StringBuilder();
		while (it.hasNext()) {
			String key = it.next();
			String value = source.get(key);
			if (StringUtils.isBlank(value)) {
				continue;
			}
			try {
				// URL 编码
				value = URLEncoder.encode(value, "utf-8");
			} catch (UnsupportedEncodingException e) {
				// do nothing
			}
			paramStr.append("&").append(key).append("=").append(value);
		}
		// 去掉第一个&
		return paramStr.substring(1);
	}

}

雪花算法工具类

使用:无需多言,要用的自然知道这个要做啥的

import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 描述: Twitter的分布式自增ID雪花算法snowflake
 **/
public class SnowFlakeUtil {

    /**
     * 起始的时间戳
     */
    private final static long START_STMP = 1480166465631L;

    /**
     * 每一部分占用的位数
     */
    private final static long SEQUENCE_BIT = 12; //序列号占用的位数
    private final static long MACHINE_BIT = 5;   //机器标识占用的位数
    private final static long DATA_CENTER_BIT = 5;//数据中心占用的位数

    /**
     * 每一部分的最大值
     */
    private final static long MAX_DATA_CENTER_NUM = -1L ^ (-1L << DATA_CENTER_BIT);
    private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
    private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);

    /**
     * 每一部分向左的位移
     */
//    private final static long MACHINE_LEFT = SEQUENCE_BIT;
//    private final static long DATACENTER_LEFT = MACHINE_LEFT + MACHINE_BIT;
//    private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATA_CENTER_BIT;


    private final static long DATA_CENTER_LEFT = MACHINE_BIT;
    private final static long SEQUENCE_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT;
    private final static long TIMESTMP_LEFT = SEQUENCE_LEFT + SEQUENCE_BIT;

    private long datacenterId;  //数据中心
    private long machineId;     //机器标识
    private long sequence = 0L; //序列号
    private long lastStmp = -1L;//上一次时间戳

    public SnowFlakeUtil(long datacenterId, long machineId) {
        if (datacenterId > MAX_DATA_CENTER_NUM || datacenterId < 0) {
            throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
        }
        if (machineId > MAX_MACHINE_NUM || machineId < 0) {
            throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
        }
        this.datacenterId = datacenterId;
        this.machineId = machineId;
    }

    /**
     * 获取实例
     *
     * @return
     */
    public static SnowFlakeUtil getInstance() {
        return getInstance(true);
    }

    public static SnowFlakeUtil getInstance(boolean random) {
        if (random) {
            Random rand = new Random();
            int min = 0;
            int max = 30;
            int s = rand.nextInt(max) % (max - min + 1) + min;
            int e = rand.nextInt(max) % (max - min + 1) + min;
            return getInstance(s, e);
        } else {
            return getInstance(1, 1);
        }
    }

    private static final ConcurrentHashMap<String, SnowFlakeUtil> SNOW_MAP = new ConcurrentHashMap<>();

    /**
     * 获取实例
     *
     * @param datacenterId
     * @param machineId
     * @return
     */
    public static SnowFlakeUtil getInstance(long datacenterId, long machineId) {
        String key = new StringBuilder().append("datacenterId=").append(datacenterId).append(" machineId=").append(machineId).toString();
        SNOW_MAP.putIfAbsent(key, new SnowFlakeUtil(datacenterId, machineId));
        return SNOW_MAP.get(key);
    }

    /**
     * 产生下一个ID
     *
     * @return
     */
    public synchronized long nextId() {
        long currStmp = getNewstmp();
        if (currStmp < lastStmp) {
            throw new RuntimeException("Clock moved backwards.  Refusing to generate id");
        }

        if (currStmp == lastStmp) {
            //相同毫秒内,序列号自增
            sequence = (sequence + 1) & MAX_SEQUENCE;
            //同一毫秒的序列数已经达到最大
            if (sequence == 0L) {
                currStmp = getNextMill();
            }
        } else {
            //不同毫秒内,序列号置为0
            sequence = 0L;
        }

        lastStmp = currStmp;

//        return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分
//                | datacenterId << DATACENTER_LEFT       //数据中心部分
//                | machineId << MACHINE_LEFT             //机器标识部分
//                | sequence;                             //序列号部分

        return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分
                | sequence << SEQUENCE_LEFT             //序列部分
                | datacenterId << DATA_CENTER_LEFT      //数据中心部分
                | machineId;                            //机器部分
    }

    private long getNextMill() {
        long mill = getNewstmp();
        while (mill <= lastStmp) {
            mill = getNewstmp();
        }
        return mill;
    }

    private long getNewstmp() {
        return System.currentTimeMillis();
    }

}

弱密码校验工具类

作用:登录的时候校验密码是否是弱密码
使用:根据对应的需求,修改对应的代码

import java.util.*;

public class HandlePasswordUtil {
    /**
     * 对密码进行校验判断,弱密码将返回true,强密码返回false
     * 
     * 如果密码是以下几种情况将返回true,即是弱密码:
     * 1.如果密码是admin、
     * 2.密码位数小于等于6位、
     * 3.密码全部是相同的字符(如:aaaaaaa、8888888)、
     * 4.密码全部是空字符、
     * 5.密码全是顺序字符(如:123456、987654、bcdefg、gfedcb)
     */
    public static boolean isWeekPassword(String password) {
        password = password.trim();
        //判断密码是不是特殊的admin
        if (password.length() <= 8) {
            return true;
        }
        char[] chPassword = password.toCharArray();
        LinkedHashSet<Character> link = new LinkedHashSet<>();
        StringBuilder buff = new StringBuilder();
        boolean result = false;
        int count = 0;
        for (int i = 0; i < chPassword.length; i++) {
            //判断密码是否是连续的正序或降序数字或字母
            int preNumber = i == 0 ? -999 : chPassword[i - 1] - 0; //前一字符对应的ascii码
            int currentNumber = chPassword[i] - 0;//当前字符对应的ascii码
            int asciiNum = preNumber + currentNumber;
            if ((96 <= asciiNum && asciiNum <= 114) || (130 <= asciiNum && asciiNum <= 180) || (194 <= asciiNum && asciiNum <= 244)) {
                //判断密码的相邻字符是否是正序或降序的数字或字符
                if (Math.abs(preNumber - currentNumber) == 1) {
                    count += 1;
                }
            }
            //处理不重复的字符
            if (!link.contains(chPassword[i])) {
                link.add(chPassword[i]);
                buff.append(chPassword[i]);
            }
        }
        //处理空字符串和密码全是同一字符的
        String resultStr = String.valueOf(buff);
        if (count == chPassword.length - 1 || resultStr.length() <= 1) {
            result = true;
        }
        return result;
    }
}

时间格式和日期工具类

使用:将一些时间格式和日期要求的工具类进行了汇总

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

public class DateUtils {

    /** 一星期的天数 */
    public static final int WEEK_DAYS = 7;
    /** 一年的月份数 */
    public static final int YEAR_MONTHS = 12;
    /** 一天的小时数 */
    public static final int DAY_HOURS = 24;
    /** 一小时分钟数 */
    public static final int HOUR_MINUTES = 60;
    /** 一天分钟数 (24 * 60) */
    public static final int DAY_MINUTES = 1440;
    /** 一分钟的秒数 */
    public static final int MINUTE_SECONDS = 60;
    /** 一个小时的秒数 (60 * 60) */
    public static final int HOUR_SECONDS = 3600;
    /** 一天的秒数 (24 * 60 * 60) */
    public static final int DAY_SECONDS = 86400;
    /** 一秒的毫秒数 */
    public static final long SECOND_MILLISECONDS = 1000L;
    /** 一分钟的毫秒数(60 * 1000) */
    public static final long MINUTE_MILLISECONDS = 60000L;
    /** 一小时的毫秒数(60 * 60 * 1000) */
    public static final long HOUR_MILLISECONDS = 3600000L;
    /** 一天的毫秒数(24 * 60* 60* 1000) */
    public static final long DAY_MILLISECONDS = 86400000L;
    /** 星期一 */
    public static final int WEEK_1_MONDAY = 1;
    /** 星期二 */
    public static final int WEEK_2_TUESDAY = 2;
    /** 星期三 */
    public static final int WEEK_3_WEDNESDAY = 3;
    /** 星期四 */
    public static final int WEEK_4_THURSDAY = 4;
    /** 星期五 */
    public static final int WEEK_5_FRIDAY = 5;
    /** 星期六 */
    public static final int WEEK_6_SATURDAY = 6;
    /** 星期天 */
    public static final int WEEK_7_SUNDAY = 7;
    /** 一月 */
    public static final int MONTH_1_JANUARY = 1;
    /** 二月 */
    public static final int MONTH_2_FEBRUARY = 2;
    /** 三月 */
    public static final int MONTH_3_MARCH = 3;
    /** 四月 */
    public static final int MONTH_4_APRIL= 4;
    /** 五月 */
    public static final int MONTH_5_MAY = 5;
    /** 六月 */
    public static final int MONTH_6_JUNE = 6;
    /** 七月 */
    public static final int MONTH_7_JULY = 7;
    /** 八月 */
    public static final int MONTH_8_AUGUST = 8;
    /** 九月 */
    public static final int MONTH_9_SEPTEMBER = 9;
    /** 十月 */
    public static final int MONTH_10_OCTOBER = 10;
    /** 十一月 */
    public static final int MONTH_11_NOVEMBER = 11;
    /** 十二月 */
    public static final int MONTH_12_DECEMBER= 12;
    /** 显示到日期 */
    public static final String FORMAT_DATE = "yyyy-MM-dd";
    public static final String YEAR_DATE = "yyyy";
    public static final String MOON_DATE = "MM-dd HH:mm:ss";
    /** 显示到小时 */
    public static final String FORMAT_HOUR = "yyyy-MM-dd HH";
    /** 显示到分 */
    public static final String FORMAT_MINUTE = "yyyy-MM-dd HH:mm";
    /** 显示到秒 */
    public static final String FORMAT_SECOND = "yyyy-MM-dd HH:mm:ss";
    /** 显示到毫秒 */
    public static final String FORMAT_MILLISECOND = "yyyy-MM-dd HH:mm:ss:SSS";
    /** 显示到日期(数字格式) */
    public static final String FORMAT_NO_DATE = "yyyyMMdd";
    /** 显示到小时(数字格式) */
    public static final String FORMAT_NO_HOUR = "yyyyMMddHH";
    /** 显示到分(数字格式) */
    public static final String FORMAT_NO_MINUTE = "yyyyMMddHHmm";
    /** 显示到秒(数字格式) */
    public static final String FORMAT_NO_SECOND = "yyyyMMddHHmmss";
    /** 显示到毫秒(数字格式) */
    public static final String FORMAT_NO_MILLISECOND = "yyyyMMddHHmmssSSS";


    /**
     * 获取指定时间格式化器
     *
     * @param formatStyle 时间格式
     * @return 时间格式化器
     */
    private static SimpleDateFormat getSimpleDateFormat(String formatStyle) {
        return new SimpleDateFormat(formatStyle);
    }

    /**
     * 将 Date 格式时间转化为指定格式时间
     *
     * @param date        Date 格式时间
     * @param formatStyle 转化指定格式(如: yyyy-MM-dd HH:mm:ss)
     * @return 转化格式时间
     */
    public static String format(Date date, String formatStyle) {
        if (Objects.isNull(date)) {
            return "";
        }
        return getSimpleDateFormat(formatStyle).format(date);
    }

    /**
     * 将 Date 格式时间转化为 yyyy-MM-dd 格式时间
     *
     * @param date Date 格式时间
     * @return yyyy-MM-dd 格式时间(如:2022-06-17)
     */
    public static String formatDate(Date date) {
        return format(date, FORMAT_DATE);
    }


    public static String contrastMessageDetail(Date date) {
        if(null == date){
            return format(new Date(), MOON_DATE);
        }
        String nowDate = format(new Date(), YEAR_DATE);
        String contrastDate = format(date, YEAR_DATE);
        if(Integer.parseInt(nowDate) <= Integer.parseInt(contrastDate)){
            return format(date, MOON_DATE);
        }
        return format(date, FORMAT_SECOND);
    }

    /**
     * 将 Date 格式时间转化为 yyyy-MM-dd HH:mm:ss 格式时间
     *
     * @param date Date 格式时间
     * @return yyyy-MM-dd HH:mm:ss 格式时间(如:2022-06-17 16:06:17)
     */
    public static String formatDateTime(Date date) {
        return format(date, FORMAT_SECOND);
    }

    /**
     * 将 Date 格式时间转化为 yyyy-MM-dd HH:mm:ss:SSS 格式时间
     *
     * @param date Date 格式时间
     * @return yyyy-MM-dd HH:mm:ss:SSS 格式时间(如:2022-06-17 16:06:17:325)
     */
    public static String formatDateTimeStamp(Date date) {
        return format(date, FORMAT_MILLISECOND);
    }

    /**
     * 将 yyyy-MM-dd 格式时间转化为 Date 格式时间
     *
     * @param dateString yyyy-MM-dd 格式时间(如:2022-06-17)
     * @return Date 格式时间
     */
    public static Date parseDate(String dateString) {
        return parse(dateString, FORMAT_DATE);
    }

    /**
     * 将 yyyy-MM-dd HH:mm:ss 格式时间转化为 Date 格式时间
     *
     * @param dateTimeStr yyyy-MM-dd HH:mm:ss 格式时间(如:2022-06-17 16:06:17)
     * @return Date 格式时间
     */
    public static Date parseDateTime(String dateTimeStr) {
        return parse(dateTimeStr, FORMAT_SECOND);
    }

    /**
     * 将 yyyy-MM-dd HH:mm:ss:SSS 格式时间转化为 Date 格式时间
     *
     * @param dateTimeStampStr yyyy-MM-dd HH:mm:ss:SSS 格式时间(如:2022-06-17 16:06:17)
     * @return Date 格式时间
     */
    public static Date parseDateTimeStamp(String dateTimeStampStr) {
        return parse(dateTimeStampStr, FORMAT_MILLISECOND);
    }

    /**
     * 将字符串格式时间转化为 Date 格式时间
     *
     * @param dateString 字符串时间(如:2022-06-17 16:06:17)
     * @return formatStyle 格式内容
     * @return Date 格式时间
     */
    public static Date parse(String dateString, String formatStyle) {
        String s = getString(dateString);
        if (s.isEmpty()) {
            return null;
        }
        try {
            return getSimpleDateFormat(formatStyle).parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取字符串有效内容
     *
     * @param s 字符串
     * @return 有效内容
     */
    private static String getString(String s) {
        return Objects.isNull(s) ? "" : s.trim();
    }

    /**
     * 获取一天的开始时间(即:0 点 0 分 0 秒 0 毫秒)
     *
     * @param date 指定时间
     * @return 当天的开始时间
     */
    public static Date getDateStart(Date date) {
        if (Objects.isNull(date)) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取一天的截止时间(即:23 点 59 分 59 秒 999 毫秒)
     *
     * @param date 指定时间
     * @return 当天的开始时间
     */
    public static Date getDateEnd(Date date) {
        if (Objects.isNull(date)) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }

    /**
     * 获取一天的截止时间(即:23 点 59 分 59 秒 999 毫秒)
     *
     * @param date 指定时间
     * @return 当天的开始时间
     */
    public static Date getDateStr(Date date) {
        if (Objects.isNull(date)) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取日期数字
     *
     * @param date 日期
     * @return 日期数字
     */
    public static int getDateNo(Date date) {
        if (Objects.isNull(date)) {
            return 0;
        }
        return Integer.valueOf(format(date, FORMAT_NO_DATE));
    }

    /**
     * 获取日期时间数字(到秒)
     *
     * @param date 日期
     * @return 日期数字
     */
    public static long getDateTimeNo(Date date) {
        if (Objects.isNull(date)) {
            return 0L;
        }
        return Long.valueOf(format(date, FORMAT_NO_SECOND));
    }

    /**
     * 获取日期时间数字(到毫秒)
     *
     * @param date 日期
     * @return 日期数字
     */
    public static long getDateTimeStampNo(Date date) {
        if (Objects.isNull(date)) {
            return 0L;
        }
        return Long.valueOf(format(date, FORMAT_NO_MILLISECOND));
    }

    /**
     * 获取星期几
     *
     * @param date 时间
     * @return 0(时间为空), 1(周一), 2(周二),3(周三),4(周四),5(周五),6(周六),7(周日)
     */
    public static int getWeek(Date date) {
        if (Objects.isNull(date)) {
            return 0;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return getWeek(calendar);
    }

    /**
     * 获取星期几
     *
     * @param calendar 时间
     * @return 0(时间为空), 1(周一), 2(周二),3(周三),4(周四),5(周五),6(周六),7(周日)
     */
    private static int getWeek(Calendar calendar) {
        switch (calendar.get(Calendar.DAY_OF_WEEK)) {
            case Calendar.MONDAY:
                return 1;
            case Calendar.TUESDAY:
                return 2;
            case Calendar.WEDNESDAY:
                return 3;
            case Calendar.THURSDAY:
                return 4;
            case Calendar.FRIDAY:
                return 5;
            case Calendar.SATURDAY:
                return 6;
            case Calendar.SUNDAY:
                return 7;
            default:
                return 0;
        }
    }

    /**
     * 获取该日期是今年的第几周(以本年的周一为第1周,详见下面说明)<br>
     *
     * 【说明】<br>
     * 比如 2022-01-01(周六)和 2022-01-02(周日)虽然在 2022 年里,但他们两天则属于 2021 年最后一周,<br>
     * 那么这两天不会算在 2022 年第 1 周里,此时会返回 0 ;而 2022 年第 1 周将从 2022-01-03(周一) 开始计算。<br>
     *
     * @param date 时间
     * @return -1(时间为空), 0(为上个年的最后一周),其他数字(今年的第几周)
     */
    public static int getWeekOfYear(Date date) {
        if (Objects.isNull(date)) {
            return -1;
        }
        int weeks = getWeekOfYearIgnoreLastYear(date);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.MONTH, Calendar.JANUARY);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        int week = getWeek(calendar);
        if (week == 1) {
            return weeks;
        }
        return weeks - 1;
    }

    /**
     * 获取今年的第几周(以本年的1月1日为第1周第1天)<br>
     *
     * @param date 时间
     * @return -1(时间为空),其他数字(今年的第几周)
     */
    public static int getWeekOfYearIgnoreLastYear(Date date) {
        if (Objects.isNull(date)) {
            return -1;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int days = calendar.get(Calendar.DAY_OF_YEAR);
        int weeks = days / 7;
        // 如果是 7 的倍数,则表示恰好是多少周
        if (days % 7 == 0) {
            return weeks;
        }
        // 如果有余数,则需要再加 1
        return weeks + 1;
    }

    /**
     * 获取时间节点对象
     *
     * @param date 时间对象
     * @return DateNode
     */
    public static DateNode getDateNode(Date date) {
        if (Objects.isNull(date)) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        DateNode node = new DateNode();
        node.setTime(format(date, FORMAT_MILLISECOND));
        node.setYear(calendar.get(Calendar.YEAR));
        node.setMonth(calendar.get(Calendar.MONTH) + 1);
        node.setDay(calendar.get(Calendar.DAY_OF_MONTH));
        node.setHour(calendar.get(Calendar.HOUR_OF_DAY));
        node.setMinute(calendar.get(Calendar.MINUTE));
        node.setSecond(calendar.get(Calendar.SECOND));
        node.setMillisecond(calendar.get(Calendar.MILLISECOND));
        node.setWeek(getWeek(calendar));
        node.setDayOfYear(calendar.get(Calendar.DAY_OF_YEAR));
        node.setWeekOfYear(getWeekOfYear(date));
        node.setWeekOfYearIgnoreLastYear(getWeekOfYearIgnoreLastYear(date));
        node.setMillisecondStamp(date.getTime());
        node.setSecondStamp(node.getMillisecondStamp() / 1000);
        return node;
    }

    /**
     * 日期变更
     *
     * @param date   指定日期
     * @param field  变更属性(如变更年份,则该值为 Calendar.DAY_OF_YEAR)
     * @param amount 变更大小(大于 0 时增加,小于 0 时减少)
     * @return 变更后的日期时间
     */
    public static Date add(Date date, int field, int amount) {
        if (Objects.isNull(date)) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(field, amount);
        return calendar.getTime();
    }

    /**
     * 指定日期加减年份
     *
     * @param date 指定日期
     * @param year 变更年份(大于 0 时增加,小于 0 时减少)
     * @return 变更年份后的日期
     */
    public static Date addYear(Date date, int year) {
        return add(date, Calendar.YEAR, year);
    }

    /**
     * 指定日期加减月份
     *
     * @param date  指定日期
     * @param month 变更月份(大于 0 时增加,小于 0 时减少)
     * @return 变更月份后的日期
     */
    public static Date addMonth(Date date, int month) {
        return add(date, Calendar.MONTH, month);
    }

    /**
     * 指定日期加减天数
     *
     * @param date 指定日期
     * @param day  变更天数(大于 0 时增加,小于 0 时减少)
     * @return 变更天数后的日期
     */
    public static Date addDay(Date date, int day) {
        return add(date, Calendar.DAY_OF_YEAR, day);
    }

    /**
     * 指定日期加减星期
     *
     * @param date 指定日期
     * @param week 变更星期数(大于 0 时增加,小于 0 时减少)
     * @return 变更星期数后的日期
     */
    public static Date addWeek(Date date, int week) {
        return add(date, Calendar.WEEK_OF_YEAR, week);
    }

    /**
     * 指定日期加减小时
     *
     * @param date 指定日期时间
     * @param hour 变更小时数(大于 0 时增加,小于 0 时减少)
     * @return 变更小时数后的日期时间
     */
    public static Date addHour(Date date, int hour) {
        return add(date, Calendar.HOUR_OF_DAY, hour);
    }

    /**
     * 指定日期加减分钟
     *
     * @param date   指定日期时间
     * @param minute 变更分钟数(大于 0 时增加,小于 0 时减少)
     * @return 变更分钟数后的日期时间
     */
    public static Date addMinute(Date date, int minute) {
        return add(date, Calendar.MINUTE, minute);
    }

    /**
     * 指定日期加减秒
     *
     * @param date   指定日期时间
     * @param second 变更秒数(大于 0 时增加,小于 0 时减少)
     * @return 变更秒数后的日期时间
     */
    public static Date addSecond(Date date, int second) {
        return add(date, Calendar.SECOND, second);
    }

    /**
     * 指定日期加减秒
     *
     * @param date   指定日期时间
     * @param millisecond 变更毫秒数(大于 0 时增加,小于 0 时减少)
     * @return 变更毫秒数后的日期时间
     */
    public static Date addMillisecond(Date date, int millisecond) {
        return add(date, Calendar.MILLISECOND, millisecond);
    }

    /**
     * 获取该日期所在周指定星期的日期
     *
     * @param date 日期所在时间
     * @return index 指定星期(1 - 7 分别对应星期一到星期天)
     */
    public static Date getWeekDate(Date date, int index) {
        if (index < WEEK_1_MONDAY || index > WEEK_7_SUNDAY) {
            return null;
        }
        int week = getWeek(date);
        return addDay(date, index - week);
    }

    /**
     * 获取该日期所在周开始日期
     *
     * @param date 日期所在时间
     * @return 所在周开始日期
     */
    public static Date getWeekDateStart(Date date) {
        return getDateStart(getWeekDate(date, WEEK_1_MONDAY));
    }

    /**
     * 获取该日期所在周开始日期
     *
     * @param date 日期所在时间
     * @return 所在周开始日期
     */
    public static Date getWeekDateEnd(Date date) {
        return getWeekDateEnd(getWeekDate(date, WEEK_7_SUNDAY));
    }

    /**
     * 获取该日期所在周的所有日期(周一到周日)
     *
     * @param date 日期
     * @return 该日照所在周的所有日期
     */
    public static List<Date> getWeekDateList(Date date) {
        if (Objects.isNull(date)) {
            return Collections.emptyList();
        }
        // 获取本周开始时间
        Date weekFromDate = getWeekDateStart(date);
        // 获取本周截止时间
        Date weekeEndDate = getWeekDateEnd(date);
        return getBetweenDateList(weekFromDate, weekeEndDate, true);
    }

    public static List<Date> getWeekDates(Date date) {
        List<Date> weekDates = new ArrayList<>();

        // 将Date转换为LocalDate
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1; // 月份从0开始
        int day = calendar.get(Calendar.DAY_OF_MONTH);

        // 获取给定日期所在周的第一天(周一)
        calendar.set(year, month - 1, day);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        int daysUntilMonday = (dayOfWeek - Calendar.MONDAY + 7) % 7;
        calendar.add(Calendar.DAY_OF_MONTH, -daysUntilMonday);

        // 将周一到周日的日期添加到列表中
        for (int i = 0; i < 7; i++) {
            weekDates.add(calendar.getTime());
            calendar.add(Calendar.DAY_OF_MONTH, 1);
        }

        return weekDates;
    }

    /**
     * 获取该日期所在周的所有日期(周一到周日)
     *
     * @param dateString
     * @return 该日照所在周的所有日期
     */
    public static List<String> getWeekDateList(String dateString) {
        Date date = parseDate(dateString);
        if (Objects.isNull(date)) {
            return Collections.emptyList();
        }
        return getDateStrList(getWeekDateList(date));
    }

    /**
     * 获取该日期所在月的所有日期
     *
     * @param date
     * @return 该日照所月的所有日期
     */
    public static List<Date> getMonthDateList(Date date) {
        if (Objects.isNull(date)) {
            return Collections.emptyList();
        }
        Date monthDateStart = getMonthDateStart(date);
        Date monthDateEnd = getMonthDateEnd(date);
        return getBetweenDateList(monthDateStart, monthDateEnd, true);
    }

    /**
     * 获取该日期所在月的所有日期
     *
     * @param dateString
     * @return 该日照所月的所有日期
     */
    public static List<String> getMonthDateList(String dateString) {
        Date date = parseDate(dateString);
        if (Objects.isNull(date)) {
            return Collections.emptyList();
        }
        return getDateStrList(getMonthDateList(date));
    }

    /**
     * 获取本日期所在月第一天
     *
     * @param date 日期
     * @return 本日期所在月第一天
     */
    public static Date getMonthDateStart(Date date) {
        if (Objects.isNull(date)) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        return getDateStart(calendar.getTime());
    }

    /**
     * 获取本日期所在月最后一天
     *
     * @param date 日期
     * @return 本日期所在月最后一天
     */
    public static Date getMonthDateEnd(Date date) {
        if (Objects.isNull(date)) {
            return null;
        }
        Date monthDateStart = getMonthDateStart(date);
        Date nextMonthDateStart = getMonthDateStart(addMonth(monthDateStart, 1));
        return getDateEnd(addDay(nextMonthDateStart, -1));
    }

    /**
     * 获取两个日期相差的天数(以日期为单位计算,不以24小时制计算,详见下面说明)<br>
     *
     * 【说明】比如 2022-06-17 23:00:00 和 2022-06-17 01:00:00,两者虽然只相差 2 个小时,但也算相差 1 天 <br>
     *
     * @param date1 日期1
     * @param date2 日期2
     * @return 相差天数(若返回 -1,则至少有一个日期存在为空,此时不能进行比较)
     */
    public static int countBetweenDays(Date date1, Date date2) {
        if (Objects.isNull(date1) || Objects.isNull(date2)) {
            return -1;
        }
        // 获取两个日期 0 点 0 时 0 分 0 秒 0 毫秒时的时间戳(毫秒级)
        long t1 = getDateStart(date1).getTime();
        long t2 = getDateStart(date2).getTime();
        // 相差天数 = 相差的毫秒数 / 一天的毫秒数
        return (int) (Math.abs(t1 - t2) / DAY_MILLISECONDS);
    }

    /**
     * 获取两个日期之间的所有日期
     *
     * @param date1 日期1
     * @param date2 日期2
     * @return 两个日期之间的所有日期的开始时间
     */
    public static List<Date> getBetweenDateList(Date date1, Date date2) {
        return getBetweenDateList(date1, date2, false);
    }

    /**
     * 获取两个日期之间的所有日期
     *
     * @param date1 日期1
     * @param date2 日期2
     * @return 两个日期之间的所有日期的开始时间
     */
    public static List<Date> getBetweenDateList(Date date1, Date date2, boolean isContainParams) {
        if (Objects.isNull(date1) || Objects.isNull(date2)) {
            return Collections.emptyList();
        }
        // 确定前后日期
        Date fromDate = date1;
        Date toDate = date2;
        if (date2.before(date1)) {
            fromDate = date2;
            toDate = date1;
        }
        // 获取两个日期每天的开始时间
        Date from = getDateStart(fromDate);
        Date to = getDateStart(toDate);
        // 获取日期,开始循环
        List<Date> dates = new ArrayList<Date>();
        if (isContainParams) {
            dates.add(from);
        }
        Date date = from;
        boolean isBefore = true;
        while (isBefore) {
            date = addDay(date, 1);
            isBefore = date.before(to);
            if (isBefore) {
                dates.add(getDateStart(date));
            }
        }
        if (isContainParams) {
            dates.add(to);
        }
        return dates;
    }

    /**
     * 获取两个日期之间的所有日期
     *
     * @param dateString1 日期1(如:2022-06-20)
     * @param dateString2 日期2(如:2022-07-15)
     * @return 两个日期之间的所有日期(不包含参数日期)
     */
    public static List<String> getBetweenDateList(String dateString1, String dateString2) {
        return getBetweenDateList(dateString1, dateString2, false);
    }

    /**
     * 获取两个日期之间的所有日期
     *
     * @param dateString1     日期1(如:2022-06-20)
     * @param dateString2     日期2(如:2022-07-15)
     * @param isContainParams 是否包含参数的两个日期
     * @return 两个日期之间的所有日期的开始时间
     */
    public static List<String> getBetweenDateList(String dateString1, String dateString2, boolean isContainParams) {
        Date date1 = parseDate(dateString1);
        Date date2 = parseDate(dateString2);
        List<Date> dates = getBetweenDateList(date1, date2, isContainParams);
        return getDateStrList(dates);
    }

    /**
     * List<Date> 转 List<String>
     *
     * @param dates 日期集合
     * @return 日期字符串集合
     */
    public static List<String> getDateStrList(List<Date> dates) {
        if (dates.isEmpty()) {
            return Collections.emptyList();
        }
        List<String> dateList = new ArrayList<String>();
        for (Date date : dates) {
            dateList.add(formatDate(date));
        }
        return dateList;
    }

    /**
     * 日期计算年龄
     * @param birthday
     * @return
     */
    public static Integer getAgeByBirthday(Date birthday) {
        Calendar birthDate = Calendar.getInstance();
        birthDate.setTime(birthday);
        Calendar currentDate = Calendar.getInstance();
        int age = currentDate.get(Calendar.YEAR) - birthDate.get(Calendar.YEAR);
        // 可以考虑将当前月份和生日月份进行比较,以确定是否已过生日,进而确定是否需要减少1岁
        if (currentDate.get(Calendar.MONTH) < birthDate.get(Calendar.MONTH)
                || (currentDate.get(Calendar.MONTH) == birthDate.get(Calendar.MONTH)
                && currentDate.get(Calendar.DAY_OF_MONTH) < birthDate.get(Calendar.DAY_OF_MONTH))) {
            age--;
        }
        return age;
    }

    /**
     * 传入时间与当天时间计算时间差 毫秒
     * @param date
     * @return
     */
    public static long getNowAndEntDayDifference(Date date) {
        LocalDateTime strTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        LocalDateTime endTime = LocalDateTime.ofInstant(Objects.requireNonNull(getDateEnd(date)).toInstant(), ZoneId.systemDefault());
        Duration duration = Duration.between(strTime, endTime); // 获取持续时间对象
        return duration.toMinutes() ;
    }
    static class DateNode {
        /** 年 */
        private int year;
        /** 月 */
        private int month;
        /** 日 */
        private int day;
        /** 时 */
        private int hour;
        /** 分 */
        private int minute;
        /** 秒 */
        private int second;
        /** 毫秒 */
        private int millisecond;
        /** 星期几( 1 - 7 对应周一到周日) */
        private int week;
        /** 当年第几天 */
        private int dayOfYear;
        /** 当年第几周(本年周 1 为第 1 周,0 则表示属于去年最后一周) */
        private int weekOfYear;
        /** 当年第几周(本年周 1 为第 1 周,0 则表示属于去年最后一周) */
        private int weekOfYearIgnoreLastYear;
        /** 时间戳(秒级) */
        private long secondStamp;
        /** 时间戳(毫秒级) */
        private long millisecondStamp;
        /** 显示时间 */
        private String time;

        public int getYear() {
            return year;
        }

        public void setYear(int year) {
            this.year = year;
        }

        public int getMonth() {
            return month;
        }

        public void setMonth(int month) {
            this.month = month;
        }

        public int getDay() {
            return day;
        }

        public void setDay(int day) {
            this.day = day;
        }

        public int getHour() {
            return hour;
        }

        public void setHour(int hour) {
            this.hour = hour;
        }

        public int getMinute() {
            return minute;
        }

        public void setMinute(int minute) {
            this.minute = minute;
        }

        public int getSecond() {
            return second;
        }

        public void setSecond(int second) {
            this.second = second;
        }

        public int getMillisecond() {
            return millisecond;
        }

        public void setMillisecond(int millisecond) {
            this.millisecond = millisecond;
        }

        public int getWeek() {
            return week;
        }

        public void setWeek(int week) {
            this.week = week;
        }

        public int getDayOfYear() {
            return dayOfYear;
        }

        public void setDayOfYear(int dayOfYear) {
            this.dayOfYear = dayOfYear;
        }

        public int getWeekOfYear() {
            return weekOfYear;
        }

        public void setWeekOfYear(int weekOfYear) {
            this.weekOfYear = weekOfYear;
        }

        public int getWeekOfYearIgnoreLastYear() {
            return weekOfYearIgnoreLastYear;
        }

        public void setWeekOfYearIgnoreLastYear(int weekOfYearIgnoreLastYear) {
            this.weekOfYearIgnoreLastYear = weekOfYearIgnoreLastYear;
        }

        public long getSecondStamp() {
            return secondStamp;
        }

        public void setSecondStamp(long secondStamp) {
            this.secondStamp = secondStamp;
        }

        public long getMillisecondStamp() {
            return millisecondStamp;
        }

        public void setMillisecondStamp(long millisecondStamp) {
            this.millisecondStamp = millisecondStamp;
        }

        public String getTime() {
            return time;
        }

        public void setTime(String time) {
            this.time = time;
        }

    }

}

String字符串工具类

作用:对String类型字符串进行处理
使用:调用工具类里对应方法

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * String工具类.(来源spring框架)。
 * 如果需要更多的功能,请使用apache-commons-lang的StringUtils
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Keith Donald
 * @author Rob Harrop
 * @author Rick Evans
 * @author Arjen Poutsma
 * @since 16 April 2001
 */
public abstract class StringUtils {

	private static final Logger logger = LoggerFactory.getLogger(StringUtils.class);

	private static final String FOLDER_SEPARATOR = "/";

	private static final String WINDOWS_FOLDER_SEPARATOR = "\\";

	private static final String TOP_PATH = "..";

	private static final String CURRENT_PATH = ".";

	private static final char EXTENSION_SEPARATOR = '.';


	//---------------------------------------------------------------------
	// General convenience methods for working with Strings
	//---------------------------------------------------------------------

	/**
     * 将下划线风格替换为驼峰风格
     */
    public static String underlineToCamelhump(String str) {
    	if(!hasText(str)){
    		return str;
    	}
        Matcher matcher = Pattern.compile("_[a-z]").matcher(str.toLowerCase());
        StringBuilder builder = new StringBuilder(str);
        for (int i = 0; matcher.find(); i++) {
            builder.replace(matcher.start() - i, matcher.end() - i, matcher.group().substring(1).toUpperCase());
        }
        if (Character.isUpperCase(builder.charAt(0))) {
            builder.replace(0, 1, String.valueOf(Character.toLowerCase(builder.charAt(0))));
        }
        return builder.toString();
    }
    
    /**
     * 将驼峰风格替换为下划线风格
     */
    public static String camelhumpToUnderline(String str) {
        final int size;
        final char[] chars;
        final StringBuilder sb = new StringBuilder(
                (size = (chars = str.toCharArray()).length) * 3 / 2 + 1);
        char c;
        for (int i = 0; i < size; i++) {
            c = chars[i];
            if (isUppercaseAlpha(c)) {
                sb.append('_').append(c);
            } else {
                sb.append(toUpperAscii(c));
            }
        }
        return sb.charAt(0) == '_' ? sb.substring(1) : sb.toString();
    }   
    public static boolean isUppercaseAlpha(char c) {
        return (c >= 'A') && (c <= 'Z');
    }
    public static char toUpperAscii(char c) {
        if (isUppercaseAlpha(c)) {
            c -= (char) 0x20;
        }
        return c;
    }


	
	/**
	 * 判断字符串是否为空或null
	 */
	public static boolean isEmpty(Object str) {
		return (str == null || "".equals(str));
	}


	public static boolean isNotEmpty(Object str){
		return !isEmpty(str);
	}

	public static boolean isBlank(String str) {
		return str == null || str.trim().isEmpty();
	}

	public static boolean isNotBlank(String str) {
		return !isBlank(str);
	}

	/**
	 * 判断字符序列是否有内容:
	 * <p><pre class="code">
	 * StringUtils.hasLength(null) = false
	 * StringUtils.hasLength("") = false
	 * StringUtils.hasLength(" ") = true
	 * StringUtils.hasLength("Hello") = true
	 * </pre>
	 */
	public static boolean hasLength(CharSequence str) {
		return (str != null && str.length() > 0);
	}

	/**
	 * 判断字符串是否有内容:
	 */
	public static boolean hasLength(String str) {
		return hasLength((CharSequence) str);
	}

	/**
	 * 判断字符序列是否有非空的内容。
	 * <p><pre class="code">
	 * StringUtils.hasText(null) = false
	 * StringUtils.hasText("") = false
	 * StringUtils.hasText(" ") = false
	 * StringUtils.hasText("12345") = true
	 * StringUtils.hasText(" 12345 ") = true
	 * </pre>
	 */
	public static boolean hasText(CharSequence str) {
		if (!hasLength(str)) {
			return false;
		}
		int strLen = str.length();
		for (int i = 0; i < strLen; i++) {
			if (!Character.isWhitespace(str.charAt(i))) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 判断字符串是否有非空的内容。
	 */
	public static boolean hasText(String str) {
		return hasText((CharSequence) str);
	}

	/**
	 * 字符串中是否有空格
	 */
	public static boolean containsWhitespace(String str) {
		if (!hasLength(str)) {
			return false;
		}
		int strLen = str.length();
		for (int i = 0; i < strLen; i++) {
			if (Character.isWhitespace(str.charAt(i))) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 减去字符串两端的空格
	 */
	public static String trimWhitespace(String str) {
		if (!hasLength(str)) {
			return str;
		}
		StringBuilder sb = new StringBuilder(str);
		while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) {
			sb.deleteCharAt(0);
		}
		while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1))) {
			sb.deleteCharAt(sb.length() - 1);
		}
		return sb.toString();
	}

	/**
	 * 减去字符串两端及中间的所有空格
	 */
	public static String trimAllWhitespace(String str) {
		if (!hasLength(str)) {
			return str;
		}
		int len = str.length();
		StringBuilder sb = new StringBuilder(str.length());
		for (int i = 0; i < len; i++) {
			char c = str.charAt(i);
			if (!Character.isWhitespace(c)) {
				sb.append(c);
			}
		}
		return sb.toString();
	}

	/**
	 * 减去字符串开头的空格
	 */
	public static String trimLeadingWhitespace(String str) {
		if (!hasLength(str)) {
			return str;
		}
		StringBuilder sb = new StringBuilder(str);
		while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) {
			sb.deleteCharAt(0);
		}
		return sb.toString();
	}

	/**
	 * 减去字符串末尾的空格
	 */
	public static String trimTrailingWhitespace(String str) {
		if (!hasLength(str)) {
			return str;
		}
		StringBuilder sb = new StringBuilder(str);
		while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1))) {
			sb.deleteCharAt(sb.length() - 1);
		}
		return sb.toString();
	}

	/**
	 * 从字符串前端中减去指定的char。
	 */
	public static String trimLeadingCharacter(String str, char leadingCharacter) {
		if (!hasLength(str)) {
			return str;
		}
		StringBuilder sb = new StringBuilder(str);
		while (sb.length() > 0 && sb.charAt(0) == leadingCharacter) {
			sb.deleteCharAt(0);
		}
		return sb.toString();
	}

	/**
	 * 从字符串尾端减去指定的char
	 */
	public static String trimTrailingCharacter(String str, char trailingCharacter) {
		if (!hasLength(str)) {
			return str;
		}
		StringBuilder sb = new StringBuilder(str);
		while (sb.length() > 0 && sb.charAt(sb.length() - 1) == trailingCharacter) {
			sb.deleteCharAt(sb.length() - 1);
		}
		return sb.toString();
	}


	/**
	 * 判断字符串是否以prefix开头,忽略大小写
	 */
	public static boolean startsWithIgnoreCase(String str, String prefix) {
		if (str == null || prefix == null) {
			return false;
		}
		if (str.startsWith(prefix)) {
			return true;
		}
		if (str.length() < prefix.length()) {
			return false;
		}
		String lcStr = str.substring(0, prefix.length()).toLowerCase();
		String lcPrefix = prefix.toLowerCase();
		return lcStr.equals(lcPrefix);
	}

	/**
	 * 判断字符串是否以prefix结尾,忽略大小写
	 */
	public static boolean endsWithIgnoreCase(String str, String suffix) {
		if (str == null || suffix == null) {
			return false;
		}
		if (str.endsWith(suffix)) {
			return true;
		}
		if (str.length() < suffix.length()) {
			return false;
		}

		String lcStr = str.substring(str.length() - suffix.length()).toLowerCase();
		String lcSuffix = suffix.toLowerCase();
		return lcStr.equals(lcSuffix);
	}

	/**
	 * 计算sub在str中出现的次数.
	 */
	public static int countOccurrencesOf(String str, String sub) {
		if (str == null || sub == null || str.length() == 0 || sub.length() == 0) {
			return 0;
		}
		int count = 0;
		int pos = 0;
		int idx;
		while ((idx = str.indexOf(sub, pos)) != -1) {
			++count;
			pos = idx + sub.length();
		}
		return count;
	}

	/**
	 * 在inString中,将所有的oldPattern替换为newPattern
	 */
	public static String replace(String inString, String oldPattern, String newPattern) {
		if (!hasLength(inString) || !hasLength(oldPattern) || newPattern == null) {
			return inString;
		}
		StringBuilder sb = new StringBuilder();
		int pos = 0; // our position in the old string
		int index = inString.indexOf(oldPattern);
		// the index of an occurrence we've found, or -1
		int patLen = oldPattern.length();
		while (index >= 0) {
			sb.append(inString.substring(pos, index));
			sb.append(newPattern);
			pos = index + patLen;
			index = inString.indexOf(oldPattern, pos);
		}
		sb.append(inString.substring(pos));
		// remember to append any characters to the right of a match
		return sb.toString();
	}

	/**
	 * 从inString中删除所有的pattern
	 */
	public static String delete(String inString, String pattern) {
		return replace(inString, pattern, "");
	}

	/**
	 * 从inString中删除包含在charsToDelete中的所有char
	 */
	public static String deleteAny(String inString, String charsToDelete) {
		if (!hasLength(inString) || !hasLength(charsToDelete)) {
			return inString;
		}
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < inString.length(); i++) {
			char c = inString.charAt(i);
			if (charsToDelete.indexOf(c) == -1) {
				sb.append(c);
			}
		}
		return sb.toString();
	}


	//---------------------------------------------------------------------
	// Convenience methods for working with formatted Strings
	//---------------------------------------------------------------------

	/**
	 * 为str打上单引号标记
	 */
	public static String quote(String str) {
		return (str != null ? "'" + str + "'" : null);
	}

	/**
	 * obj如果是String类型,则为其打上单引号标记
	 */
	public static Object quoteIfString(Object obj) {
		return (obj instanceof String ? quote((String) obj) : obj);
	}

	/**
	 * 获得最后一个‘.’后的字符串内容。例如:"this.name.is.qualified", 返回  "qualified".
	 */
	public static String unqualify(String qualifiedName) {
		return unqualify(qualifiedName, '.');
	}

	/**
	 * 获得最后一个separator后的字符串内容。
	 */
	public static String unqualify(String qualifiedName, char separator) {
		return qualifiedName.substring(qualifiedName.lastIndexOf(separator) + 1);
	}

	/**
	 * 字符串首字母大写
	 */
	public static String capitalize(String str) {
		return changeFirstCharacterCase(str, true);
	}

	/**
	 *  字符串首字母小写
	 */
	public static String uncapitalize(String str) {
		return changeFirstCharacterCase(str, false);
	}

	private static String changeFirstCharacterCase(String str, boolean capitalize) {
		if (str == null || str.length() == 0) {
			return str;
		}
		StringBuilder sb = new StringBuilder(str.length());
		if (capitalize) {
			sb.append(Character.toUpperCase(str.charAt(0)));
		}
		else {
			sb.append(Character.toLowerCase(str.charAt(0)));
		}
		sb.append(str.substring(1));
		return sb.toString();
	}

	/**
	 * 从path中解析出filename,
	 * 例如: "mypath/myfile.txt" -> "myfile.txt".
	 */
	public static String getFilename(String path) {
		if (path == null) {
			return null;
		}
		int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR);
		return (separatorIndex != -1 ? path.substring(separatorIndex + 1) : path);
	}

	public static byte[] getBytes(String s) {
		try {
			return s.getBytes("UTF8");
		} catch (UnsupportedEncodingException e) {
			logger.error(e.getMessage(), e);
		}
		return null;
	}

	public static String fromBytes(byte[] b) {
		try {
			return new String(b, "UTF8");
		} catch (UnsupportedEncodingException e) {
			logger.error(e.getMessage(), e);
		}
		return null;
	}

	/**
	 * 从path中解析出文件的后缀名,
	 * 例如: "mypath/myfile.txt" -> "txt".
	 */
	public static String getFilenameExtension(String path) {
		if (path == null) {
			return null;
		}
		int extIndex = path.lastIndexOf(EXTENSION_SEPARATOR);
		if (extIndex == -1) {
			return null;
		}
		int folderIndex = path.lastIndexOf(FOLDER_SEPARATOR);
		if (folderIndex > extIndex) {
			return null;
		}
		return path.substring(extIndex + 1);
	}

	/**
	 * 将relativePath加到path的最后一个层级之后,也即最后一级的“/”的后面。
	 */
	public static String applyRelativePath(String path, String relativePath) {
		int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR);
		if (separatorIndex != -1) {
			String newPath = path.substring(0, separatorIndex);
			if (!relativePath.startsWith(FOLDER_SEPARATOR)) {
				newPath += FOLDER_SEPARATOR;
			}
			return newPath + relativePath;
		}
		else {
			return relativePath;
		}
	}

	/**
	 * Normalize the path by suppressing sequences like "path/.." and
	 * inner simple dots.
	 * <p>The result is convenient for path comparison. For other uses,
	 * notice that Windows separators ("\") are replaced by simple slashes.
	 * @param path the original path
	 * @return the normalized path
	 */
	public static String cleanPath(String path) {
		if (path == null) {
			return null;
		}
		String pathToUse = replace(path, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR);

		// Strip prefix from path to analyze, to not treat it as part of the
		// first path element. This is necessary to correctly parse paths like
		// "file:core/../core/io/Resource.class", where the ".." should just
		// strip the first "core" directory while keeping the "file:" prefix.
		int prefixIndex = pathToUse.indexOf(":");
		String prefix = "";
		if (prefixIndex != -1) {
			prefix = pathToUse.substring(0, prefixIndex + 1);
			if (prefix.contains("/")) {
				prefix = "";
			}
			else {
				pathToUse = pathToUse.substring(prefixIndex + 1);
			}
		}
		if (pathToUse.startsWith(FOLDER_SEPARATOR)) {
			prefix = prefix + FOLDER_SEPARATOR;
			pathToUse = pathToUse.substring(1);
		}

		String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR);
		List<String> pathElements = new LinkedList<String>();
		int tops = 0;

		for (int i = pathArray.length - 1; i >= 0; i--) {
			String element = pathArray[i];
			if (CURRENT_PATH.equals(element)) {
				// Points to current directory - drop it.
			}
			else if (TOP_PATH.equals(element)) {
				// Registering top path found.
				tops++;
			}
			else {
				if (tops > 0) {
					// Merging path element with element corresponding to top path.
					tops--;
				}
				else {
					// Normal path element found.
					pathElements.add(0, element);
				}
			}
		}

		// Remaining top paths need to be retained.
		for (int i = 0; i < tops; i++) {
			pathElements.add(0, TOP_PATH);
		}

		return prefix + collectionToDelimitedString(pathElements, FOLDER_SEPARATOR);
	}

	/**
	 * 判断两个path是否相同
	 */
	public static boolean pathEquals(String path1, String path2) {
		return cleanPath(path1).equals(cleanPath(path2));
	}

	//---------------------------------------------------------------------
	// Convenience methods for working with String arrays
	//---------------------------------------------------------------------

	/**
	 * 将str添加到array的末尾
	 */
	public static String[] addStringToArray(String[] array, String str) {
		if (ObjUtil.isEmpty(array)) {
			return new String[] {str};
		}
		String[] newArr = new String[array.length + 1];
		System.arraycopy(array, 0, newArr, 0, array.length);
		newArr[array.length] = str;
		return newArr;
	}

	/**
	 * 合并两个字符串数组
	 */
	public static String[] concatenateStringArrays(String[] array1, String[] array2) {
		if (ObjUtil.isEmpty(array1)) {
			return array2;
		}
		if (ObjUtil.isEmpty(array2)) {
			return array1;
		}
		String[] newArr = new String[array1.length + array2.length];
		System.arraycopy(array1, 0, newArr, 0, array1.length);
		System.arraycopy(array2, 0, newArr, array1.length, array2.length);
		return newArr;
	}

	/**
	 * 合并两个字符串数组,且过滤掉重复的元素
	 */
	public static String[] mergeStringArrays(String[] array1, String[] array2) {
		if (ObjUtil.isEmpty(array1)) {
			return array2;
		}
		if (ObjUtil.isEmpty(array2)) {
			return array1;
		}
		List<String> result = new ArrayList<String>();
		result.addAll(Arrays.asList(array1));
		for (String str : array2) {
			if (!result.contains(str)) {
				result.add(str);
			}
		}
		return toStringArray(result);
	}

	/**
	 * 对字符串数组进行排序
	 */
	public static String[] sortStringArray(String[] array) {
		if (ObjUtil.isEmpty(array)) {
			return new String[0];
		}
		Arrays.sort(array);
		return array;
	}

	/**
	 * 将String类型的集合转为字符串数组
	 */
	public static String[] toStringArray(Collection<String> collection) {
		if (collection == null) {
			return null;
		}
		return collection.toArray(new String[collection.size()]);
	}

	/**
	 * 将字符串类型的Enumeration转换为字符串数组
	 */
	public static String[] toStringArray(Enumeration<String> enumeration) {
		if (enumeration == null) {
			return null;
		}
		List<String> list = Collections.list(enumeration);
		return list.toArray(new String[list.size()]);
	}

	/**
	 * 对array的每个元素进行trim操作
	 */
	public static String[] trimArrayElements(String[] array) {
		if (ObjUtil.isEmpty(array)) {
			return new String[0];
		}
		String[] result = new String[array.length];
		for (int i = 0; i < array.length; i++) {
			String element = array[i];
			result[i] = (element != null ? element.trim() : null);
		}
		return result;
	}

	/**
	 * 使用TreeSet实现对array中重复元素的过滤,并具备排序功能
	 */
	public static String[] removeDuplicateStrings(String[] array) {
		if (ObjUtil.isEmpty(array)) {
			return array;
		}
		Set<String> set = new TreeSet<String>();
		for (String element : array) {
			set.add(element);
		}
		return toStringArray(set);
	}

	/**
	 * 将toSplit从第一次出现delimiter的地方截断,不包含delimiter。
	 */
	public static String[] split(String toSplit, String delimiter) {
		if (!hasLength(toSplit) || !hasLength(delimiter)) {
			return null;
		}
		int offset = toSplit.indexOf(delimiter);
		if (offset < 0) {
			return null;
		}
		String beforeDelimiter = toSplit.substring(0, offset);
		String afterDelimiter = toSplit.substring(offset + delimiter.length());
		return new String[] {beforeDelimiter, afterDelimiter};
	}

	/**
	 * 将字符串数组转换为Properties。其每一个字符串元素通过delimiter进行截断,作为key和value值。
	 */
	public static Properties splitArrayElementsIntoProperties(String[] array, String delimiter) {
		return splitArrayElementsIntoProperties(array, delimiter, null);
	}

	/**
	 * 将字符串数组转换为Properties。其每一个字符串元素通过delimiter进行截断,作为key和value值。
	 * 同时删除掉字符串中所有的包含charsToDelete的字符。
	 */
	public static Properties splitArrayElementsIntoProperties(
			String[] array, String delimiter, String charsToDelete) {

		if (ObjUtil.isEmpty(array)) {
			return null;
		}
		Properties result = new Properties();
		for (String element : array) {
			if (charsToDelete != null) {
				element = deleteAny(element, charsToDelete);
			}
			String[] splittedElement = split(element, delimiter);
			if (splittedElement == null) {
				continue;
			}
			result.setProperty(splittedElement[0].trim(), splittedElement[1].trim());
		}
		return result;
	}

	

	/**
	 * 将通过delimiter分隔的字符串转化为数组
	 */
	public static String[] delimitedListToStringArray(String str, String delimiter) {
		return delimitedListToStringArray(str, delimiter, null);
	}

	/**
	 * Take a String which is a delimited list and convert it to a String array.
	 * <p>A single delimiter can consists of more than one character: It will still
	 * be considered as single delimiter string, rather than as bunch of potential
	 * delimiter characters - in contrast to {@code tokenizeToStringArray}.
	 * @param str the input String
	 * @param delimiter the delimiter between elements (this is a single delimiter,
	 * rather than a bunch individual delimiter characters)
	 * @param charsToDelete a set of characters to delete. Useful for deleting unwanted
	 * line breaks: e.g. "\r\n\f" will delete all new lines and line feeds in a String.
	 * @return an array of the tokens in the list
	 * @see #tokenizeToStringArray
	 */
	public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) {
		if (str == null) {
			return new String[0];
		}
		if (delimiter == null) {
			return new String[] {str};
		}
		List<String> result = new ArrayList<String>();
		if ("".equals(delimiter)) {
			for (int i = 0; i < str.length(); i++) {
				result.add(deleteAny(str.substring(i, i + 1), charsToDelete));
			}
		}
		else {
			int pos = 0;
			int delPos;
			while ((delPos = str.indexOf(delimiter, pos)) != -1) {
				result.add(deleteAny(str.substring(pos, delPos), charsToDelete));
				pos = delPos + delimiter.length();
			}
			if (str.length() > 0 && pos <= str.length()) {
				// Add rest of String, but not in case of empty input.
				result.add(deleteAny(str.substring(pos), charsToDelete));
			}
		}
		return toStringArray(result);
	}

	/**
	 * 将通过逗号分隔的字符串转化为数组。
	 */
	public static String[] commaDelimitedListToStringArray(String str) {
		return delimitedListToStringArray(str, ",");
	}

	/**
	 * 将通过逗号分隔的字符串,转化为set集合。
	 */
	public static Set<String> commaDelimitedListToSet(String str) {
		Set<String> set = new TreeSet<String>();
		String[] tokens = commaDelimitedListToStringArray(str);
		for (String token : tokens) {
			set.add(token);
		}
		return set;
	}

	/**
	 *  将coll转换为字符串, 每个元素用delim分隔,并加上前后缀
	 */
	public static String collectionToDelimitedString(Collection<?> coll, String delim, String prefix, String suffix) {
		if (CollUtil.isEmpty(coll)) {
			return "";
		}
		StringBuilder sb = new StringBuilder();
		Iterator<?> it = coll.iterator();
		while (it.hasNext()) {
			sb.append(prefix).append(it.next()).append(suffix);
			if (it.hasNext()) {
				sb.append(delim);
			}
		}
		return sb.toString();
	}

	/**
	 * 将coll转换为字符串, 每个元素用delim分隔。
	 */
	public static String collectionToDelimitedString(Collection<?> coll, String delim) {
		return collectionToDelimitedString(coll, delim, "", "");
	}

	/**
	 * 将coll转换为字符串, 每个元素用逗号分隔。
	 */
	public static String collectionToCommaDelimitedString(Collection<?> coll) {
		return collectionToDelimitedString(coll, ",");
	}

	/**
	 * 将arr转换为字符串,每个元素用delim分隔。
	 */
	public static String arrayToDelimitedString(Object[] arr, String delim) {
		if (ObjUtil.isEmpty(arr)) {
			return "";
		}
		if (arr.length == 1) {
			return ObjUtil.toString(arr[0]);
		}
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < arr.length; i++) {
			if (i > 0) {
				sb.append(delim);
			}
			sb.append(arr[i]);
		}
		return sb.toString();
	}

	/**
	 * 将arr转换为字符串,每个元素用逗号分隔。
	 */
	public static String arrayToCommaDelimitedString(Object[] arr) {
		return arrayToDelimitedString(arr, ",");
	}


	/**
	 * Convert byte[] to hex string.这里我们可以将byte转换成int,然后利用Integer.toHexString(int)来转换成16进制字符串。
	 * @param src byte[] data
	 * @return hex string
	 */
	public static String bytesToHexString(byte[] src){
		StringBuilder stringBuilder = new StringBuilder("");
		if (src == null || src.length <= 0) {
			return null;
		}
		for (int i = 0; i < src.length; i++) {
			int v = src[i] & 0xFF;
			String hv = Integer.toHexString(v);
			if (hv.length() < 2) {
				stringBuilder.append(0);
			}
			stringBuilder.append(hv);
		}
		return stringBuilder.toString();
	}
	/**
	 * Convert hex string to byte[]
	 * @param hexString the hex string
	 * @return byte[]
	 */
	public static byte[] hexStringToBytes(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return null;
		}
		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d = new byte[length];
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
		}
		return d;
	}

	/**
	 * Convert char to byte
	 * @param c char
	 * @return byte
	 */
	private static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);
	}

	/**
	 * Tokenize the given String into a String array via a StringTokenizer.
	 * Trims tokens and omits empty tokens.
	 * <p>The given delimiters string is supposed to consist of any number of
	 * delimiter characters. Each of those characters can be used to separate
	 * tokens. A delimiter is always a single character; for multi-character
	 * delimiters, consider using <code>delimitedListToStringArray</code>
	 * <p/>
	 * <p>Copied from the Spring Framework while retaining all license, copyright and author information.
	 *
	 * @param str        the String to tokenize
	 * @param delimiters the delimiter characters, assembled as String
	 *                   (each of those characters is individually considered as delimiter).
	 * @return an array of the tokens
	 * @see StringTokenizer
	 * @see String#trim()
	 */
	public static String[] tokenizeToStringArray(String str, String delimiters) {
		return tokenizeToStringArray(str, delimiters, true, true);
	}

	/**
	 * Tokenize the given String into a String array via a StringTokenizer.
	 * <p>The given delimiters string is supposed to consist of any number of
	 * delimiter characters. Each of those characters can be used to separate
	 * tokens. A delimiter is always a single character; for multi-character
	 * delimiters, consider using <code>delimitedListToStringArray</code>
	 * <p/>
	 * <p>Copied from the Spring Framework while retaining all license, copyright and author information.
	 *
	 * @param str               the String to tokenize
	 * @param delimiters        the delimiter characters, assembled as String
	 *                          (each of those characters is individually considered as delimiter)
	 * @param trimTokens        trim the tokens via String's <code>trim</code>
	 * @param ignoreEmptyTokens omit empty tokens from the result array
	 *                          (only applies to tokens that are empty after trimming; StringTokenizer
	 *                          will not consider subsequent delimiters as token in the first place).
	 * @return an array of the tokens (<code>null</code> if the input String
	 *         was <code>null</code>)
	 * @see StringTokenizer
	 * @see String#trim()
	 */
	@SuppressWarnings({"unchecked"})
	public static String[] tokenizeToStringArray(
			String str, String delimiters, boolean trimTokens, boolean ignoreEmptyTokens) {

		if (str == null) {
			return null;
		}
		StringTokenizer st = new StringTokenizer(str, delimiters);
		List tokens = new ArrayList();
		while (st.hasMoreTokens()) {
			String token = st.nextToken();
			if (trimTokens) {
				token = token.trim();
			}
			if (!ignoreEmptyTokens || token.length() > 0) {
				tokens.add(token);
			}
		}
		return toStringArray(tokens);
	}

	/**
	 * 首字母转大写
	 * @param s
	 * @return
	 */
	public static String toUpperCaseFirstOne(String s){
		if(Character.isUpperCase(s.charAt(0))){
			return s;
		} else {
			return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
		}
	}
}

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值