Java8的LocalDateTime使用技巧分享

前言

java的Date类在早期版本中确实存在多个问题,主要表现在以下几个方面:

  1. 设计不清晰
    Date类同时包含了日期和时间信息,并且它的构造函数允许创建一个没有时区的对象,但实际上存储的是格林威治标准时间(UTC)的毫秒数。
  2. 可读性差
    Date对象默认的toString()方法返回的是本地时区下的日期/时间字符串,这导致在多线程或多时区环境中可能产生混淆。若要获得特定格式的日期时间字符串,通常需要使用SimpleDateFormat类进行格式化,而SimpleDateFormat是非线程安全的,易引发并发问题。
  3. 不符合日期时间处理的最佳实践
    无法明确区分日期、时间和日期时间概念。没有提供对ISO-8601标准的良好支持,以及对日期和时间组件的便捷操作。
  4. 与日历API耦合度高
    早期版本的Java日期时间处理高度依赖于Calendar类,而Calendar类同样具有可读性差、不易理解和使用的缺点。

为了解决这些问题,Java 8引入了新的日期和时间API,包括LocalDateTime、Instant、DateTimeFormatter等类。这些新类不仅解决了Date类存在的问题,还提供了更多功能和更好的性能。

format

format() 方法用于将 LocalDateTime 对象格式化成字符串,其语法如下:

public String format(DateTimeFormatter formatter)

其中,formatter 表示日期时间格式化对象。
例如,以下代码将一个 LocalDateTime 对象格式化成 “yyyy-MM-dd HH:mm:ss” 格式的字符串:

LocalDateTime dateTime = LocalDateTime.of(2024, 01, 03, 14, 30, 0, 0);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String strDate = dateTime.format(formatter);

时间加减

加减语法很简单,加plus,减为minus。举例:

LocalDateTime now = LocalDateTime.now();
LocalDateTime tomorrow = now.plusDays(1); // 加一天
LocalDateTime yesterday = now.minusDays(1); // 减一天
LocalDateTime nextMonth = now.plusMonths(1); // 加一个月(不考虑天数)
LocalDateTime lastMonth = now.minusMonths(1); // 减一个月(不考虑天数)
LocalDateTime lastMinute = now.minusMinutes(10); // 减一个月(不考虑天数)
System.out.println("现在:" + now);
System.out.println("明天:" + tomorrow);
System.out.println("昨天:" + yesterday);
System.out.println("下个月:" + nextMonth);
System.out.println("上个月:" + lastMonth);
System.out.println("减去10分钟:" + lastMinute);

Duration

Java 8中的Duration类表示两个时间点之间的持续时间,例如两个日期或时间戳之间的差异。它提供了一些方法来计算持续时间的长度,如获取天数、小时数、分钟数和秒数等。
Duration类是java.time包中的一部分,它是不可变的,因此可以在多线程环境中安全地使用。它提供了许多有用的方法,如:

  • toDays():返回持续时间的天数部分。
  • toHours():返回持续时间的小时数部分。
  • toMinutes():返回持续时间的分钟数部分。
  • toSeconds():返回持续时间的秒数部分。
  • toMillis():返回持续时间的毫秒数部分。
  • parse(): 从字符串中获取Duration,比如PT10H等于10分钟
 LocalDateTime start = LocalDateTime.of(2024, 1, 1, 0, 0);
 LocalDateTime end = LocalDateTime.of(2024, 1, 3, 0, 0);
 Duration duration = Duration.between(start, end);
 Duration pt10H = Duration.parse("-PT10H");
 System.out.println(pt10H.toMinutes());
 System.out.println("间隔时间为:"
         + duration.toDays() + "天"
         + duration.toHours() + "小时"
         + duration.toMinutes() + "分钟");

with

with方法可以理解为替换操作,比如替换小时:

 LocalDateTime end = LocalDateTime.of(2024, 1, 3, 0, 0);
 System.out.println(end.withHour(2)); //2024-01-03T02:00

替换为当月第一天:

 LocalDateTime end = LocalDateTime.of(2024, 1, 3, 0, 0);
 System.out.println(end.withDayOfMonth(1)); //2024-01-01T02:00

转为时间戳

需要借助系统默认时区的ZonedDateTime对象,ZoneId.systemDefault()表示获取系统默认的时区:

 LocalDateTime end = LocalDateTime.of(2024, 1, 3, 0, 0);
 ZonedDateTime zonedDateTime = end.atZone(ZoneId.systemDefault());
 Instant instant = zonedDateTime.toInstant();
 System.out.println(instant.toEpochMilli());

当然,我们知道中国地区时间为utc+8小时,所以我们也可以直接指定,代码:

 LocalDateTime end = LocalDateTime.of(2024, 1, 3, 0, 0);
 System.out.println(end.toInstant(ZoneOffset.of("+08:00")).toEpochMilli());

比较大小

compareTo() 方法用于比较两个 LocalDateTime 对象的顺序大小,如果当前对象在参数对象之前,则返回负数,如果当前对象在参数对象之后,则返回正数,如果两个对象相等,则返回 0。
例如,以下代码比较两个 LocalDateTime 对象的顺序:

LocalDateTime dateTime1 = LocalDateTime.of(2023, 01, 01, 14, 30, 0, 0);
LocalDateTime dateTime2 = LocalDateTime.of(2024, 01, 01, 14, 30, 0, 0);
int result = dateTime1.compareTo(dateTime2);  // -1

总结

本文从 LocalDateTime 类的创建、转换、格式化与解析、计算与比较以及其他操作几个方面详细介绍了 LocalDateTime 类在 Java 8 中的使用。掌握 LocalDateTime 类的使用可以大大提高日期时间处理效率和质量,理解在不通过引用其他三方jar的情况下JAVA自身就有很好的操作方式,希望本文对读者有所帮助。

你可能感兴趣的:(java)