日期工具类
Posted 野生java研究僧
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日期工具类相关的知识,希望对你有一定的参考价值。
日期工具类
概述
在日常的开发中,我们难免会对日期格式化,对日期进行计算,对日期进行校验,为了避免重复写这些琐碎的逻辑,我这里封装了一个日期工具类,方便以后使用,直接复制代码到项目中即可使用。
日期工具类代码:
import org.apache.commons.lang3.StringUtils;
import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.ZoneId;
import java.util.*;
import java.util.regex.Pattern;
/**
* 常用日期工具类
*
* @author compass
* @date 2022/10/21 14:20
* @since 1.0.0
**/
public class DateTools
public final static String DEFAULT_TIME_FORMAT = "HH:mm:ss";
public final static String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public final static String DEFAULT_DATE_FORMAT_SHORT = "yyMMdd";
public final static String DEFAULT_YEAR_MODTH_SHORT = "yyyyMM";
public final static String DEFAULT_TIME_FORMAT_SHORT = "HHmmss";
public final static String DEFAULT_DATETIME_FORMAT_SHORT = "yyMMddHHmmss";
public final static String DEFAULT_DATE_FORMAT_ALLSHORT = "yyyyMMdd";
public static final String SIMPLE_DATE_STR = "yyyy-MM-dd";
public static final String FULL_DATE_STR = "yyyy-MM-dd HH:mm:ss";
public static final String ALL_FULL_DATE_STR = "yyyy-MM-dd HH:mm:ss.S";
public static final String PART_DATE_STR = "yyyy-MM-dd HH:mm";
public static final String DATEFORMAT_Y2H = "yyyy-MM-dd HH";
public static final String SIMPLE_RULE_DATE_STR = "yyyy/MM/dd";
public static final String FULL_RULE_DATE_STR = "yyyy/MM/dd HH:mm:ss";
public static final String PART_RULE_DATE_STR = "yyyy/MM/dd HH:mm";
public static final String SMALL_PART_RULE_DATE_STR = "HH:mm";
public static final String DATE_FORMAT_YYYYMMDD = "yyyyMMdd";
public static final String DATE_FORMAT_YYYYMMDDHH = "yyyyMMddHH";
public static final String DATE_FORMAT_YYYYMMDDHHMM = "yyyyMMddHHmm";
public static final String DATE_FORMAT_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
public static final String SIMPLE_POINT_DATE_STR = "yyyy.MM.dd";
public static final String FULL_POINT_DATE_STR = "yyyy.MM.dd HH:mm:ss";
/**
* 锁对象
*/
private static final Object lockObj = new Object();
/**
* 存放不同格式的线程安全的SimpleDateFormat
*/
private static Map<String, ThreadLocal<SimpleDateFormat>> sdfMap = new HashMap<>();
public enum DateType
YEAR("YEAR", 1),
MONTH("MONTH", 2),
DAY("DAY", 3),
HOUR("HOUR", 4),
MINUTE("MINUTE", 5),
SECOND("SECOND", 6);
private String name;
private int value;
DateType(String name, int value)
this.value = value;
this.name = name;
public int getValue()
return value;
public String getName()
return name;
/**
* 返回一个ThreadLocal的sdf,每个线程只会new一次sdf
*
* @param pattern
* @return
*/
private static SimpleDateFormat getSdf(final String pattern)
ThreadLocal<SimpleDateFormat> tl = sdfMap.get(pattern);
if (tl == null)
synchronized (lockObj)
tl = sdfMap.get(pattern);
if (tl == null)
tl = ThreadLocal.withInitial(() -> new SimpleDateFormat(pattern));
sdfMap.put(pattern, tl);
return tl.get();
private static String[] supportFmt = new String[]ALL_FULL_DATE_STR, SIMPLE_DATE_STR,DATE_FORMAT_YYYYMMDDHHMMSS, DEFAULT_YEAR_MODTH_SHORT, DEFAULT_TIME_FORMAT, DEFAULT_DATE_FORMAT_SHORT;
private static String checkFmt(String datestr)
if (datestr == null)
return null;
int len = datestr.length();
if (len == 0)
return null;
String fmt;
switch (len)
case 19:
fmt = supportFmt[0];
break;
case 10:
fmt = supportFmt[1];
break;
case 14:
fmt = supportFmt[2];
break;
case 6:
fmt = supportFmt[3];
break;
case 8:
if (datestr.indexOf(":") > 0)
fmt = supportFmt[4];
else
fmt = supportFmt[5];
break;
default:
return null;
return fmt;
/**
* 日期格式,正则表达式
*/
private static String[] supportFmtPattern = new String[]
"\\\\d4\\\\-\\\\d1,2\\\\-\\\\d1,2", "yyyy-MM-dd",
"\\\\d4-\\\\d1,2-\\\\d1,2\\\\s+\\\\d1,2:\\\\d1,2:\\\\d1,2", "yyyy-MM-dd HH:mm:ss",
"\\\\d1,2:\\\\d1,2:\\\\d1,2", "HH:mm:ss",
"\\\\d1,2:\\\\d1,2:\\\\d1,2\\\\.\\\\d1,3", "HH:mm:ss.SSS",
"\\\\d4年\\\\d1,2月\\\\d1,2日", "yyyy年MM月dd日",
"\\\\d4-\\\\d1,2-\\\\d1,2\\\\s+\\\\d1,2:\\\\d1,2:\\\\d1,2\\\\.\\\\d1,3", "yyyy-MM-dd HH:mm:ss.SSS",
"\\\\d4(10|11|12|0[1-9])(30|31|[1-2][0-9]|0[1-9])(20|21|22|23|1[0-9]|0[0-9])([1-5][0-9]|0[0-9])([1-5][0-9]|0[0-9])", "yyyyMMddHHmmss",
"\\\\d4(10|11|12|0[1-9])(30|31|[1-2][0-9]|0[1-9])", "yyyyMMdd",
"\\\\d4(10|11|12|0[1-9])(30|31|[1-2][0-9]|0[1-9])(20|21|22|23|1[0-9]|0[0-9])([1-5][0-9]|0[0-9])([1-5][0-9]|0[0-9])\\\\d1,3", "yyyyMMddHHmmssSSS",
"\\\\d4(10|11|12|0[1-9])", "yyyyMM",
"\\\\d4\\\\/\\\\d1,2\\\\/\\\\d1,2", "yyyy/MM/dd",
"\\\\d4\\\\.\\\\d1,2\\\\.\\\\d1,2", "yyyy.MM.dd",
"\\\\d1,2\\\\-\\\\d1,2\\\\-\\\\d4", "MM-dd-yyyy",
"\\\\d1,2\\\\/\\\\d1,2\\\\/\\\\d4", "MM/dd/yyyy",
"\\\\d1,2\\\\/\\\\d1,2\\\\/\\\\d2", "MM/dd/yy",
"\\\\d4\\\\/\\\\d1,2\\\\/\\\\d1,2T\\\\d1,2:\\\\d1,2:\\\\d1,2", "yyyy/MM/dd'T'HH:mm:ss",
"\\\\d4\\\\/\\\\d1,2\\\\/\\\\d1,2t\\\\d1,2:\\\\d1,2:\\\\d1,2", "yyyy/MM/dd't'HH:mm:ss",
"\\\\d4-\\\\d1,2-\\\\d1,2T\\\\d1,2:\\\\d1,2:\\\\d1,2", "yyyy-MM-dd'T'HH:mm:ss",
"\\\\d4-\\\\d1,2-\\\\d1,2t\\\\d1,2:\\\\d1,2:\\\\d1,2", "yyyy-MM-dd't'HH:mm:ss",
"\\\\d4\\\\/\\\\d1,2\\\\/\\\\d1,2T\\\\d1,2:\\\\d1,2:\\\\d1,2\\\\.\\\\d1,3Z", "yyyy/MM/dd'T'HH:mm:ss.SSS'Z'",
"\\\\d4\\\\/\\\\d1,2\\\\/\\\\d1,2t\\\\d1,2:\\\\d1,2:\\\\d1,2\\\\.\\\\d1,3z", "yyyy/MM/dd't'HH:mm:ss.SSS'z'",
"\\\\d4-\\\\d1,2-\\\\d1,2T\\\\d1,2:\\\\d1,2:\\\\d1,2\\\\.\\\\d1,3Z", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
"\\\\d4-\\\\d1,2-\\\\d1,2t\\\\d1,2:\\\\d1,2:\\\\d1,2\\\\.\\\\d1,3z", "yyyy-MM-dd't'HH:mm:ss.SSS'z'"
;
/**
* 日期格式,正则表达式
*/
private static String[] supportDateFmtPattern = new String[]
"\\\\d4\\\\-\\\\d1,2\\\\-\\\\d1,2", "yyyy-MM-dd",
"\\\\d4年\\\\d1,2月\\\\d1,2日", "yyyy年MM月dd日",
"\\\\d4(10|11|12|0[1-9])(30|31|[1-2][0-9]|0[1-9])", "yyyyMMdd",
"\\\\d4(10|11|12|0[1-9])", "yyyyMM",
"\\\\d4\\\\/\\\\d1,2\\\\/\\\\d1,2", "yyyy/MM/dd",
"\\\\d4\\\\.\\\\d1,2\\\\.\\\\d1,2", "yyyy.MM.dd",
"\\\\d1,2\\\\-\\\\d1,2\\\\-\\\\d4", "MM-dd-yyyy",
"\\\\d1,2\\\\/\\\\d1,2\\\\/\\\\d4", "MM/dd/yyyy",
"\\\\d1,2\\\\/\\\\d1,2\\\\/\\\\d2", "MM/dd/yy"
;
/**
* 时间格式,正则表达式
*/
private static String[] supportTimeFmtPattern = new String[]
"\\\\d4-\\\\d1,2-\\\\d1,2\\\\s+\\\\d1,2:\\\\d1,2:\\\\d1,2", "yyyy-MM-dd HH:mm:ss",
"\\\\d1,2:\\\\d1,2:\\\\d1,2", "HH:mm:ss",
"\\\\d1,2:\\\\d1,2:\\\\d1,2\\\\.\\\\d1,3", "HH:mm:ss.SSS",
"\\\\d4-\\\\d1,2-\\\\d1,2\\\\s+\\\\d1,2:\\\\d1,2:\\\\d1,2\\\\.\\\\d1,3", "yyyy-MM-dd HH:mm:ss.SSS",
"\\\\d4(10|11|12|0[1-9])(30|31|[1-2][0-9]|0[1-9])(20|21|22|23|1[0-9]|0[0-9])([1-5][0-9]|0[0-9])([1-5][0-9]|0[0-9])", "yyyyMMddHHmmss",
"\\\\d4(10|11|12|0[1-9])(30|31|[1-2][0-9]|0[1-9])(20|21|22|23|1[0-9]|0[0-9])([1-5][0-9]|0[0-9])([1-5][0-9]|0[0-9])\\\\d1,3", "yyyyMMddHHmmssSSS",
"\\\\d4\\\\/\\\\d1,2\\\\/\\\\d1,2T\\\\d1,2:\\\\d1,2:\\\\d1,2", "yyyy/MM/dd'T'HH:mm:ss",
"\\\\d4\\\\/\\\\d1,2\\\\/\\\\d1,2t\\\\d1,2:\\\\d1,2:\\\\d1,2", "yyyy/MM/dd't'HH:mm:ss",
"\\\\d4-\\\\d1,2-\\\\d1,2T\\\\d1,2:\\\\d1,2:\\\\d1,2", "yyyy-MM-dd'T'HH:mm:ss",
"\\\\d4-\\\\d1,2-\\\\d1,2t\\\\d1,2:\\\\d1,2:\\\\d1,2", "yyyy-MM-dd't'HH:mm:ss",
"\\\\d4\\\\/\\\\d1,2\\\\/\\\\d1,2T\\\\d1,2:\\\\d1,2:\\\\d1,2\\\\.\\\\d1,3Z", "yyyy/MM/dd'T'HH:mm:ss.SSS'Z'",
"\\\\d4\\\\/\\\\d1,2\\\\/\\\\d1,2t\\\\d1,2:\\\\d1,2:\\\\d1,2\\\\.\\\\d1,3z", "yyyy/MM/dd't'HH:mm:ss.SSS'z'",
"\\\\d4-\\\\d1,2-\\\\d1,2T\\\\d1,2:\\\\d1,2:\\\\d1,2\\\\.\\\\d1,3Z", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
"\\\\d4-\\\\d1,2-\\\\d1,2t\\\\d1,2:\\\\d1,2:\\\\d1,2\\\\.\\\\d1,3z", "yyyy-MM-dd't'HH:mm:ss.SSS'z'"
;
/**
* 根据日期时间串推断日期格式
*
* @param datestr 日期字符串
* @return java.lang.Integer
* @author compass
* @date 2022/10/21 11:06
* @since 1.0.0
**/
public static String checkFmtByPattern(String datestr)
if (datestr == null)
return null;
for (int i = 0; i < supportFmtPattern.length; i += 2)
if (Pattern.matches(supportFmtPattern[i], datestr))
return supportFmtPattern[i + 1];
return null;
/**
* 根据字符串格式自动判断日期格式,支持11种 <br>
* yyyy-MM-dd HH:mm:ss.SSS <br>
* yyyy-MM-dd HH:mm:ss <br>
* yyyy-MM-dd <br>
* yyyy.MM.dd <br>
* yyyy/MM/dd <br>
* HH:mm:ss.SSS <br>
* HH:mm:ss <br>
* yyyyMMdd <br>
* yyyyMMddHHmmssSSS <br>
* yyyyMMddHHmmss <br>
* yyyyMM <br>
*
* @param datestr
* @return
*/
public static Date parse(String datestr)
String fmt = checkFmtByPattern(datestr);
return parse(datestr, fmt);
/**
* 获取yyyy-MM-dd日期类型
*
* @param dateStr 日期字符串
* @param fmt 日期格式
* @return java.lang.Integer
* @author compass
* @date 2022/10/21 11:06
* @since 1.0.0
**/
public static Date parse(String dateStr, String fmt)
try
return getSdf(fmt).parse(dateStr);
catch (NullPointerException | ParseException e)
throw new RuntimeException(String.format("不支持的时间格式,[%s]", dateStr));
/**
* 获取yyyy-MM-dd日期类型
*
* @param datestr 日期字符串
* @return java.lang.Integer
* @author compass
* @date 2022/10/21 11:06
* @since 1.0.0
**/
public static Date parseDay(String datestr)
try
return getSdf(supportFmt[1]).parse(datestr);
catch (ParseException e)
throw new RuntimeException("不支持的时间格式");
/**
* 获取yyyy-MM-dd HH:mm:ss日期类型
*
* @param datestr 日期字符串
* @return java.lang.Integer
* @author compass
* @date 2022/10/21 11:06
* @since 1.0.0
**/
public static Date parseDayTime(String datestr)
try
return getSdf(supportFmt[0]).parse(datestr);
catch (ParseException e)
throw new RuntimeException("不支持的时间格式");
/**
* 将日期格式化成指定格式
*
* @param dt 日期
* @param dt 格式字符串
* @return java.lang.Integer
* @author compass
* @date 2022/10/21 11:06
* @since 1.0.0
**/
public static String format(Date dt, String... pattern)
if (pattern != null && pattern.length > 1)
throw new RuntimeException("日期格式字符串,只支持一个");
String format = pattern.length <= 0 ?DEFAULT_DATETIME_FORMAT : pattern[0];
return getSdf(format).format(dt);
/**
* 将日期格式化为yyyy-MM-dd HH:mm:ss
*
* @param dt 日期
* @return java.lang.Integer
* @author compass
* @date 2022/10/21 11:06
* @since 1.0.0
**/
public static String formatDayTime(Date dt)
return getSdf(supportFmt[0]).format(dt);
/**
* 将日期格式化为yyyy-MM-dd
*
* @param dt 开日期
* @return java.lang.Integer
* @author compass
* @date 2022/10/21 11:06
* @since 1.0.0
**/
public static String formatDay(Date dt)
return getSdf(supportFmt[1]).format(dt);
/**
* 将日期格式化为HH:mm:ss
*
* @param dt 开日期
* @return java.lang.Integer
* @author compass
* @date 2022/10/21 11:06
* @since 1.0.0
**/
public static String formatTime(Date dt)
return getSdf(supportFmt[4]).format(dt);
/**
* 计算月份差[日期型],按月份计算忽略天数
*
* @param fromDate 开始日期
* @param toDate 结束日期
* @return java.lang.Integer
* @author compass
* @date 2022/10/21 11:06
* @since 1.0.0
**/
public static Integer monthBetween(Date fromDate, Date toDate)
if ((fromDate == null) || (toDate == null))
return null;
int times = 1;
if (!fromDate.after(toDate))
Calendar calFrom = Calendar.getInstance();
Calendar calTo = Calendar.getInstance();
calFrom.setTime(fromDate);
calFrom.set(Calendar.DAY_OF_MONTH, 1);
calTo.setTime(toDate);
calTo.set(Calendar.DAY_OF_MONTH, 1);
while (calFrom.before(calTo))
calFrom.add(2, 1);
times++;
else
return 0;
return times;
/**
* 计算月份差(字符型),自动判定格式
*
* @param fromDate 开始日期
* @param toDate 结束日期
* @return java.lang.Integer
* @author compass
* @date 2022/10/21 11:06
* @since 1.0.0
**/
public static Integer monthBetween(String fromDate, String toDate)
if ((fromDate == null) || (toDate == null))
return null;
return monthBetween(parse(fromDate), parse(toDate));
/**
* 计算天数差
*
* @param from 开始日期
* @param end 结束日期
* @return java.util.Date
* @author compass
* @date 2022/10/21 11:06
* @since 1.0.0
**/
public static Integer daysBetween(Date from, Date end)
if ((from == null) || (end == null))
return null;
long fromL = from.getTime();
long endL = end.getTime();
double diff = 网上搜罗的些年月日季度之类的工具类,