不推荐使用Date日期和Calendar日期

发布时间 2023-05-29 15:59:09作者: 阳阳天天开心

很神奇,为什么java中不推荐使用Date与Calendar日期了,很多时候初学者在刚学习java时,大部分使用的日期都是Date与Calendar,只有及少数个别使用的LocalDateTime日期

  Date 与 Calendar存在的共性问题

  • 毫秒值与日期直接转换麻烦和繁琐,然后通过毫秒值来计算时间的差额步骤较多,并且还可能存在误差

  • 再有一个就是线程问题,我们都知道在创建一个Date日期变量时,它的格式不是我们能看懂的日期格式,这时候就需要使用SimpleDateFormat了,然后

    这就引发了一个问题,这个类的线程是不安全的(在做生产总览的时候,需要大量使用日期类,当时每个类我都创建了一个SimpleDateFormat,想着有点

    浪费内存空间了,然后在service层最上面定义了一个静态的日期格式类,接着就引发了一个问题,页面报错,然后查询资料才知道,多个线程

    对同一个类操作造成了格式化错误,甚至有可能引发内存泄漏,可能导致内存泄漏问题,占用过多的内存资源)

使用日期推荐LocalDate、LocalTime、LocalDateTime这三个日期类

1. LocalDate类是一个不可变的日期时间对象,表示日期,通常被视为年月日

 // 获取当前年、月、日
LocalDate today = LocalDate.now();
// 获取年
int year = today.getYear();
// 获取月
int month = today.getMonthValue();
// 获取天
int day = today.getDayOfMonth();
// 获取毫秒值
LocalDateTime startOfDay = localDate.atStartOfDay();
long millisecondsFromDate = startOfDay.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();

2. LocalTime类是一个不可变的日期时间对象,代表一个时间,通常被看作小时-秒,时间表示为纳秒精度

 // 获取当前年、月、日
LocalTime time = LocalTime.now();
int hour = time.getHour(); // 获取小时
int minute = time.getMinute(); // 获取分钟
int second = time.getSecond(); // 获取秒
int nano = time.getNano(); // 获取纳秒

3. LocalDateTime是一个不可变的日期时间对象,代表日期时间,通常被视为年-月-日- 时-分-秒

LocalDateTime dateTime = LocalDateTime.now();
int year = dateTime.getYear(); // 获取年份
int month = dateTime.getMonthValue(); // 获取月份 (1-12)
int dayOfMonth = dateTime.getDayOfMonth(); // 获取月份中的天数
int hour = dateTime.getHour(); // 获取小时
int minute = dateTime.getMinute(); // 获取分钟
int second = dateTime.getSecond(); // 获取秒
int nano = dateTime.getNano(); // 获取纳秒

// 获取毫秒值
// 需要将LocalDateTime变量转换为ZoneDateTime对象
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
Instant instant = zonedDateTime.toInstant();
long milliseconds = instant.toEpochMilli();

// 日期格式化
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String dayTime = dateTimeFormatter.format(dateTime);
方法名 说明
public LocalDateTime plusYears(long years) 添加或者减去年
public LocalDateTime plusMonths(long months) 添加或者减去月
public LocalDateTime plusDays(long months) 添加或者减去日
public LocalDateTime plusHours(long hours) 添加或者减去时
public LocalDateTime plusMinutes(long minutes) 添加或者减去分
public LocalDateTime plusSeconds(long seconds) 添加或者减去秒
public LocalDateTime plusWeeks(long weeks) 添加或者减去周

这里要注意!!根据业务需求使用不同的日期,如果前端传值为年-月-日,而后端使用了LocalDateTime日期会报无法转换的问题,这是因为LocalDateTime底层是被final修饰了无法更改,它的格式只能是年-月-日 时:分:秒,所以要使用对应的日期格式

使用示例:(获取一天中的24小时,然后使用String的format方法截取)

// 创建 DateTimeFormatter 对象,指定时间格式为 "yyyy-MM-dd HH:mm:ss"
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

LocalDate date = LocalDate.parse(dayTime);

// 获取当前时间,小时取整,分和秒设为0 使用with将日期设定为指定日期,然后分与秒为0
LocalDateTime now = LocalDateTime.now().with(date).withMinute(0).withSecond(0);


for(int j = 0; j < 24; j++){
    TbProductionLineStopDTO tbProductionLineStopDTO = new TbProductionLineStopDTO();
    if(j == 23){
        // 设置当前日期小时为23,并且格式化
        startTime = now.withHour(23).format(formatter);
        // 天数减1,并且小时设置为0
        endTime = now.plusDays(1).withHour(0).format(formatter);

        starHour = String.format("%02d", j);
        endHour = String.format("%02d", 00);
    }else{
        // 创建 startTime 和 endTime 变量
        startTime = now.withHour(j).format(formatter);
        endTime = now.withHour(j+1).format(formatter);

        starHour = String.format("%02d", j);
        endHour = String.format("%02d", j+1);
    }

    Integer productionCount = realTimeMapper.queryTbProductPassrecord(startTime,endTime,lineCode);
    if(productionCount == null){
        productionCount = 0;
    }
    String time = starHour + "-" + endHour;

    tbProductionLineStopDTO.setLineCount(productionCount);
    tbProductionLineStopDTO.setTimeHour(time);
    tbProductionLineStopDTOList.add(tbProductionLineStopDTO);
}