视频讲解
实现效果
简述
今天遇到一个需求,就是将消息的创建时间与当前时间做比较,展示对应的数据格式,具体要求如下:
1. 1分钟内:刚刚
2. 60分钟内:x分钟前
3. 24小时内:x小时前
4. >24小时:x月x日 08-1
5. 非年内:年-月-日 2021-05-02
实现思路
从需求描述来看,我们很容易可以发现需要比较的时间的最小精度是【秒】,所以我们具体操作可以这样做
- 先取得年份,比较是否在年内
- 当前时间与传入时间比较取得秒数差
- 比较60秒内显示刚刚
- 秒数差 < 60*60 (即60分钟) => 秒数差/60 分钟前
- 秒数差 < 606024 (即24小时内) => 秒数差/60*60 小时前
- 秒数差 >606024 (即24小时内) => 转localDateTime 后再格式化输出 【SimpleDateFormat多线程不安全】
转换成代码如下:
为了操作方便,也避免计算出错,这里将各个时间单位转换为秒数定义为静态常量,并且使用DateTimFormatter格式化保证多线程安全,如下:
完整代码
封装DateUtil工具类
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
/**
* @Author: lzp
* @description:
* @Date: 2022/8/6
*/
public class DateUtils {
/**
* 一天、一分钟、一小时对应的秒数
*/
private static final Long ONE_MINUTE_TO_SECOND = 60L;
private static final Long ONE_HOUR_TO_SECOND = ONE_MINUTE_TO_SECOND * 60;
private static final Long ONE_DAY_TO_SECOND = ONE_HOUR_TO_SECOND * 24;
/**
* 使用LocalDateTime进行格式化 保证多线程安全
*/
private static final DateTimeFormatter DATE_TIME_FORMATTER1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
private static final DateTimeFormatter DATE_TIME_FORMATTER2 = DateTimeFormatter.ofPattern("MM-dd");
/**
* 设置推送消息的时间描述
* 1. 1分钟内:刚刚
* 2. 60分钟内:x分钟前
* 3. 24小时内:x小时前
* 4. >24小时:x月x日 08-1
* 5. 非年内:年-月-日 2021-05-02
*
* @param now 当前时间 传一个当前时间目的是方便遍历,减少date对象的创建
* @param targetDate 与当前时间做对比的时间
*/
public static String getTimeDescriptionByDate(Date now, Date targetDate) {
String timeDescription = "";
if (targetDate != null) {
// 5. 年内判断
if (targetDate.getYear() == now.getYear()) {
// 获取秒数差
long betweenSeconds = (now.getTime() - targetDate.getTime()) / 1000;
if (betweenSeconds < ONE_MINUTE_TO_SECOND) {
// 1. 1分钟内:刚刚
timeDescription = "刚刚";
} else if (betweenSeconds < ONE_HOUR_TO_SECOND) {
// 2. 60分钟内
timeDescription = betweenSeconds / ONE_MINUTE_TO_SECOND + "分钟前";
} else if (betweenSeconds < ONE_HOUR_TO_SECOND * 24) {
// 3. 24小时内:x小时前
timeDescription = betweenSeconds / ONE_HOUR_TO_SECOND + "小时前";
} else {
// 4. >24小时:x月x日 08-1
timeDescription = dateToLocalDateTime(targetDate).format(DATE_TIME_FORMATTER2);
}
} else {
timeDescription = dateToLocalDateTime(targetDate).format(DATE_TIME_FORMATTER1);
}
}
return timeDescription;
}
/**
* date转localDateTime
*/
public static LocalDateTime dateToLocalDateTime(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
}
}
测试类,直接运行即可,能够自动按照当前时间显示对应的描述:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Author: lzp
* @description:
* @Date: 2022/8/6
*/
public class Demo {
public static void main(String[] args) throws ParseException {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date now = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(now);
System.out.printf("当前时间为:%s ==============================\n", df.format(now));
cal.add(Calendar.SECOND, -20); // 20秒前
System.out.printf("%s => %s\n", df.format(cal.getTime()), DateUtils.getTimeDescriptionByDate(now, cal.getTime()));
cal.add(Calendar.MINUTE, -1); // 1分钟前
System.out.printf("%s => %s\n", df.format(cal.getTime()), DateUtils.getTimeDescriptionByDate(now, cal.getTime()));
cal.add(Calendar.HOUR, -1); // 1小时前
System.out.printf("%s => %s\n", df.format(cal.getTime()), DateUtils.getTimeDescriptionByDate(now, cal.getTime()));
cal.add(Calendar.DAY_OF_MONTH, -1); // 1天前
System.out.printf("%s => %s\n", df.format(cal.getTime()), DateUtils.getTimeDescriptionByDate(now, cal.getTime()));
cal.add(Calendar.YEAR, -1); // 1年前
System.out.printf("%s => %s\n", df.format(cal.getTime()), DateUtils.getTimeDescriptionByDate(now, cal.getTime()));
}
}