import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Optional;
/**
* 处理Date的工具类
* 一方库依赖:无
* 二方库依赖:无
* 三方库依赖:无
*
* @author ParanoidCAT
* @since JDK 1.8
*/
public class DateUtils {
/**
* 以下是解析或格式化Date时所需的Pattern字符串常量
* 这些常量字符串将常驻内存中方便在需要的时候作为参数生成SimpleDateFormat
* 在这里没有使用SimpleDateFormat作为常量的原因是因为其父类DateFormat内部使用了一个Calendar字段来缓存需要处理的Date
* 由于该字段的修改方法并没有对多线程访问进行限制,因此在并发调用时会导致难以预料的线程安全问题
* 尽管每次都实例化新的SimpleDateFormat会有一定的额外开销,但比起数据的一致性的确保,这一开销是完全值得的
*
* @see DateFormat
*/
public static final String DATE_PATTERN = "yyyy-MM-dd";
public static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
public static final String DATE_TIME_MILLISECOND_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS";
public static final String[] PATTERNS = {
DATE_PATTERN, DATE_TIME_PATTERN, DATE_TIME_MILLISECOND_PATTERN, "yyyy/MM/dd HH:mm:ss"
};
/**
* 根据默认格式化模板将Date格式化为String
* 默认格式化模板为"yyyy-MM-dd HH:mm:ss"
*
* @param date 待格式化的Date
* @return java.lang.String
*/
public static String format(Date date) {
return format(date, DATE_TIME_PATTERN);
}
/**
* 根据指定的格式化模板datePattern将Date格式化为String
* 若指定的格式化模板为null,使用默认格式化模板
*
* @param date 待格式化的Date
* @param datePattern 指定的格式化模板
* @return java.lang.String
*/
public static String format(Date date, String datePattern) {
try {
return new SimpleDateFormat(Optional.ofNullable(datePattern).orElse(DATE_TIME_PATTERN)).format(date);
} catch (Exception e) {
return null;
}
}
/**
* 根据指定的解析模板datePattern将String解析为Date
*
* @param dateString 待解析的String
* @param datePattern 指定的解析模板
* @return java.util.Date
*/
public static Date parse(String dateString, String datePattern) {
try {
DateFormat dateFormat = new SimpleDateFormat(datePattern);
Date date = dateFormat.parse(dateString);
// 注意,这里在完成解析后必须反向格式化进行校验才可以返回
return dateString.equals(dateFormat.format(date)) ? date : null;
} catch (Exception e) {
return null;
}
}
/**
* 根据一系列解析模板datePatterns将String解析为Date
*
* @param dateString 待解析的String
* @param datePatterns 一系列解析模板
* @return java.util.Date
*/
public static Date parse(String dateString, String[] datePatterns) {
Date date = null;
for (String datePattern : Optional.ofNullable(datePatterns).orElse(PATTERNS)) {
if (null == date) {
date = parse(dateString, datePattern);
} else {
break;
}
}
return date;
}
/**
* 根据默认解析模板将String解析为Date
*
* @param dateString 待解析的String
* @return java.util.Date
*/
public static Date parse(String dateString) {
return parse(dateString, PATTERNS);
}
/**
* 对Date进行变更的方法
* 内部使用Calendar实现
* 私有方法,只有date和amount为外部传入
* 为避免amount的形参为int时实参为null自动拆箱即抛出NullPointException(此时未进入方法无法捕获),使用Integer作为形参,在内部处理
*
* @param date 待变更的Date
* @param calendarField Calendar的字段编号
* @param amount 变更的数量(正数为增加负数为减少)
* @return java.util.Date
*/
private static Date add(Date date, int calendarField, Integer amount) {
try {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(calendarField, Optional.ofNullable(amount).orElse(0));
return calendar.getTime();
} catch (Exception e) {
return null;
}
}
/**
* 变更Date的年
*
* @param date 待变更的Date
* @param amount 变更的数量(正数为增加负数为减少)
* @return java.util.Date
*/
public static Date addYears(Date date, Integer amount) {
return add(date, Calendar.YEAR, amount);
}
/**
* 变更Date的月
*
* @param date 待变更的Date
* @param amount 变更的数量(正数为增加负数为减少)
* @return java.util.Date
*/
public static Date addMonths(Date date, Integer amount) {
return add(date, Calendar.MONTH, amount);
}
/**
* 变更Date的日期
*
* @param date 待变更的Date
* @param amount 变更的数量(正数为增加负数为减少)
* @return java.util.Date
*/
public static Date addDays(Date date, Integer amount) {
return add(date, Calendar.DATE, amount);
}
/**
* 变更Date的小时
*
* @param date 待变更的Date
* @param amount 变更的数量(正数为增加负数为减少)
* @return java.util.Date
*/
public static Date addHours(Date date, Integer amount) {
return add(date, Calendar.HOUR_OF_DAY, amount);
}
/**
* 变更Date的分钟
*
* @param date 待变更的Date
* @param amount 变更的数量(正数为增加负数为减少)
* @return java.util.Date
*/
public static Date addMinutes(Date date, Integer amount) {
return add(date, Calendar.MINUTE, amount);
}
/**
* 变更Date的秒
*
* @param date 待变更的Date
* @param amount 变更的数量(正数为增加负数为减少)
* @return java.util.Date
*/
public static Date addSeconds(Date date, Integer amount) {
return add(date, Calendar.SECOND, amount);
}
/**
* 变更Date的毫秒
*
* @param date 待变更的Date
* @param amount 变更的数量(正数为增加负数为减少)
* @return java.util.Date
*/
public static Date addMilliseconds(Date date, Integer amount) {
return add(date, Calendar.MILLISECOND, amount);
}
/**
* 获取当前日期字符串
*
* @return java.lang.String
*/
public static String getCurrentDate() {
return format(new Date(), DATE_PATTERN);
}
/**
* 获取当前时间字符串
*
* @return java.lang.String
*/
public static String getCurrentDateTime() {
return format(new Date(), DATE_TIME_PATTERN);
}
/**
* 获取当前时间(带毫秒)字符串
*
* @return java.lang.String
*/
public static String getCurrentDateTimeMillisecond() {
return format(new Date(), DATE_TIME_MILLISECOND_PATTERN);
}
/**
* 获取当前小时
*
* @return int
*/
public static int getCurrentHour() {
return Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
}
/**
* 变更Date的时间为0时0分0秒
*
* @param date 待变更的Date
* @return java.util.Date
*/
public static Date getStartOfDate(Date date) {
try {
return parse(format(date, DATE_PATTERN) + " 00:00:00", DATE_TIME_PATTERN);
} catch (Exception e) {
return null;
}
}
/**
* 变更Date的时间为23时59分59秒
*
* @param date 待变更的Date
* @return java.util.Date
*/
public static Date getEndOfDate(Date date) {
try {
return parse(format(date, DATE_PATTERN) + " 23:59:59", DATE_TIME_PATTERN);
} catch (Exception e) {
return null;
}
}
}