import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.NonNull;
import java.lang.reflect.Field;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
/**
* @author
* @version 1.0
* @Description 时间工具类
* @date 2020/01/08 14:03
*/
public class DateUtils {
// 缓存
private static final Map<String, DateTimeFormatter> FORMATTER_CACHE = new ConcurrentHashMap<>();
private static final String PREFIX = "com.example.project.util.DateUtils$Pattern$";
private static final String DATE_TIME_CLASS_NAME = "DateTime";
private static final String DATE_CLASS_NAME = "Date";
private static final String TIME_CLASS_NAME = "Time";
private DateUtils() {
}
/**
* 日期的格式化定义
*
* @author wangl
* @date 12/28/2020
*/
public static class Pattern {
private Pattern() {
}
public static class Date {
private Date() {
}
public static final String YYYY_MM_DD = "yyyy-MM-dd";
public static final String YYYY_M_DD = "yyyy-M-dd";
public static final String YYYY_M_D = "yyyy-M-d";
public static final String YYYY_MM_DD_ = "yyyy/MM/dd";
public static final String YYYY_M_DD_ = "yyyy/M/dd";
public static final String YYYY_M_D_ = "yyyy/M/d";
public static final String YYYYMMDD = "yyyyMMdd";
public static final String YYYYMDD = "yyyyMdd";
public static final String YYYYMD = "yyyyMd";
public static final String MM_DD_YYYY = "MM-dd-yyyy";
public static final String M_DD_YYYY = "M-dd-yyyy";
public static final String M_D_YYYY = "M-d-yyyy";
public static final String MM_DD_YYYY_ = "MM/dd/yyyy";
public static final String M_DD_YYYY_ = "M/dd/yyyy";
public static final String M_D_YYYY_ = "M/d/yyyy";
public static final String MMDDYYYY = "MMddyyyy";
public static final String MDDYYYY = "Mddyyyy";
public static final String MDYYYY = "Mdyyyy";
}
public static class DateTime {
private DateTime() {
}
public static final String YYYY_MM_DD_SPACE_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
public static final String YYYY_MM_DD_SPACE_HH_MM = "yyyy-MM-dd HH:mm";
public static final String YYYY_M_D_SPACE_H_M_S = "yyyy-M-d H:m:s";
public static final String YYYY_MM_DD_SPACE_HH_MM_SS_ = "yyyy/MM/dd HH:mm:ss";
public static final String HH_MM_SPACE_YYYY_MM_DD = "HH:mm yyyy-MM-dd";
public static final String HH_MM_SPACE_YYYY_MM_DD_ = "HH:mm yyyy/MM/dd";
public static final String H_MM_SPACE_YYYY_MM_DD = "H:mm yyyy-MM-dd";
public static final String H_MM_SPACE_YYYY_MM_DD_ = "H:mm yyyy/MM/dd";
public static final String H_MM_COMMA_YYYY_MM_DD = "H:mm,yyyy-MM-dd";
public static final String H_MM_COMMA_YYYY_MM_DD_ = "H:mm,yyyy/MM/dd";
public static final String H_MM_COMMA_YYYY_M_D = "H:mm,yyyy-M-d";
public static final String H_M_COMMA_YYYY_M_D = "H:m,yyyy-M-d";
public static final String H_MM_COMMA_YYYY_M_D_ = "H:mm,yyyy/M/d";
public static final String H_M_COMMA_YYYY_M_D_ = "H:m,yyyy/M/d";
public static final String YYYY_MM_DD_HH_MM = "yyyyMMddHHmm";
public static final String YYYY_MM_DD_HH_MM_SS = "yyyyMMddHHmmss";
}
public static class Time {
private Time() {
}
public static final String HH_MM_SS = "HH:mm:ss";
public static final String H_M_S = "H:m:s";
public static final String HH_MM = "HH:mm";
public static final String H_MM = "H:mm";
public static final String H_M = "H:m";
public static final String HH = "HH";
public static final String HHMM = "HHmm";
public static final String HHMMSS = "HHmmss";
}
}
/**
* Date --> LocalDateTime
*
* @param date
* @return LocalDateTime
*/
public static LocalDateTime dateToLocalDateTime(Date date) {
Instant instant = date.toInstant();
// 获取系统默认时区
ZoneId zone = ZoneId.systemDefault();
return LocalDateTime.ofInstant(instant, zone);
}
/**
* @return Date
* @Description LocalDateTime -> Date
* @Param localDateTime
*/
public static Date localDateTimeToDate(LocalDateTime localDateTime) {
ZoneId zone = ZoneId.systemDefault();
ZonedDateTime zonedDateTime = localDateTime.atZone(zone);
Instant instant = zonedDateTime.toInstant();
return Date.from(instant);
}
/**
* Date --> String
*
* @param time 时分秒
* @param pattern 时间格式(静态内部类实现)
* @return
*/
public static String formatTime(@NonNull Date time, @NonNull String pattern) {
if (StringUtils.isBlank(pattern)) {
throw new NullPointerException("pattern is null");
}
Instant instant = time.toInstant();
// 获取系统默认时区
ZoneId zone = ZoneId.systemDefault();
LocalTime formatTime = LocalDateTime.ofInstant(instant, zone).toLocalTime();
return formatLocalTime(formatTime, pattern);
}
/**
* Date --> String
*
* @param date 年月日
* @param pattern 日期格式(静态内部类实现)
* @return
*/
public static String formatDate(@NonNull Date date, @NonNull String pattern) {
if (StringUtils.isBlank(pattern)) {
throw new NullPointerException("pattern is null");
}
Instant instant = date.toInstant();
// 获取系统默认时区
ZoneId zone = ZoneId.systemDefault();
LocalDate localDate = LocalDateTime.ofInstant(instant, zone).toLocalDate();
return formatLocalDate(localDate, pattern);
}
/**
* Date --> String
*
* @param dateTime 年月日时分秒
* @param pattern 日期格式(静态内部类实现)
* @return
*/
public static String formatDateTime(@NonNull Date dateTime, @NonNull String pattern) {
if (StringUtils.isBlank(pattern)) {
throw new NullPointerException("pattern is null");
}
Instant instant = dateTime.toInstant();
// 获取系统默认时区
ZoneId zone = ZoneId.systemDefault();
LocalDateTime formatDateTime = LocalDateTime.ofInstant(instant, zone);
return formatLocalDateTime(formatDateTime, pattern);
}
/**
* LocalDate(时分秒) --> String
*
* @param localTime
* @param pattern 时间格式(静态内部类实现)
* @return
*/
public static String formatLocalTime(@NonNull LocalTime localTime, @NonNull String pattern) {
if (StringUtils.isBlank(pattern)) {
throw new NullPointerException("pattern is null");
}
DateTimeFormatter formatter = createCacheFormatter(pattern);
return localTime.format(formatter);
}
/**
* LocalDate(年月日) --> String
*
* @param localDate
* @param pattern 日期格式(静态内部类实现)
* @return
*/
public static String formatLocalDate(@NonNull LocalDate localDate, @NonNull String pattern) {
if (StringUtils.isBlank(pattern)) {
throw new NullPointerException("pattern is null");
}
DateTimeFormatter formatter = createCacheFormatter(pattern);
return localDate.format(formatter);
}
/**
* LocalDateTime(年月日时分秒) --> String
*
* @param localDateTime
* @param pattern 日期格式(静态内部类实现)
* @return
*/
public static String formatLocalDateTime(@NonNull LocalDateTime localDateTime, @NonNull String pattern) {
if (StringUtils.isBlank(pattern)) {
throw new NullPointerException("pattern is null");
}
DateTimeFormatter formatter = createCacheFormatter(pattern);
return localDateTime.format(formatter);
}
/**
* String(年月日) --> Date
*
* @param date
* @param pattern 日期格式(静态内部类实现)
* @return
*/
public static Date parseDate(@NonNull String date, @NonNull String pattern) {
LocalDate localDate = stringToLocalDate(date, pattern);
Instant instant = localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
return Date.from(instant);
}
/**
* String(年月日时分秒) --> Date
*
* @param dateTime
* @param pattern 日期格式(静态内部类实现)
* @return
*/
public static Date parseDateTime(@NonNull String dateTime, @NonNull String pattern) {
if (StringUtils.isBlank(dateTime)) {
throw new NullPointerException("date is null");
}
if (StringUtils.isBlank(pattern)) {
throw new NullPointerException("pattern is null");
}
LocalDateTime localDateTime = parseLocalDateTime(dateTime, pattern);
Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
return Date.from(instant);
}
/**
* String(年月日) --> LocalTime
*
* @param time
* @param pattern 日期格式(静态内部类实现)
* @return parseLocalTime
*/
public static LocalTime stringToLocalTime(@NonNull String time, @NonNull String pattern) {
if (StringUtils.isBlank(time)) {
throw new NullPointerException("time is null");
}
if (StringUtils.isBlank(pattern)) {
throw new NullPointerException("pattern is null");
}
DateTimeFormatter formatter = createCacheFormatter(pattern);
return LocalTime.parse(time, formatter);
}
/**
* String(年月日) --> LocalDate
*
* @param date
* @param pattern 日期格式(静态内部类实现)
* @return
*/
private static LocalDate stringToLocalDate(@NonNull String date, @NonNull String pattern) {
if (StringUtils.isBlank(date)) {
throw new NullPointerException("date is null");
}
if (StringUtils.isBlank(pattern)) {
throw new NullPointerException("pattern is null");
}
DateTimeFormatter formatter = createCacheFormatter(pattern);
return LocalDate.parse(date, formatter);
}
/**
* String(年月日时分秒) --> LocalDateTime
*
* @param dateTime
* @param pattern 日期格式(静态内部类实现)
* @return
*/
private static LocalDateTime stringToLocalDateTime(@NonNull String dateTime, @NonNull String pattern) {
if (StringUtils.isBlank(dateTime)) {
throw new NullPointerException("date is null");
}
if (StringUtils.isBlank(pattern)) {
throw new NullPointerException("pattern is null");
}
DateTimeFormatter formatter = createCacheFormatter(pattern);
return LocalDateTime.parse(dateTime, formatter);
}
/**
* @return
* @Description 适配字符串转 LocalDate
*
* <pre>
* 只有时间时,会补全日期为1970-01-01
* </pre>
* @Param [date, format]
*/
public static LocalDate parseLocalDate(@NonNull String date, @NonNull String format) {
if (StringUtils.isBlank(date)) {
throw new NullPointerException("date is null");
}
if (StringUtils.isBlank(format)) {
throw new NullPointerException("format is null");
}
LocalDate localDate;
try {
if (containsContent(format, PREFIX + DATE_TIME_CLASS_NAME)) {
localDate = stringToLocalDateTime(date, format).toLocalDate();
} else if (containsContent(format, PREFIX + DATE_CLASS_NAME)) {
localDate = stringToLocalDate(date, format);
} else if (containsContent(format, PREFIX + TIME_CLASS_NAME)) {
localDate = LocalDate.of(1970, 1, 1);
} else {
throw new RuntimeException("不支持的时间类型");
}
return localDate;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
/**
* @return
* @Description 适配字符串转 LocalDateTime
*
* <pre>
* 只有日期时,会不全时间为00:00:00
* 只有时间时,会补全日期为1970-01-01
* </pre>
* @Param [date, format]
*/
public static LocalDateTime parseLocalDateTime(@NonNull String date, @NonNull String format) {
if (StringUtils.isBlank(date)) {
throw new NullPointerException("date is null");
}
if (StringUtils.isBlank(format)) {
throw new NullPointerException("format is null");
}
LocalDateTime localDateTime;
try {
if (containsContent(format, PREFIX + DATE_TIME_CLASS_NAME)) {
localDateTime = stringToLocalDateTime(date, format);
} else if (containsContent(format, PREFIX + DATE_CLASS_NAME)) {
LocalDate localDate = stringToLocalDate(date, format);
// 指定时间形成新日期时间
localDateTime = localDate.atTime(0, 0, 0);
} else if (containsContent(format, PREFIX + TIME_CLASS_NAME)) {
LocalDate localDate = LocalDate.of(1970, 1, 1);
LocalTime localTime = stringToLocalTime(date, format);
localDateTime = localTime.atDate(localDate);
} else {
throw new RuntimeException("不支持的时间类型");
}
return localDateTime;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
/**
* @return long 时间戳(毫秒)
* @Description localDateTime -> long
* @Param localDateTime
*/
public static long parseTimestamp(@NonNull LocalDateTime localDateTime) {
return localDateTime.toInstant(localDateTime.atZone(ZoneId.systemDefault()).getOffset()).toEpochMilli();
}
/**
* @return long 时间戳(毫秒)
* @Description String -> long
* @Param date
* @Param format
*/
public static long parseTimestamp(@NonNull String date, @NonNull String format) {
return parseTimestamp(parseLocalDateTime(date, format));
}
/**
* @return long 时间戳(毫秒)
* @Description Date -> long
* @Param date
*/
public static long parseTimestamp(@NonNull Date date) {
return parseTimestamp(dateToLocalDateTime(date));
}
/**
* @param begin 开始日期
* @param end 结束日期
* @return 调用period的get方法可获取年月日日期差
* @Description TODO 计算日期差
*/
public static Period calculationPeriod(@NonNull Date begin, @NonNull Date end) {
LocalDate beginLocalDate = dateToLocalDateTime(begin).toLocalDate();
LocalDate endLocalDate = dateToLocalDateTime(end).toLocalDate();
return Period.between(beginLocalDate, endLocalDate);
}
/**
* @return 调用period的get方法可获取年月日日期差
* @Description TODO 计算日期差
* @Param begin 开始时间
* @Param end 结束时间
* @format 时间格式(必须和传入的开始和结束时间格式一致)
*/
public static Period calculationPeriod(@NonNull String begin, @NonNull String end, @NonNull String format) {
if (StringUtils.isBlank(begin) || StringUtils.isBlank(end)) {
throw new NullPointerException("date is null");
}
if (StringUtils.isBlank(format)) {
throw new NullPointerException("pattern is null");
}
LocalDate beginLocalDate = parseLocalDateTime(begin, format).toLocalDate();
LocalDate endLocalDate = parseLocalDateTime(end, format).toLocalDate();
return Period.between(beginLocalDate, endLocalDate);
}
/**
* @return 调用duration的to方法可获取时分秒时间差
* @Description TODO 计算时间差
* @Param begin 开始时间
* @Param end 结束时间
* @format 时间格式(必须和传入的开始和结束时间格式一致)
* 1990-01-01 13:20:56
*/
public static Duration calculationDuration(@NonNull String begin, @NonNull String end, @NonNull String format) {
if (StringUtils.isBlank(begin) || StringUtils.isBlank(end)) {
throw new NullPointerException("date is null");
}
if (StringUtils.isBlank(format)) {
throw new NullPointerException("pattern is null");
}
LocalDateTime beginLocalDateTime = parseLocalDateTime(begin, format);
LocalDateTime endLocalDateTime = parseLocalDateTime(end, format);
return Duration.between(beginLocalDateTime, endLocalDateTime);
}
/**
* @return 时分秒
* @Description TODO 计算时间差
* @Param begin 开始时间
* @Param end 结束时间
* 1990-01-01 13:20:56
*/
public static Duration calculationDuration(@NonNull Date begin, @NonNull Date end) {
LocalDateTime beginLocalDateTime = dateToLocalDateTime(begin);
LocalDateTime endLocalDateTime = dateToLocalDateTime(end);
return Duration.between(beginLocalDateTime, endLocalDateTime);
}
/**
* 日期的加减(仅支持天/小时/分/秒)
*
* @param date 基础时间
* @param addValue 增量(负数则日期减少)
* @param unit 时间单位
* @return
*/
public static Date dateAdd(@NonNull Date date, int addValue, TimeUnit unit) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
if (TimeUnit.DAYS.equals(unit)) {
cal.add(Calendar.DAY_OF_YEAR, addValue);
} else if (TimeUnit.HOURS.equals(unit)) {
cal.add(Calendar.HOUR_OF_DAY, addValue);
} else if (TimeUnit.MINUTES.equals(unit)) {
cal.add(Calendar.MINUTE, addValue);
} else if (TimeUnit.SECONDS.equals(unit)) {
cal.add(Calendar.SECOND, addValue);
} else {
throw new RuntimeException("Time type not supported");
}
return cal.getTime();
}
/**
* DateTimeFormatter缓存
*
* @param
* @param
* @return
*/
private static DateTimeFormatter createCacheFormatter(String pattern) {
if (pattern == null || pattern.length() == 0) {
throw new IllegalArgumentException("Invalid pattern specification");
}
// 先从缓存中获取DateTimeFormatter,有就返回。没有再创建
DateTimeFormatter formatter = FORMATTER_CACHE.get(pattern);
if (null == formatter) {
formatter = DateTimeFormatter.ofPattern(pattern);
FORMATTER_CACHE.put(pattern, formatter);
}
return formatter;
}
/**
* @return
* @Description 查看格式是否在内部类常量中
* @Param [format, className]
*/
private static boolean containsContent(String format, String className) throws ClassNotFoundException, IllegalAccessException {
Class<?> clazz = Class.forName(className);
Field[] fields = clazz.getDeclaredFields();
if (!(fields.length > 0)) {
return false;
}
for (Field field : fields) {
String fieldName = field.getName();
String fieldValue = (String) field.get(fieldName);
if (format.equals(fieldValue)) {
return true;
}
}
return false;
}
}