代码说明
-
比较泛用的日期反序列化 (非正则,直接循环处理字符串)
-
看到了公司代码里面用多种DateTimeFormatter涵盖一些格式然后for循环去序列化的情况,效率不高
-
实现方法很简单,一般的日期之间 , 年月日用 - 或者 / 当做分隔符 , 然后时间就用 : 或者 - ,但是无论什么分隔符,不能是数字就对了 , 那么就简单提取出一个字符串内的若干数字 , 这些数字就是年月日时分秒 .
-
但是如果有些年月日粘在一起的情况 , 或者时分秒粘在一起的情况 , 那么把他们 %100 , 然后 / 100 , 分隔出来就行.
-
因为日期这个数组最多也就7个数字 , 也就是年月日时分秒,和后面的ns , 那么7位的数组就够了 , 这里处理年月日或时分秒粘连时 , 直接复制timeArr这个原数组 , 也就是 timeArrCopy 当做辅助数组 .
-
因为年月日粘连在一起时 , 如果用 %100 , 先出来的数字 , 一般都是日或者秒, 是右侧的值 , 一般来说,如果有年月日粘连 , 那么timeArr右侧肯定有空缺的,timeArrCopy 肯定也是 , 所以就把timeArrCopy末尾当做暂存区 , copyTail当做下标从末尾往左移 .
-
然后分割出来的数据 , 从timeArrCopy复制到timeArr就行
-
System.arraycopy(timeArrCopy, copyTail, timeArr, j, partNum - copyTail);
-
这里下标j就是拆分后这个位置的新下标 , j-i可以判断出拆出了几个新数字 , 再把原数组这个数字后面的部分拷回来
-
然后保存的原有的那些数据 , 附加到新的下标j
-
System.arraycopy(timeArrCopy, in + 1, timeArr, j, partNum - j);
-
实际数据说明 , 例如 [20241030,14,3,31,0,0,0] , timeArrCopy末尾先 [20241030,14,3,31,0,10,30]
-
然后拷贝回去分隔出来的部分 [2024,10,30,31,0,0,0] , 再把原来第一位数后面的部分 [2024,10,30,14,3,31,0]
-
关于ms的处理比较糙 , 因为localdatetime只接受ns的参数,所以需要ns不能和s粘连在一起,需要用.隔开
-
或者直接不加ns(也就是字符串只有6个数字) , 因为用到的情况确实比较少
-
然后这里只截取了三位, 也就是说只接受精确到ms值 , 这样一般够用 , 也比较统一,输出的字符串也是整齐的,因为LocalDateTime.now().toString() , 这东西偶尔长度不一致,因为他会裁剪掉末尾的0
代码
import java.time.LocalDate;
import java.time.LocalDateTime;
public class GenericDateFormat {
public static void main(String[] args) {
正常转日期();
// 一些异常的校验();
}
private static void 一些异常的校验() {
System.out.println(" ============================================================================ ");
System.out.println(" ============================ str2localDateTime_withMilliOrNano =================================== ");
System.out.println(" ============================================================================ ");
System.out.println(str2localDateTime_withMilliOrNano("2021/1/02 23:04:23"));
System.out.println(str2localDateTime_withMilliOrNano("2021/13/02 2:04:23"));
System.out.println(str2localDateTime_withMilliOrNano("2022/1-02 3:88:23"));
System.out.println(str2localDateTime_withMilliOrNano("2023/01/02 29:04:23"));
System.out.println(" ============================================================================ ");
System.out.println(" ============================ 转localdate的(从 str2localDateTime_withMilliOrNano 结果裁剪) =================================== ");
System.out.println(" ============================================================================ ");
System.out.println(str2localDate("2021/1/66"));
System.out.println(str2localDate("2022/99-02"));
}
private static void 正常转日期() {
System.out.println(" ============================================================================ ");
System.out.println(" ============================ str2localDateTime_withMilliOrNano =================================== ");
System.out.println(" ============================================================================ ");
System.out.println(str2localDateTime_withMilliOrNano("2021/1/02 2:04:23"));
System.out.println(str2localDateTime_withMilliOrNano("2022/1-02 3:04:23"));
System.out.println(str2localDateTime_withMilliOrNano("2023/01/02 4:04:23"));
System.out.println(str2localDateTime_withMilliOrNano("2024-01-02 05:04:23"));
System.out.println(str2localDateTime_withMilliOrNano("2025-01-02 06:4:23"));
System.out.println(str2localDateTime_withMilliOrNano("2030-01-02 06:4:23.125"));
System.out.println(str2localDateTime_withMilliOrNano("2031-01-02 06:4:23.8948956"));
System.out.println(str2localDateTime_withMilliOrNano("2032-01-02 06:4:23.52"));
System.out.println(str2localDateTime_withMilliOrNano("2033-1-02 06:4:23.52"));
System.out.println(str2localDateTime_withMilliOrNano("2034-01-2 06:4:23.52"));
System.out.println(str2localDateTime_withMilliOrNano("2035-1-2 06:4:23.52"));
System.out.println(str2localDateTime_withMilliOrNano("20350102 030411.52"));
System.out.println(str2localDateTime_withMilliOrNano("20360304 060822.886"));
System.out.println(str2localDateTime_withMilliOrNano("20370304 06/08/22.886"));
System.out.println(str2localDateTime_withMilliOrNano("20380304 06/08/22.887546"));
System.out.println(" ============================================================================ ");
System.out.println(" ============================ 转localdate的(从 str2localDateTime_withMilliOrNano 结果裁剪) =================================== ");
System.out.println(" ============================================================================ ");
System.out.println(str2localDate("2021/1/02"));
System.out.println(str2localDate("2022/1-02"));
System.out.println(str2localDate("2023/01/02"));
System.out.println(str2localDate("2024-01-02"));
System.out.println(str2localDate("2033-1-02"));
System.out.println(str2localDate("2034-01-2"));
System.out.println(str2localDate("2035-1-2"));
System.out.println(str2localDate("20350102"));
System.out.println(str2localDate("20360304"));
}
static int[] maxTime = new int[]{9999, 12, 31, 23, 59, 59, 999};
public static LocalDate str2localDate(String time) {
return str2localDateTime_withMilliOrNano(time).toLocalDate();
}
/**
* 泛用版字符串转日期
* 输入得是正常的日期,不要是345575745646645这种莫名其妙的 , 然后ms记得得加上.不然会有误差 .
* str2localdatetime 忽略 Milli 或 Nano
* 鉴于一般的时间也都只精确到ms , 那么都以ms接收 , 但是 LocalDateTime.of 只支持ns , 那么再乘以 1,000,000
*
* @param time 时间
* @return {@link LocalDateTime }
*/
public static LocalDateTime str2localDateTime_withMilliOrNano(String time) {
int partNum = 7;
int[] timeArr = new int[partNum];
int firstPoint = time.indexOf('.');
int pointIndex = time.lastIndexOf('.');
if (firstPoint != pointIndex) {
throw new RuntimeException(" [.] 只能当做ms部分的分隔符 ");
}
// . 一般不能在左侧的 , 尽量别传错误数据吧
if (pointIndex > 0) {
int numberCount = time.length() - pointIndex - 1;
int countDiff = 3 - numberCount;
if (countDiff > 0) {
time = time + "0".repeat(countDiff);
} else if (countDiff < 0) {
// 之前考虑要不要做个四舍五入 , 但是 999,999,999 这种情况又很麻烦,要是进位到秒就麻烦了,所以还是直接截取掉
time = time.substring(0, time.length() + countDiff);
}
}
int arrIndexOrLen = 0;
int strIndex = 0;
int length = time.length();
while (arrIndexOrLen < partNum && strIndex < length) {
while (strIndex < length && (time.charAt(strIndex) < '0' || time.charAt(strIndex) > '9')) {
strIndex++;
}
int num = 0;
while (strIndex < length && time.charAt(strIndex) >= '0' && time.charAt(strIndex) <= '9') {
num *= 10;
num += time.charAt(strIndex) - '0';
if (num > maxTime[arrIndexOrLen]) {
num /= 10;
break;
}
strIndex++;
}
timeArr[arrIndexOrLen++] = num;
}
// 暂时不接受秒和ms粘连的情况 , 如果数据是分隔符形式比较标准的 , 为了效率 , 免得创建数组和走if判断了,直接返回
return LocalDateTime.of(timeArr[0], timeArr[1], timeArr[2], timeArr[3], timeArr[4], timeArr[5], timeArr[6] * 1000_000);
}
}