package org.springside.modules.utils.time;
import java.text.ParseException;
import java.util.Date;
import org.apache.commons.lang3.time.DurationFormatUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.springside.modules.utils.base.annotation.NotNull;
/**
* Date的parse()与format(), 采用Apache Common Lang中线程安全, 性能更佳的FastDateFormat
*
* 注意Common Lang版本,3.5版才使用StringBuilder,3.4及以前使用StringBuffer.
*
* 1. 常用格式的FastDateFormat定义
*
* 2. 日期格式不固定时的String<->Date 转换函数.
*
* 3. 打印时间间隔,如"01:10:10",以及用户友好的版本,比如"刚刚","10分钟前"
*
* @see FastDateFormat#parse(String)
* @see FastDateFormat#format(java.util.Date)
* @see FastDateFormat#format(long)
*
* @author calvin
*/
public class DateFormatUtil {
// 以T分隔日期和时间,并带时区信息,符合ISO8601规范
public static final String PATTERN_ISO = "yyyy-MM-dd'T'HH:mm:ss.SSSZZ";
public static final String PATTERN_ISO_ON_SECOND = "yyyy-MM-dd'T'HH:mm:ssZZ";
public static final String PATTERN_ISO_ON_DATE = "yyyy-MM-dd";
// 以空格分隔日期和时间,不带时区信息
public static final String PATTERN_DEFAULT = "yyyy-MM-dd HH:mm:ss.SSS";
public static final String PATTERN_DEFAULT_ON_SECOND = "yyyy-MM-dd HH:mm:ss";
// 使用工厂方法FastDateFormat.getInstance(), 从缓存中获取实例
// 以T分隔日期和时间,并带时区信息,符合ISO8601规范
public static final FastDateFormat ISO_FORMAT = FastDateFormat.getInstance(PATTERN_ISO);
public static final FastDateFormat ISO_ON_SECOND_FORMAT = FastDateFormat.getInstance(PATTERN_ISO_ON_SECOND);
public static final FastDateFormat ISO_ON_DATE_FORMAT = FastDateFormat.getInstance(PATTERN_ISO_ON_DATE);
// 以空格分隔日期和时间,不带时区信息
public static final FastDateFormat DEFAULT_FORMAT = FastDateFormat.getInstance(PATTERN_DEFAULT);
public static final FastDateFormat DEFAULT_ON_SECOND_FORMAT = FastDateFormat.getInstance(PATTERN_DEFAULT_ON_SECOND);
/**
* 分析日期字符串, 仅用于pattern不固定的情况.
*
* 否则直接使用DateFormats中封装好的FastDateFormat.
*
* FastDateFormat.getInstance()已经做了缓存,不会每次创建对象,但直接使用对象仍然能减少在缓存中的查找.
*/
public static Date pareDate(@NotNull String pattern, @NotNull String dateString) throws ParseException {
return FastDateFormat.getInstance(pattern).parse(dateString);
}
/**
* 格式化日期, 仅用于pattern不固定的情况.
*
* 否则直接使用本类中封装好的FastDateFormat.
*
* FastDateFormat.getInstance()已经做了缓存,不会每次创建对象,但直接使用对象仍然能减少在缓存中的查找.
*/
public static String formatDate(@NotNull String pattern, @NotNull Date date) {
return FastDateFormat.getInstance(pattern).format(date);
}
/**
* 格式化日期, 仅用于不固定pattern不固定的情况.
*
* 否否则直接使用本类中封装好的FastDateFormat.
*
* FastDateFormat.getInstance()已经做了缓存,不会每次创建对象,但直接使用对象仍然能减少在缓存中的查找.
*/
public static String formatDate(@NotNull String pattern, long date) {
return FastDateFormat.getInstance(pattern).format(date);
}
/////// 格式化间隔时间/////////
/**
* 按HH:mm:ss.SSS格式,格式化时间间隔.
*
* endDate必须大于startDate,间隔可大于1天,
*/
public static String formatDuration(@NotNull Date startDate, @NotNull Date endDate) {
return DurationFormatUtils.formatDurationHMS(endDate.getTime() - startDate.getTime());
}
/**
* 按HH:mm:ss.SSS格式,格式化时间间隔
*
* 单位为毫秒,必须大于0,可大于1天
*/
public static String formatDuration(long durationMillis) {
return DurationFormatUtils.formatDurationHMS(durationMillis);
}
/**
* 按HH:mm:ss格式,格式化时间间隔
*
* endDate必须大于startDate,间隔可大于1天
*/
public static String formatDurationOnSecond(@NotNull Date startDate, @NotNull Date endDate) {
return DurationFormatUtils.formatDuration(endDate.getTime() - startDate.getTime(), "HH:mm:ss");
}
/**
* 按HH:mm:ss格式,格式化时间间隔
*
* 单位为毫秒,必须大于0,可大于1天
*/
public static String formatDurationOnSecond(long durationMillis) {
return DurationFormatUtils.formatDuration(durationMillis, "HH:mm:ss");
}
//////// 打印用于页面显示的用户友好,与当前时间比的时间差
/**
* 打印用户友好的,与当前时间相比的时间差,如刚刚,5分钟前,今天XXX,昨天XXX
*
* from AndroidUtilCode
*/
public static String formatFriendlyTimeSpanByNow(@NotNull Date date) {
return formatFriendlyTimeSpanByNow(date.getTime());
}
/**
* 打印用户友好的,与当前时间相比的时间差,如刚刚,5分钟前,今天XXX,昨天XXX
*
* from AndroidUtilCode
*/
public static String formatFriendlyTimeSpanByNow(long timeStampMillis) {
long now = ClockUtil.currentTimeMillis();
long span = now - timeStampMillis;
if (span < 0) {
// 'c' 日期和时间,被格式化为 "%ta %tb %td %tT %tZ %tY",例如 "Sun Jul 20 16:17:00 EDT 1969"。
return String.format("%tc", timeStampMillis);
}
if (span < DateUtil.MILLIS_PER_SECOND) {
return "刚刚";
} else if (span < DateUtil.MILLIS_PER_MINUTE) {
return String.format("%d秒前", span / DateUtil.MILLIS_PER_SECOND);
} else if (span < DateUtil.MILLIS_PER_HOUR) {
return String.format("%d分钟前", span / DateUtil.MILLIS_PER_MINUTE);
}
// 获取当天00:00
long wee = DateUtil.beginOfDate(new Date(now)).getTime();
if (timeStampMillis >= wee) {
// 'R' 24 小时制的时间,被格式化为 "%tH:%tM"
return String.format("今天%tR", timeStampMillis);
} else if (timeStampMillis >= wee - DateUtil.MILLIS_PER_DAY) {
return String.format("昨天%tR", timeStampMillis);
} else {
// 'F' ISO 8601 格式的完整日期,被格式化为 "%tY-%tm-%td"。
return String.format("%tF", timeStampMillis);
}
}
}