Java时间详解:常见时间类、LocalDateTime和Date区别转换、时间计算和格式化、SimpleDateFormat和DateTimeFormatter区别、ISO常见格式


常见时间类

常见时间

  • java.util.Date 类允许创建和操纵表示特定瞬间的时间对象。
  • java.time.LocalDatejava.time.LocalDateTime 类允许操作日期和时间,但不考虑时区。

时间处理类

  • java.time.ZonedDateTime 类允许操作日期和时间,同时考虑到时区的影响。
  • java.time.Duration 类允许计算两个时刻之间的持续时间。
  • java.time.Period 类允许计算两个日期之间的期间。
  • java.time.format.DateTimeFormatter 类允许将日期和时间格式化为人类可读的形式。

LocalDateTime跟Date

区别

1.不可变性:LocalDateTime不可变的类型,一旦创建后,其值是不可变的。而Date可变的类型,可以通过方法修改其值。
2.线程安全性:LocalDateTime线程安全的,多个线程可以同时访问和操作不同的LocalDateTime实例。而Date非线程安全的,如果多个线程同时访问和修改同一个Date实例,可能会导致不可预期的结果。
3.时间精度:LocalDateTime提供了纳秒级别的时间精度,可以表示更加精确的时间。而Date只能表示毫秒级别的时间精度
4.时区处理:LocalDateTime默认不包含时区信息,表示的是本地日期和时间。而Date包含时区信息,它的实际值会受到系统默认时区的影响。

两者对象值是否可变区别案例

在 Java 中,LocalDateTime 是不可变的,而 Date 是可变的。这意味着一旦创建了一个 LocalDateTime 对象,就不能更改其值。相比之下,可以更改 Date 对象的值。
以下是一个示例,说明 LocalDateTime 是不可变的:

LocalDateTime ldt = LocalDateTime.now();
ldt.withHour(2); // 这个方法会返回一个新的 LocalDateTime 对象,而不会更改原来的对象

在这个例子中,withHour(int hour) 方法返回一个新的 LocalDateTime 对象,其中小时设置为 2。然而,原始的 LocalDateTime 对象并没有改变。
相反,对于 Date 对象来说,可以直接更改其值:

Date date = new Date();
date.setYear(2023); // 这个方法会更改原有的 Date 对象

在这个例子中,setYear(int year) 方法会更改原始的 Date 对象,使其变为2023年。

总结

LocalDate不可变类时间对象优点:

  • 它们不会受到意外更改的影响。当您将不可变对象传递给函数或存储在集合中时,可以确信它不会被更改。
  • 不可变对象可以共享,而不会引发并发问题。这是因为它们没有状态,所以不会出现多个线程同时访问并更改同一对象的情况。
  • 不可变对象更容易测试和调试,因为它们的行为始终一致。

两者相互转换

通过LocalDateTime的atZone()方法和Date的toInstant()方法进行转换。
在 Java 中,您可以使用 LocalDateTimeatZone() 方法和 DatetoInstant() 方法来将 LocalDateTime 对象转换为 Date 对象,反之亦然。以下是一些示例:
LocalDateTime 转换为 Date

// 创建一个 LocalDatetime 对象
LocalDateTime ldt = LocalDateTime.of(2023, Month.JANUARY, 1, 10, 30);

// 使用 atZone() 方法将其转换为 ZonedDateTime
ZonedDateTime zdt = ldt.atZone(ZoneId.of("UTC"));

// 将 ZonedDateTime 转换为 Instant
Instant instant = zdt.toInstant();

// 将 Instant 转换为 Date
Date date = Date.from(instant);

Date 转换为 LocalDateTime

// 创建一个 Date 对象
Date date = new Date();

// 将 Date 转换为 Instant
Instant instant = date.toInstant();

// 将 Instant 转换为 ZonedDateTime
ZonedDateTime zdt = instant.atZone(ZoneId.of("UTC"));

// 将 ZonedDateTime 转换为 LocalDateTime
LocalDateTime ldt = zdt.toLocalDateTime();

请注意,在进行此类转换时,必须指定一个时区。否则,无法确定 LocalDateTime 的确切时间点。在上述示例中,我们使用 “UTC” 作为时区。如果您想使用其他时区,请替换 ZoneId.of("UTC") 中的 “UTC”。


时间处理

在 Java 中,可以使用 LocalDateTime 对象进行日期和时间的相减操作。由于它们都是数值对象,所以可以直接相减得到时间差值。另外,它们还具有 equals() 和 compareTo() 方法,可以比较两个 LocalDateTime 对象是否相同或一个比另一个大。

LocalDateTime 对象之间的持续时间案例

下面是一个简单的示例:

LocalDateTime start = LocalDateTime.now();
Thread.sleep(5000); // 约等于 5 秒延迟
LocalDateTime end = LocalDateTime.now();

Duration duration = Duration.between(start,end);

long seconds = duration.getSeconds();

在这个示例中,Duration.between() 方法会返回两个 LocalDateTime 对象之间的持续时间。这将会得到一个 Duration 对象,其中包含了毫秒数,可以进一步提取出秒数。如果你想知道整分钟或整小时的数量,请用 seconds 或 minutes 方法,分别是 duration.getSeconds()duration.toMinutes()。请注意,Duration 的 API 也可用来提取其他时间单位,如分钟、小时和天数等。

请注意,由于 LocalDateTime 不包含时区信息,在比较时间时最好确保时区一致,否则会出现错误。如果你需要考虑时区,请使用 ZonedDateTime 对象。

ZonedDateTime zstart = ZonedDateTime.now(); // 代表本地时区
Thread.sleep(5000);
ZonedDateTime zend = ZonedDateTime.now();

Duration duration = Duration.between(zstart, zend);
long seconds = duration.getSeconds();

