hutool工具类的DateUtil和LocalDateTimeUtil
目录
java中的Date和LocalDateTime的区别
1.1 设计理念
1.2 功能和特性
1.3 线程安全性
1.4 使用场景
2.1 MySQL 的 DATETIME 类型
2.2 映射关系
hutool工具类的DateUtil和LocalDatetimeUtil工具类
DateUtil使用
LocalDatetimeUtil使用
java中的Date和LocalDateTime的区别
1.1 设计理念
-
java.time.LocalDateTime
-
是 Java 8 引入的
java.time
包中的一个类,属于新的日期时间 API(JSR-310)。 -
它是不可变的、线程安全的,并且专注于本地日期和时间(不包含时区信息)。
-
设计上更加灵活,提供了丰富的日期时间操作方法,如日期加减、格式化等。
-
-
java.util.Date
-
是 Java 早期的日期时间类,存在于 Java 1.0 中。
-
它是一个可变类,线程不安全。
-
同时包含日期和时间信息,但功能较为有限,且存在一些设计上的缺陷(如月份从 0 开始)。
-
1.2 功能和特性
-
LocalDateTime
-
不包含时区信息,只表示本地日期和时间。
-
提供了丰富的日期时间操作方法,例如
plusDays()
、minusHours()
、format()
等。 -
可以与
java.time.ZoneId
结合使用,转换为带时区的日期时间(如ZonedDateTime
)。 -
支持 ISO-8601 标准日期时间格式。
-
-
Date
-
包含自 1970-01-01 00:00:00 GMT 以来的毫秒数(时间戳)。
-
提供的方法较少,且存在一些易用性问题(如月份从 0 开始)。
-
可以通过
SimpleDateFormat
进行格式化,但SimpleDateFormat
是线程不安全的。
-
1.3 线程安全性
-
LocalDateTime
:不可变,线程安全。 -
Date
:可变,线程不安全。
1.4 使用场景
-
LocalDateTime
:推荐在需要精确日期时间操作、格式化或需要与 Java 8 及以上版本的新日期时间 API 集成的场景中使用。 -
Date
:在一些旧的 Java 应用或需要与旧版本 Java 代码兼容的场景中仍然会用到,但不推荐在新项目中使用。
2.1 MySQL 的 DATETIME
类型
-
DATETIME
是 MySQL 中用于存储日期和时间的字段类型,格式为YYYY-MM-DD HH:MM:SS
。 -
它不包含时区信息,只表示本地日期和时间。
2.2 映射关系
-
LocalDateTime
-
LocalDateTime
与 MySQL 的DATETIME
类型字段天然匹配,因为它们都表示本地日期和时间,且不包含时区信息。 -
在使用 JPA、Hibernate 或 MyBatis 等框架时,
LocalDateTime
可以直接映射到DATETIME
字段。
-
-
Date
-
Date
也可以映射到 MySQL 的DATETIME
类型字段,但需要注意以下几点:-
Date
包含时间戳(毫秒数),在存储到数据库时,通常需要转换为java.sql.Timestamp
或java.sql.Date
。 -
Date
的月份从 0 开始,可能会导致混淆。 -
如果使用
Date
,建议在存储和读取时进行显式的转换。
-
-
@Temporal(TemporalType.TIMESTAMP) // 需要指定时间类型 private Date eventTime; // 映射到 DATETIME
hutool工具类的DateUtil和LocalDatetimeUtil工具类
DateUtil工具类可以操作Date类型数据, LocalDatetimeUtil工具类可以操作 LocalDatetime类型数据。
接收前端的时间参数可以使用@JsonFormat注解指定序列化和反序列化的时间格式
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime estimatedStartTime;
DateUtil使用
传入的时间格式是字符串类型
@GetMapping("count")
@ApiOperation(value = "任务数量查询", notes = "按照当日快递员id列表查询每个快递员的取派件任务数")
@ApiImplicitParams({
@ApiImplicitParam(name = "courierIds", value = "订单id列表", required = true),
@ApiImplicitParam(name = "taskType", value = "任务类型", required = true),
@ApiImplicitParam(name = "date", value = "日期,格式:yyyy-MM-dd 或 yyyyMMdd", required = true)
})
public List<CourierTaskCountDTO> findCountByCourierIds(@RequestParam("courierIds") List<Long> courierIds,
@RequestParam("taskType") PickupDispatchTaskType taskType,
@RequestParam("date") String date) {
return this.pickupDispatchTaskService.findCountByCourierIds(courierIds, taskType, date);
这里可以直接使用DateUtil工具类的parse方法解析这个日期字符串对象,我们进入源码查看,可以发现可以解析四种类型的数据
也可以自定义解析格式
DateTime dateTime = DateUtil.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
可以发现返回类型是hutool工具类的DateTime类型,这个类继承了Date类
这两个方法可以这个时间的0点时间和结束时间
LocalDateTime beginTime = DateUtil.beginOfDay(dateTime).toLocalDateTime(); LocalDateTime endTime = DateUtil.endOfDay(dateTime).toLocalDateTime();
@Override
public List<CourierTaskCountDTO> findCountByCourierIds(List<Long> courierIds, PickupDispatchTaskType pickupDispatchTaskType, String date) {
// TODO day09 查询指定快递员的任务数量
//1. 计算一天的时间的边界 tips: 使用hutool 的 DateUtil
DateTime dateTime = DateUtil.parse(date);
LocalDateTime beginTime = DateUtil.beginOfDay(dateTime).toLocalDateTime();
LocalDateTime endTime = DateUtil.endOfDay(dateTime).toLocalDateTime();
//2. 执行SQL tips: 下面是sql提示 需要写到TaskPickupDispatchMapper中
// SELECT
// COUNT(1) `count`,
// courier_id
// FROM sl_pickup_dispatch_task t
// WHERE
// t.courier_id IN <foreach collection="courierIds" item="courierId" open="(" close=")" separator=",">#{courierId}</foreach>
// AND t.created BETWEEN #{startDateTime} AND #{endDateTime}
// AND t.task_type = #{type}
// GROUP BY courier_id
return taskPickupDispatchMapper.findCountByCourierIds(courierIds, pickupDispatchTaskType.getCode(), beginTime, endTime);
}
解析成功
![]()
LocalDateTime startTime = LocalDateTimeUtil.of(DateUtil.beginOfDay(new Date()));
LocalDateTime endTime = LocalDateTimeUtil.of(DateUtil.endOfDay(new Date()));
/**
* 今日任务分类计数
*
* @param courierId 快递员id
* @param taskType 任务类型,1为取件任务,2为派件任务
* @param status 任务状态,1新任务,2已完成,3已取消
* @param isDeleted 是否逻辑删除
* @return 任务数量
*/
@Override
public Integer todayTasksCount(Long courierId, PickupDispatchTaskType taskType, PickupDispatchTaskStatus status, PickupDispatchTaskIsDeleted isDeleted) {
//构建查询条件
LambdaQueryWrapper<PickupDispatchTaskEntity> queryWrapper = Wrappers.<PickupDispatchTaskEntity>lambdaQuery()
.eq(ObjectUtil.isNotEmpty(courierId), PickupDispatchTaskEntity::getCourierId, courierId)
.eq(ObjectUtil.isNotEmpty(taskType), PickupDispatchTaskEntity::getTaskType, taskType)
.eq(ObjectUtil.isNotEmpty(status), PickupDispatchTaskEntity::getStatus, status)
.eq(ObjectUtil.isNotEmpty(isDeleted), PickupDispatchTaskEntity::getIsDeleted, isDeleted);
//根据任务状态限定查询的日期条件
LocalDateTime startTime = LocalDateTimeUtil.of(DateUtil.beginOfDay(new Date()));
LocalDateTime endTime = LocalDateTimeUtil.of(DateUtil.endOfDay(new Date()));
if (status == null) {
//没有任务状态,查询任务创建时间
queryWrapper.between(PickupDispatchTaskEntity::getCreated, startTime, endTime);
} else if (status == PickupDispatchTaskStatus.NEW) {
//新任务状态,查询预计结束时间
queryWrapper.between(PickupDispatchTaskEntity::getEstimatedEndTime, startTime, endTime);
} else if (status == PickupDispatchTaskStatus.COMPLETED) {
//完成状态,查询实际完成时间
queryWrapper.between(PickupDispatchTaskEntity::getActualEndTime, startTime, endTime);
} else if (status == PickupDispatchTaskStatus.CANCELLED) {
//取消状态,查询取消时间
queryWrapper.between(PickupDispatchTaskEntity::getCancelTime, startTime, endTime);
}
//结果返回integer类型值
return Convert.toInt(super.count(queryWrapper));
}
LocalDatetimeUtil使用
@Override
public List<PickupDispatchTaskDTO> findTodayTaskByCourierId(Long courierId) {
// 1. 构建查询条件
LambdaQueryWrapper<PickupDispatchTaskEntity> wrapper = Wrappers.<PickupDispatchTaskEntity>lambdaQuery()
.eq(PickupDispatchTaskEntity::getCourierId, courierId)
.ge(PickupDispatchTaskEntity::getEstimatedStartTime, LocalDateTimeUtil.beginOfDay(LocalDateTime.now()))
.le(PickupDispatchTaskEntity::getEstimatedStartTime, LocalDateTimeUtil.endOfDay(LocalDateTime.now()))
.eq(PickupDispatchTaskEntity::getIsDeleted, PickupDispatchTaskIsDeleted.NOT_DELETED);
// 1.1 快递员id 等值查询
// 1.2 预计开始时间 大于等于今天的开始时间 今天 00:00:00
// 1.3 预计开始时间 小于等于今天的结束时间 今天 23:59:59
// 1.4 isDeleted 不能是删除状态
// 2. 执行查询
// 3. 将entity集合 转为 DTO集合返回 tips: BeanUtil
List<PickupDispatchTaskEntity> list = super.list(wrapper);
return BeanUtil.copyToList(list, PickupDispatchTaskDTO.class);
}