需求
工具类,满足尽可能地自动解析转换各种时间格式的时间字符串为LocalDate,目前支持转换的时间格式有如下,时间字符串至少含有“yyyy”:
- "yyyy"
- "yyyy/MM"
- "yyyy-MM"
- "yyyy/MM/dd"
- "yyyy-MM-dd"
- "yyyy/MM/dd HH:mm"
- "yyyy-MM-dd HH:mm"
- "yyyy-MM-dd HH:mm:ss"
核心全部代码 复制到编译器可以直接运行 更多格式自己改造下
package test.date;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
/**
* @description 全自动适配各种时间格式的字符串 必须包含年
* @Date 2020/8/16 23:10
*/
@Slf4j
public class AutoDateUtils {
public static final String FORMAT_DATETIME = "yyyy-MM-dd HH:mm:ss";
public static final String FORMAT = "yyyy-MM-dd";
public static final String FORMAT2 = "yyyy/MM/dd";
public static final String FORMAT3 = "yyyy-MM-dd HH:mm";
public static final String FORMAT5 = "yyyy/MM/dd HH:mm";
// public static final String FORMAT6 = "yyyyMMdd"; # 暂不支持
// public static final String FORMAT7 = "yyyy年MM月dd日 HH:mm:ss"; # 暂不支持
public static final String FORMAT8 = "yyyy-MM";
// public static final String FORMAT9 = "MM-dd"; # 暂不支持
public static final String FORMAT10 = "yyyy";
public static final String FORMAT11 = "yyyy/MM";
/**
* 自动适配字符串的配置格式
*/
private static final List FORMATTERS = Arrays.asList(FORMAT_DATETIME, FORMAT, FORMAT2, FORMAT3, FORMAT5, FORMAT8, FORMAT10, FORMAT11);
private static Map DAY_FORMATTER_MAPS = preParseLocalDate();
// 预处理
private static Map preParseLocalDate() {
Map regexMap = new HashMap<>(FORMATTERS.size());
// 最全的yyyy-MM-dd HH:mm:ss
for (String format : FORMATTERS) {
String regex = format.replace("yyyy", "\\d{4}").replace("MM", "\\d{2}").replace("dd", "\\d{2}").replace("HH", "\\d{2}").replace("mm", "\\d{2}").replace("ss", "\\d{2}");
regexMap.put(format, regex);
}
return regexMap;
}
/**
* 校验是否为localDate的任意一种格式
*
* @param timeText
* @return
*/
public static boolean judgeLocalDateFormat(String timeText) {
for (String formatter : FORMATTERS) {
String regex = DAY_FORMATTER_MAPS.get(formatter);
if (Pattern.matches(regex, timeText)) {
return true;
}
}
return false;
}
/**
* 自动适配字符串, 转换日期字符串为LocalDate
*
* @param timeText
* @return
*/
public static LocalDate autoParseLocalDate(String timeText) {
for (String formatter : FORMATTERS) {
String regex = DAY_FORMATTER_MAPS.get(formatter);
if (Pattern.matches(regex, timeText)) {
// 特殊考虑
if (formatter.equals(FORMAT10)) {
timeText = timeText.trim() + "-01-01";
formatter = FORMAT;
} else if (formatter.equals(FORMAT11)) {
timeText = timeText.trim() + "/01";
formatter = FORMAT2;
} else if (formatter.equals(FORMAT8)) {
timeText = timeText.trim() + "-01";
formatter = FORMAT;
}
//
return LocalDate.parse(timeText, DateTimeFormatter.ofPattern(formatter));
// 转为 LocalDateTime 格式, 直接反注释下面这一行并且将上面的 特殊考虑重新修订一遍
// return LocalDateTime.parse(timeText, DateTimeFormatter.ofPattern(formatter));
}
}
String msg = timeText + "没有合适的对应的formatter, 请先在DateUtil.DAY_FORMATTER_MAPS 中进行配置";
log.error(msg);
throw new RuntimeException(msg);
}
/**
* 简单匹配转换yyyyMMdd类型的日期字符串,更多格式自己配置
*
* @param timeText
* @return
*/
public static String simpleParseStrOfYYYYMMHH(String timeText) throws Exception {
List regexs = Arrays.asList("\\d{4}[-]\\d{2}[-]\\d{2}", "\\d{4}[/]\\d{2}[/]\\d{2}");
List formats = Arrays.asList("yyyy-MM-dd", "yyyy/MM/dd");
for (int idx = 0; idx < regexs.size(); idx++) {
if (Pattern.matches(regexs.get(idx), timeText)) {
try {
LocalDate parse = LocalDate.parse(timeText, DateTimeFormatter.ofPattern(formats.get(idx)));
return parse.toString();
} catch (Exception e) {
throw new Exception("日期格式错误,请填写正确的日期");
}
}
}
throw new Exception("日期格式异常,建议日期格式类型应该为 \"yyyy-MM-dd\"");
}
@SneakyThrows
public static void main(String[] args) {
System.out.println(DAY_FORMATTER_MAPS);
// 支持8种格式的时间日期字符串转为LocalDate
System.out.println(autoParseLocalDate("2020-06-09 16:34:14"));
System.out.println(autoParseLocalDate("2020-06-09 16:34"));
System.out.println(autoParseLocalDate("2020/06/09 16:34"));
System.out.println(autoParseLocalDate("2020/06/09"));
System.out.println(autoParseLocalDate("2020-06-09"));
System.out.println(autoParseLocalDate("2020-06"));
System.out.println(autoParseLocalDate("2020/06"));
System.out.println(autoParseLocalDate("2020"));
// 刚开始写的简单版本,后来发现还可以再扩展就有了上面的autoParseLocalDate
System.out.println("==================测试出来的彩蛋,自动纠正了,02-31不会抛异常");
System.out.println(simpleParseStrOfYYYYMMHH("2019/09/30"));
System.out.println(simpleParseStrOfYYYYMMHH("2019-02-29"));
System.out.println(simpleParseStrOfYYYYMMHH("2019-02-30"));
System.out.println(simpleParseStrOfYYYYMMHH("2019-02-31"));
System.out.println(simpleParseStrOfYYYYMMHH("2019-02-20"));
}
}
运行上面的main方法测试和输出
支持格式
{yyyy-MM=\d{4}-\d{2}, yyyy/MM=\d{4}/\d{2}, yyyy/MM/dd=\d{4}/\d{2}/\d{2}, yyyy/MM/dd HH:mm=\d{4}/\d{2}/\d{2} \d{2}:\d{2}, yyyy-MM-dd HH:mm:ss=\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}, yyyy=\d{4}, yyyy-MM-dd HH:mm=\d{4}-\d{2}-\d{2} \d{2}:\d{2}, yyyy-MM-dd=\d{4}-\d{2}-\d{2}}
打印结果:
2020-06-09
2020-06-09
2020-06-09
2020-06-09
2020-06-09
2020-06-01
2020-06-01
2020-01-01
2019-09-30
2019-02-28
2019-02-28
2019-02-28
2019-02-20