上述代码就可以得到相差的时间,以秒为单位。你还可以使用 Duration 来获取其他时间单位,例如Duration常用方法:

Duration常用方法

Duration 类是 Java 时间日期包中的一个类,表示一个时间段。以下是一些常用的 Duration 类方法:

  • between(): 获取两个日期或时间之间的时间差
Duration d = Duration.between(date1, date2);
  • toDays(): 把当前 Duration 对象转为天数
long days = d.toDays();
  • toHours(): 把当前 Duration 对象转为小时数
long hours = d.toHours();
  • toMinutes(): 把当前 Duration 对象转为分钟数
long minutes = d.toMinutes();
  • toSeconds(): 把当前 Duration 对象转为秒数
long seconds = d.getSeconds();
  • toMillis(): 把当前 Duration 对象转为毫秒数
long millis = d.toMillis();
  • plus(long amountToAdd): 添加一个数值到当前 Duration 对象,使得对象值增加相应的时间长度
d.plus(amountToAdd);
  • minus(long amountToSubtract): 从当前 Duration 对象中减去一个值,使得对象值减少相应的时间长度
d.minus(amountToSubtract);
  • abs(): 返回一个新的 Duration 对象,它的值等于原对象的绝对值
Duration absolute = d.abs();

Date对象持续时间处理

Duration 类处理 Date 类型的对象。可以先将 Date 对象转化为 LocalDateTime 对象,然后再进行减法操作:

// 创建两个 Date 对象
Date date1 = new Date();
Thread.sleep(5 * 1000); // 约等于五秒钟延迟
Date date2 = new Date();

// 转换为 LocalDateTime 对象
LocalDateTime ldt1 = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime ldt2 = date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();

// 计算时间差
Duration d = Duration.between(ldt1, ldt2);

// 打印结果
System.out.println(d.getSeconds()); // 输出大约等于 5 的结果

上述代码将计算两个 Date 对象之间的持续时间,并打印出来。如果你想知道整分钟或整小时的数量,请用 seconds 或 minutes 方法,分别是 d.getSeconds()d.toMinutes()


LocalDateTime方法:compareTo时间比较

在Java中,可以使用LocalDateTime重写Object类的compareTo()方法进行LocalDateTime对象之间的时间比较。该方法返回一个整数值(正整数、零或负整数)来表示比较结果。

import java.time.LocalDateTime;
 
public class LocalDateTimeCompare {
    
    
    public static void main(String[] args) {
    
    
        LocalDateTime dateTime1 = LocalDateTime.of(2023, 6, 7, 10, 30);
        LocalDateTime dateTime2 = LocalDateTime.of(2023, 6, 8, 10, 30);
 
        int result = dateTime1.compareTo(dateTime2);
 
        if (result < 0) {
    
    
        	//负整数调用时间小
            System.out.println("dateTime1 is before dateTime2");
        } else if (result > 0) {
    
    
        	//正整数调用时间大
            System.out.println("dateTime1 is after dateTime2");
        } else {
    
    
        	//0两个时间相等
            System.out.println("dateTime1 is equal to dateTime2");
        }
    }
}

LocalDateTime时间格式化

LocalDateTime now = LocalDateTime.now();
//String类型格式化后的时间
String format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(now);
//LocalDateTime类型格式化后的时间
LocalDateTime formatted = LocalDateTime.parse(format, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

System.out.println(formatted);

补充SimpleDateFormat和DateTimeFormatter区别

SimpleDateFormat线程不安全,DateTimeFormatter线程安全。
SimpleDateFormat 类更适合处理 Date 类型,DateTimeFormatter更适合处理LocalDateTime或LocalDate,但是其也可以间接格式化Date。

个人建议使用LocalDate和LocalDateTime比较方便和安全。

DateTimeFormatter间接格式化Date案例:

DateTimeFormatter 类主要处理的是 TemporalAccessor 对象,包括 LocalDateTime,
LocalDate, LocalTime, YearMonth, MonthDayOffsetDateTime
类型。不过也可以间接格式化 Date 对象。请参考以下代码示例:

Date date = new Date(); TemporalAccessor temporal =
TemporalAccessor.from(date.toInstant());

String format = DateTimeFormatter.ISO_LOCAL_DATE.format(temporal);
System.out.println(format); 

上述代码中 TemporalAccessor 接口可以接收 Date 对象,并且把它们转换成 LocalDateTime对象,然后再使用 DateTimeFormatter 格式化它。请注意,TemporalAccessor还有其他一些构造方法和工厂方法可以用于从日期和时间转换,以及更多选项。更多信息请参阅 Java 文档中关于TemporalAccessor 的文档。

补充:ISO常见格式

这些格式和对应的时间范围取决于你的需求,请根据实际情况选择合适的格式。

常见ISO格式有:

  1. ISO_LOCAL_DATE:这种格式只有日期部分,不包含时间和时区,只保留至秒。

  2. ISO_LOCAL_TIME:这种格式只有时间部分,不包含日期和时区,只保留至秒。

  3. ISO_OFFSET_DATE_TIME:这种格式包含完整的日期和时间,以及时区。

  4. INSTANT_SECONDS:这种格式包含完整日期、时间和时间戳(精确到秒)。

  5. DATE_TIME_WITH_ZONE:这种格式只包含日期和时间,并且保留时区信息。


最后

可以使用这些类来实现各种时间相关的功能,包括计算两个时刻之间的差值、比较日期的顺序、添加或减去时间段以及格式化日期和时间等。为了更方便地处理日期和时间,请考虑使用 Java 8 及更高版本,因为它们引入了许多新的改进 API 来解决这些问题。

猜你喜欢

转载自blog.csdn.net/qq_58647634/article/details/134600773