详见代码注释。
public static final String YYYY_MM_DD = "yyyy-MM-dd";
public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd hh:mm:ss";
public static final String YYYY_MM_DD_HH_MM_SS_SSS = "yyyy-MM-dd HH:mm:ss.SSS";
/**
* 归一化日期字符串。可自动判断处理到毫秒。功能:
* <ul>
* <li>可处理10、13位的时间戳</li>
* <li>可处理阿拉伯数字顺序表示的年、月、日、小时、分钟、秒、毫秒</li>
* <li>不能处理时区表示法,以及含英文月、星期字符格式。可含非字母分隔符号,如:: / - 空格 制表等</li>
* <li>各部分数值必须满足其自身要求,如月:1-12等,年月日不满足时返回null,
* 小时不满足时返回年月日,分钟、秒、毫秒不满足时,该值部分及后续部分自动设为0</li>
* </ul>
* 要求:
* <ul>
* <li>日期或时间各部分之间可以使用任意非字母分隔符(数量不限)</li>
* <li>日期或时间各部分之间无分隔时必须满足各部分的位数要求:年为四位,其他为两位,不足时要前缀0</li>
* <li>输入字符串中必须含年月日,否则返回null!</li>
* </ul>
* 特殊示例:
* <ul>
* <li>"2020/- 1 //4 20 30 15 120"处理为"2020-01-04 20:30:15.120"</li>
* <li>"2020/- 1 //4 20 "处理为"2020-01-04 20:00:00"</li>
* <li>"2020/- 1 //4 "处理为"2020-01-04"</li>
* <li>"20200104 "处理为"2020-01-04"</li>
* <li>"20200104 12:24:36 350 "处理为"2020-01-04 12:24:36.320"</li>
* <li>"2020/ 1" 返回null;</li>
* </ul>
*
* @param dateString 日期字符串
* @return 返回null、yyyy-MM-dd、yyyy-MM-dd HH:mm:ss、yyyy-MM-dd HH:mm:ss.SSS
* @date 2023/12/20 14:09
* @author MuYi
*/
public static String normalizedDateStr(final String dateString) {
if (StringUtils.isBlank(dateString)) {
return null;
}
if (dateString.matches(".*[a-zA-Z].*")) return null;
String dateStr = dateString.trim();
int len = dateStr.length();
//时间戳
if (len == 10 || len == 13) {
try {
long time;
if (dateStr.matches("^[1-9][1-12][1-31]$")) {
time = Long.parseLong(dateStr) * 1000L;
return new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS).format(new Date(time));
} else if (dateStr.matches("^[1-9][0-9]{12}$")) {
time = Long.parseLong(dateStr);
return new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS_SSS).format(new Date(time));
}
} catch (Exception e) {
return null;
}
}
String ymd = "", hmss = "";
//年月日部分
//匹配:yyyyMMdd
String regex = "([1-3]{1}[0-9]{3})(\\d{2})(\\d{2})";
ymd = getYMD(regex, dateStr);
if (ymd == null) {
//匹配:yyyy分隔符M分隔符d
regex = "([1-3]{1}[0-9]{3})(?:\\D+)(\\d{1,2})(?:\\D+)(\\d{1,2})";
ymd = getYMD(regex, dateStr);
if (ymd == null) return null;
}
//移除年月日部分
String hmsStr = dateStr.replaceAll(regex, "");
//匹配:h分隔符m分隔符s分隔符S
regex = "(?:\\D+)(\\d{1,2})(?:\\D+)?(\\d{1,2})?(?:\\D+)?(\\d{1,2})?(?:\\D+)?(\\d{1,3})?";
hmss = getHMSS(regex, hmsStr);
if (hmss == null) {
//匹配:hhmmss分隔符S
regex = "(?:\\D+)(\\d{2})(\\d{2})?(\\d{2})?(?:\\D+)?(\\d{1,3})?";
hmss = getHMSS(regex, hmsStr);
}
return hmss == null ? ymd : ymd + " " + hmss;
}
private static String getYMD(String regex, String dateString) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(dateString);
if (matcher.find()) {
String year = matcher.group(1);
String month = matcher.group(2);
String day = matcher.group(3);
if (year != null && month != null && day != null) {
int m = Integer.parseInt(month);
int d = Integer.parseInt(day);
if (m > 0 && m < 13 && d > 0 && d < 32)
return year + "-"
+ (m < 10 ? "0" + m : month)
+ "-"
+ (d < 10 ? "0" + d: day);
}
}
return null;
}
private static String getHMSS(String regex, String dateString) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(dateString);
String hms = null;
if (matcher.find()) {
String hour = matcher.group(1);
String minute = matcher.group(2);
String second = matcher.group(3);
String microsecond = matcher.group(4);
int h = Integer.parseInt(hour);
if (h < 0 || h > 24) return null;
int m = minute != null ? Integer.parseInt(minute) : -1;
if (m < 0 || m > 60) return String.format("%02d:00:00", h);
int s = second != null ? Integer.parseInt(second) : -1;
if (s < 0 || s > 60) return String.format("%02d:%02d:00", h, m);
int ss = microsecond != null ? Integer.parseInt(microsecond) : -1;
if (ss < 0 || ss > 999) return String.format("%02d:%02d:%02d", h, m, s);
else return String.format("%02d:%02d:%02d.%03d", h, m, s, ss);
} else return null;
}