如何实现按时间显示今日/昨日/指定日期文本?求代码优化方案
问题分析与代码优化
原代码的核心问题
- "今日"判断完全失效:直接将传入的
time与calendar.timeInMillis(当前系统精确到毫秒的时间)做相等比较,实际场景中几乎不可能触发,无法识别当天任意时刻的时间。 - "昨日"判断逻辑错误:
(time - 86400000)是数值计算而非判断条件,写法完全不符合逻辑,无法正确识别昨日的时间范围。 - 性能与线程安全隐患:每次调用方法都创建
SimpleDateFormat实例,既浪费资源,且该类非线程安全,多线程环境下易出异常。
优化后的实现方案(推荐)
使用Java 8+的java.time API(Kotlin原生兼容),该API线程安全、逻辑直观,能准确处理日期范围判断:
import java.time.LocalDate import java.time.ZoneId import java.time.format.DateTimeFormatter import java.util.Locale object DateTimeUtils { // 提前初始化线程安全的日期格式化器 private val dateFormatter = DateTimeFormatter.ofPattern("dd MMMM, yyyy", Locale.getDefault()) fun getDateLabel(timestamp: Long): String { // 将时间戳转换为日期(忽略时分秒,只保留年月日) val targetDate = LocalDate.ofEpochDay(timestamp / 86400000) val today = LocalDate.now(ZoneId.systemDefault()) val yesterday = today.minusDays(1) return when (targetDate) { today -> "今日" yesterday -> "昨日" else -> targetDate.format(dateFormatter) } } }
代码说明
- 精准日期范围判断:通过
LocalDate统一忽略时分秒,只比较年月日,确保当天任意时刻都能被识别为"今日",昨日同理。 - 线程安全与性能:
DateTimeFormatter是线程安全的单例实例,避免重复创建带来的性能损耗。 - 时区适配:使用系统默认时区,确保日期判断符合用户所在地区的时间规则。
兼容旧版本的实现方案(Java 7及以下)
如果项目需兼容低版本Java,可优化原有Calendar逻辑:
import java.util.Calendar import java.util.Locale import java.text.SimpleDateFormat object DateTimeUtils { private val dateFormatter = SimpleDateFormat("dd MMMM, yyyy", Locale.getDefault()) // 同步锁解决SimpleDateFormat线程安全问题 private val formatterLock = Any() fun getDateLabel(timestamp: Long): String { // 重置目标时间的时分秒,只保留日期起始点 val targetCalendar = Calendar.getInstance().apply { timeInMillis = timestamp set(Calendar.HOUR_OF_DAY, 0) set(Calendar.MINUTE, 0) set(Calendar.SECOND, 0) set(Calendar.MILLISECOND, 0) } // 生成今日的起始时间 val todayCalendar = Calendar.getInstance().apply { set(Calendar.HOUR_OF_DAY, 0) set(Calendar.MINUTE, 0) set(Calendar.SECOND, 0) set(Calendar.MILLISECOND, 0) } // 生成昨日的起始时间 val yesterdayCalendar = Calendar.getInstance().apply { timeInMillis = todayCalendar.timeInMillis - 86400000 set(Calendar.HOUR_OF_DAY, 0) set(Calendar.MINUTE, 0) set(Calendar.SECOND, 0) set(Calendar.MILLISECOND, 0) } return when (targetCalendar.timeInMillis) { todayCalendar.timeInMillis -> "今日" yesterdayCalendar.timeInMillis -> "昨日" else -> synchronized(formatterLock) { dateFormatter.format(timestamp) } } } }
关键修改点
- 统一日期起始点:将所有时间的时分秒重置为0,确保比较的是同一天的起始时刻,解决原代码精确毫秒匹配的问题。
- 线程安全处理:给
SimpleDateFormat的格式化操作加同步锁,避免多线程环境下的异常。 - 逻辑修正:正确计算昨日的起始时间,实现对昨日任意时刻的识别。
内容的提问来源于stack exchange,提问作者Yug Mewada
相关产品推荐
相关产品推荐

