jdk(java)8 日期格式化工具-使用枚举处理
Posted privateobject
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jdk(java)8 日期格式化工具-使用枚举处理相关的知识,希望对你有一定的参考价值。
jdk(java)8 日期格式化工具-使用枚举处理
在项目开发中,日期格式化是高频的工具类。大部分 工具类 都是 class ,格式化 字符串 直接传入到 方法内,确定是 每次都要 手写 格式化字符串,或者使用 封装好的方法 内嵌格式字符串。
后来想了想,觉得使用枚举 定义日期格式化处理,感觉不用手写格式化字符串,并且可以根据需要集中增加 格式化 字符串
暂不清楚,为什么这种方式比较少。可能有我想不到的问题吧ヾ(゚∀゚ゞ)
参考链接
Java8的DateTimeFormatter bug
jdk8官方日期格式化bug
JAVA 最简单获取系统时间代码 LocalDateTime( 以yyyy-MM-dd HH:mm:ss.SSS格式显示)
【java】正则判断是否日期(年月日)字符串
Java 正则表达式
工具类代码-示例
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Date;
public class DateUtil{
/** java8之前日期格式化 */
public static String formatOld(Date date, String format) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
return simpleDateFormat.format(date);
}
/** java8日期格式化 */
public static String formatNew(Date date, String format) {
DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendPattern(format).toFormatter();
return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).format(dtf);
}
}
枚举日期格式化-代码
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.Date;
import java.util.regex.Pattern;
/**
* 日期格式化字符串 工具枚举
*
* @author z.y
* @version v1.0
* @date 2021/11/9
*/
public enum DateFormatEnum {
/**格式化字符串:yyyyMMddHHmmssSSS*/
y_M_d_H_m_s_S("yyyyMMddHHmmssSSS","\\\\d{17}","yyyyMMddHHmmss"),
/**格式化字符串:yyyy-MM-dd HH:mm:ss.SSS*/
y_M_d_H_m_s_S_1("yyyy-MM-dd HH:mm:ss.SSS","\\\\d{4}\\\\-\\\\d{2}\\\\-\\\\d{2}\\\\s{1}\\\\d{2}[:]\\\\d{2}[:]\\\\d{2}\\\\.\\\\d{3}"),
/**格式化字符串:yyyy/MM/dd HH:mm:ss.SSS*/
y_M_d_H_m_s_S_2("yyyy/MM/dd HH:mm:ss.SSS","\\\\d{4}/\\\\d{2}/\\\\d{2}\\\\s{1}\\\\d{2}[:]\\\\d{2}[:]\\\\d{2}\\\\.\\\\d{3}"),
/**格式化字符串:yyyyMMddHHmmss*/
y_M_d_H_m_s("yyyyMMddHHmmss","\\\\d{14}"),
/**格式化字符串:yyyy-MM-dd HH:mm:ss*/
y_M_d_H_m_s_1("yyyy-MM-dd HH:mm:ss","\\\\d{4}\\\\-\\\\d{2}\\\\-\\\\d{2}\\\\s{1}\\\\d{2}[:]\\\\d{2}[:]\\\\d{2}"),
/**格式化字符串:yyyy/MM/dd HH:mm:ss*/
y_M_d_H_m_s_2("yyyy/MM/dd HH:mm:ss","\\\\d{4}/\\\\d{2}/\\\\d{2}\\\\s{1}\\\\d{2}[:]\\\\d{2}[:]\\\\d{2}"),
/**格式化字符串:yyyy-MM-dd 00:00:00*/
y_M_d_0_0_0("yyyy-MM-dd 00:00:00","\\\\d{4}\\\\-\\\\d{2}\\\\-\\\\d{2}\\\\s{1}\\\\d{2}[:]\\\\d{2}[:]\\\\d{2}","yyyy-MM-dd HH:mm:ss"),
/**格式化字符串:yyyy-MM-01 00:00:00*/
y_M_1_0_0_0("yyyy-MM-01 00:00:00","\\\\d{4}\\\\-\\\\d{2}\\\\-\\\\d{2}\\\\s{1}\\\\d{2}[:]\\\\d{2}[:]\\\\d{2}","yyyy-MM-dd HH:mm:ss"),
/**格式化字符串:yyyy-MM-dd 23:59:59*/
y_M_d_23_59_59("yyyy-MM-01 23:59:59","\\\\d{4}\\\\-\\\\d{2}\\\\-\\\\d{2}\\\\s{1}\\\\d{2}[:]\\\\d{2}[:]\\\\d{2}","yyyy-MM-dd HH:mm:ss"),
/**格式化字符串:yyyyMMdd*/
y_M_d("yyyyMMdd", "\\\\d{8}"),
/**格式化字符串:yyyy-MM-dd*/
y_M_d_1("yyyy-MM-dd","\\\\d{4}\\\\-\\\\d{2}\\\\-\\\\d{2}"),
/**格式化字符串:yyyy/MM/dd*/
y_M_d_2("yyyy/MM/dd", "\\\\d{4}/\\\\d{2}/\\\\d{2}"),
/**格式化字符串:yyyyMM*/
y_M("yyyyMM","\\\\d{6}"),
/**格式化字符串:yyyy-MM*/
y_M_1("yyyy-MM","\\\\d{4}\\\\-\\\\d{2}"),
/**格式化字符串:yyyy/MM*/
y_M_2("yyyy/MM","\\\\d{4}/\\\\d{2}"),
;
/** 日期 格式化 字符串 */
private final String format;
private final DateTimeFormatter formatter;
/** 字符串 格式化 日期 */
private final String parse;
private final DateTimeFormatter parseFormatter;
/** 字符串 日期正则 */
private final String regular;
private final Pattern pattern;
DateFormatEnum(String format, String regular, String parse){
this.format = format;
this.regular = regular;
this.parse = parse;
this.formatter = createFormatter(format,false);
this.parseFormatter = createFormatter(parse,true);
this.pattern = Pattern.compile(regular);
}
DateFormatEnum(String format, String regular){
this(format,regular,format);
}
public String getFormat() { return format; }
public String getParse() { return parse; }
public String getRegular() { return regular; }
//************ 工具方法
/** 正在验证 日期字符串 */
public boolean regular(String dateVal){
return null != dateVal && pattern.matcher(dateVal).matches();
}
/** 当前日期 格式化 字符串 */
public String format(){ return format(new Date()); }
/** 日期 格式化 字符串 */
public String format(Date date){
return formatOfDef(date,null);
}
public String formatOfEmpty(Date date){
return formatOfDef(date,"");
}
/** 日期 格式化 字符串 */
public String formatOfDef(Date date,String defVal){
if ( null == date ){ return defVal; }
return formatLocalDateTime(ofInstantDefault(date));
}
public String formatLocalDateTime(LocalDateTime localDateTime){
if ( null == localDateTime ){ return null; }
return localDateTime.format(this.formatter);
}
/** 字符串 格式化 日期 */
public Date parse(String dateVal){
return parseOfDef(dateVal,null);
}
public Date parseOfNow(String dateVal){
return parseOfDef(dateVal,new Date());
}
public Date parseOfDef(String dateVal,Date def){
if (null == dateVal || dateVal.trim().length() <= 0){ return def;}
return Date.from(parseLocalDateTime(dateVal).atZone(ZoneId.systemDefault()).toInstant());
}
/** 字符串 格式化 jdk8 日期 */
public LocalDateTime parseLocalDateTime(String dateVal){
if ( null == dateVal || "".equals(dateVal.trim()) ){ return null;}
return LocalDateTime.parse(dateVal, this.parseFormatter);
}
//************ 私有方法
/** Date 转 LocalDateTime,系统默认时区 */
private LocalDateTime ofInstantDefault(Date date){
return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}
/** 获取日期格式化对象 */
private DateTimeFormatter createFormatter(String pattern,boolean isParse){
DateTimeFormatterBuilder fb = new DateTimeFormatterBuilder().appendPattern(pattern);
if ( ! isParse ){ return fb.toFormatter(); }
if (this.format.endsWith("ssSSS")){
// 规避 jdk 8 字符串含 毫秒SSS 转 日期 报错 问题
// 日期 转字符 yyyyMMdd HHmmssSSS; 字符转 日期 yyyyMMdd HHmmss
fb.appendValue(ChronoField.MILLI_OF_SECOND,3);
}else if (!this.format.endsWith("SSS")){
// 和 格式化 SSS 冲突,有就报错
fb.parseDefaulting(ChronoField.MILLI_OF_SECOND, 0);
}
return fb.parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
.parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
.toFormatter();
}
}
测试代码
import java.util.Date;
/**
* TestMain 说明:
*
* @author z.y
* @version v1.0
* @date 2021/11/10
*/
public class Test1Main {
public static void main(String[] args) {
System.out.println("1:"+ DateFormatEnum.y_M_d_H_m_s_S.format());
System.out.println("2:"+ DateFormatEnum.y_M_d_H_m_s_S_1.formatOfEmpty(new Date()));
System.out.println("3:"+ DateFormatEnum.y_M_d_H_m_s_S_1.format(null));
System.out.println("4:"+ DateFormatEnum.y_M_d_H_m_s_S_1.formatOfEmpty(null));
System.out.println("5:"+ DateFormatEnum.y_M_d_H_m_s_S_1.parse("2021-11-10 10:17:33.830"));
System.out.println("7:"+ DateFormat1Enum.y_M_d_H_m_s_S_1.formatOfEmpty(DateFormatEnum.y_M_d_H_m_s_S_1.parse("")));
System.out.println("8:"+ DateFormat1Enum.y_M_d_H_m_s_S_1.formatOfEmpty(DateFormatEnum.y_M_d_H_m_s_S_1.parseOfNow("")));
System.out.println(">>>>>测试>>>>>文字转日期再转文字");
test(DateFormatEnum.y_M_d_H_m_s_S,"20211101101733830");
test(DateFormatEnum.y_M_d_H_m_s_S_1,"2021-11-02 10:17:33.830");
test(DateFormatEnum.y_M_d_H_m_s_S_2,"2021/11/03 10:17:33.830");
test(DateFormatEnum.y_M_d_H_m_s,"20211104101733");
test(DateFormatEnum.y_M_d_H_m_s_1,"2021-11-05 10:17:33");
test(DateFormatEnum.y_M_d_H_m_s_2,"2021/11/06 10:17:33");
test(DateFormatEnum.y_M_d_0_0_0,"2021-11-07 10:17:33");
test(DateFormatEnum.y_M_1_0_0_0,"2021-11-08 10:17:33");
test(DateFormatEnum.y_M_d_23_59_59,"2021-11-09 10:17:33");
test(DateFormatEnum.y_M_d,"20211110");
test(DateFormatEnum.y_M_d_1,"2021-11-11");
test(DateFormatEnum.y_M_d_2,"2021/11/12");
System.out.println("min:"+ DateFormatEnum.y_M_d_H_m_s_S_1.formatOfEmpty(new Date(0)));
System.out.println("max:"+ DateFormatEnum.y_M_d_H_m_s_S_1.formatOfEmpty(new Date(Long.MAX_VALUE)));
}
public static void test(DateFormatEnum format, String val){
System.out.print(val + ">>: reg[" + format.regular(val) + "], parse[" + format.getParse() + "], format[" + format.getFormat() );
System.out.println("] >>:" + format.formatOfEmpty(format.parseOfNow(val)));
}
}
输出日志
1:20211110150540926
2:2021-11-10 15:05:40.956
3:null
4:
5:Wed Nov 10 10:17:33 CST 2021
7:
8:2021-11-10 15:05:40.969
>>>>>测试>>>>>文字转日期再转文字
20211101101733830>>: reg[true], parse[yyyyMMddHHmmss], format[yyyyMMddHHmmssSSS] >>:20211101101733830
2021-11-02 10:17:33.830>>: reg[true], parse[yyyy-MM-dd HH:mm:ss.SSS], format[yyyy-MM-dd HH:mm:ss.SSS] >>:2021-11-02 10:17:33.830
2021/11/03 10:17:33.830>>: reg[true], parse[yyyy/MM/dd HH:mm:ss.SSS], format[yyyy/MM/dd HH:mm:ss.SSS] >>:2021/11/03 10:17:33.830
20211104101733>>: reg[true], parse[yyyyMMddHHmmss], format[yyyyMMddHHmmss] >>:20211104101733
2021-11-05 10:17:33>>: reg[true], parse[yyyy-MM-dd HH:mm:ss], format[yyyy-MM-dd HH:mm:ss] >>:2021-11-05 10:17:33
2021/11/06 10:17:33>>: reg[true], parse[yyyy/MM/dd HH:mm:ss], format[yyyy/MM/dd HH:mm:ss] >>:2021/11/06 10:17:33
2021-11-07 10:17:33>>: reg[true], parse[yyyy-MM-dd HH:mm:ss], format[yyyy-MM-dd 00:00:00] >>:2021-11-07 00:00:00
2021-11-08 10:17:33>>: reg[true], parse[yyyy-MM-dd HH:mm:ss], format[yyyy-MM-01 00:00:00] >>:2021-11-01 00:00:00
2021-11-09 10:17:33>>: reg[true], parse[yyyy-MM-dd HH:mm:ss], format[yyyy-MM-01 23:59:59] >>:2021-11-01 23:59:59
20211110>>: reg[true], parse[yyyyMMdd], format[yyyyMMdd] >>:20211110
2021-11-11>>: reg[true], parse[yyyy-MM-dd], format[yyyy-MM-dd] >>:2021-11-11
2021/11/12>>: reg[true], parse[yyyy/MM/dd], format[yyyy/MM/dd] >>:2021/11/12
min:1970-01-01 08:00:00.000
max:+292278994-08-17 15:12:55.807
截图
关于正则验证
示例代码的正则比较简单,可以根据自己的情况定义严格的正则表达式。
日期 正则 有很多相似的片段,可以定义 不同的片段,在根据需要组装,毕竟一个字符串编写正则太长了。
这是参考代码
/** 正则片段 */
private interface Gp {
/** 格式化字符 SSS 毫秒 */ String FORMAT_SSS = "SSS";
/** 格式化字符 ssSSS 秒 毫秒 */ String FORMAT_SS_SSS = "ssSSS";
/** 小括号 ( */ String S = "(";
/** 小括号 ) */ String E = ")";
/** 正则片段 | */ String R0 = "|";
/** 分割符号 (\\\\-) */ String SP1 = "(\\\\-)";
/** 分割符号 (/) */ String SP2 = "(/)";
/** 分割符号 (\\\\.) */ String SP3 = "(\\\\.)";
/** 分割符号 (:) */ String SP4 = "(:)";
/** 正则片段 4位数字 */ String I_4NUM = "([0-9]{4})";
/** 正则片段 数字 1970-2999 */ String I_1970_2999 = "(19[7-9][0-9]|2[0-9]{3})";
/** 正则片段 数字 01-12 */ String I_01_12 = "(0[1-9]|1[012])";
/** 正则片段 数字 00-23 */ String I_00_23 = "([01][0-9]|2[0-3])";
/** 正则片段 数字 00-59 */ String I_00_59 = "([0-5][0-9])";
/** 正则片段 数字 000-999 */ String I_000_999 = "([0-9]{3})";
/** 正则片段 数字 01-31 */ String I_01_31 = "(0[1-9]|[12][0-9]|3[01])";
/** 正则片段 数字 01-30 */ String I_01_30 = "(0[1-9]|[12][0-9]|3[0])";
/** 正则片段 数字 01-30 */ String I_01_29 = "(0[1-9]|[12][0-9])";
/** 正则片段 数字 01 03 05 07 08 10 12 */ String I_0_135 = "(0[13578]|(10|12))";
/** 正则片段 数字 04 06 09 11 */ String I_0_469 = "(0[469]|11)";
/** 正则片段 数字 02 */ String I_02 = "02";
String YYYY_MM_DD = I_1970_2999 + S + S+I_0_135+I_01_31+E + R0 + S+I_02+I_01_29+E + R0 + java基础第八篇之jdk1.5jdk1.7jdk1.8新特性