Java 8日期时间API详解:LocalDate、LocalTime、LocalDateTime及ZonedDateTime的使用指南

Java 8 中,java.time 包被引入作为全新的日期时间 API,旨在解决 Java 中原有日期时间处理的许多缺陷。新的 API 包含了一些非常实用的类,如 LocalDateLocalTimeLocalDateTimeZonedDateTime 等,这些类都是不可变的,并且更加符合 ISO 标准,因此在使用时更加简洁、安全和清晰。不可变的(Immutable)意味着一旦创建了一个对象,它的状态(数据)就不能再被改变。换句话说,对象的字段(属性)在创建后不能被修改。如果你试图修改它,就会得到一个新的对象,而不是修改原有的对象。同时,不可变对象因为其状态不能改变,所以可以在多个线程间共享而无需同步,避免了多线程环境中的并发问题。

1. LocalDate

LocalDate 是 Java 8 引入的日期类,用于表示没有时区的日期(年-月-日),例如:2025-03-08。它仅包含年月日信息,适合表示没有时区或时刻的日期信息。

常用方法

  • LocalDate.now():获取当前日期。
  • LocalDate.of(int year, int month, int dayOfMonth):创建一个指定日期的 LocalDate
  • plusDays(long daysToAdd):增加指定天数,返回新的 LocalDate
  • minusDays(long daysToSubtract):减少指定天数,返回新的 LocalDate
  • isBefore(LocalDate other):判断当前日期是否在指定日期之前。
  • isAfter(LocalDate other):判断当前日期是否在指定日期之后。
  • import java.time.LocalDate;
    
    public class LocalDateExample {
        public static void main(String[] args) {
            // 获取当前日期
            LocalDate currentDate = LocalDate.now();
            System.out.println("Current Date: " + currentDate);  // 输出:当前日期
    
            // 创建指定日期
            LocalDate specificDate = LocalDate.of(2025, 3, 8);
            System.out.println("Specific Date: " + specificDate);  // 输出:2025-03-08
    
            // 增加天数
            LocalDate nextWeek = currentDate.plusDays(7);
            System.out.println("Next Week: " + nextWeek);
    
            // 减少天数
            LocalDate lastWeek = currentDate.minusDays(7);
            System.out.println("Last Week: " + lastWeek);
    
            // 判断日期
            boolean isBefore = currentDate.isBefore(specificDate);
            System.out.println("Is Current Date Before Specific Date? " + isBefore);
        }
    }
    

    2. LocalTime

    LocalTime 用于表示不带日期和时区的时间(小时-分钟-秒)。它可以表示一天中的某个时刻,但不包括日期信息。

    常用方法

  • LocalTime.now():获取当前时间。
  • LocalTime.of(int hour, int minute):创建指定小时和分钟的 LocalTime
  • plusHours(long hoursToAdd):增加指定小时数,返回新的 LocalTime
  • minusMinutes(long minutesToSubtract):减少指定分钟数,返回新的 LocalTime
  • isBefore(LocalTime other):判断当前时间是否在指定时间之前。
  • isAfter(LocalTime other):判断当前时间是否在指定时间之后。
  • import java.time.LocalTime;
    
    public class LocalTimeExample {
        public static void main(String[] args) {
            // 获取当前时间
            LocalTime currentTime = LocalTime.now();
            System.out.println("Current Time: " + currentTime);  // 输出:当前时间
    
            // 创建指定时间
            LocalTime specificTime = LocalTime.of(14, 30);  // 14:30
            System.out.println("Specific Time: " + specificTime);
    
            // 增加小时
            LocalTime nextHour = currentTime.plusHours(1);
            System.out.println("Next Hour: " + nextHour);
    
            // 减少分钟
            LocalTime earlierTime = currentTime.minusMinutes(15);
            System.out.println("Earlier Time: " + earlierTime);
    
            // 判断时间
            boolean isBefore = currentTime.isBefore(specificTime);
            System.out.println("Is Current Time Before Specific Time? " + isBefore);
        }
    }
    

    3. LocalDateTime

    LocalDateTimeLocalDateLocalTime 的组合,它表示没有时区的日期和时间(年-月-日 小时:分钟:秒)。通常用于表示一个不带时区的时间点。

    常用方法

  • LocalDateTime.now():获取当前日期和时间。
  • LocalDateTime.of(LocalDate date, LocalTime time):根据日期和时间创建 LocalDateTime
  • plusDays(long daysToAdd):增加指定天数,返回新的 LocalDateTime
  • minusHours(long hoursToSubtract):减少指定小时数,返回新的 LocalDateTime
  •  

    import java.time.LocalDateTime;
    
    public class LocalDateTimeExample {
        public static void main(String[] args) {
            // 获取当前日期时间
            LocalDateTime currentDateTime = LocalDateTime.now();
            System.out.println("Current DateTime: " + currentDateTime);
    
            // 创建指定日期时间
            LocalDateTime specificDateTime = LocalDateTime.of(2025, 3, 8, 14, 30);
            System.out.println("Specific DateTime: " + specificDateTime);
    
            // 增加天数
            LocalDateTime nextWeek = currentDateTime.plusDays(7);
            System.out.println("Next Week DateTime: " + nextWeek);
    
            // 减少小时
            LocalDateTime earlierTime = currentDateTime.minusHours(5);
            System.out.println("Earlier DateTime: " + earlierTime);
        }
    }
    

    4. 与 Instant 类结合使用

    如果需要获取 UTC 时区的时间戳,可以使用 Instant 类,它表示一个时间线上的点,通常用于表示“机器时间”。

    import java.time.Instant;
    
    public class InstantExample {
        public static void main(String[] args) {
            // 获取当前 UTC 时间戳
            Instant now = Instant.now();
            System.out.println("Current Instant: " + now);
    
            // 转换为秒数
            long seconds = now.getEpochSecond();
            System.out.println("Epoch Second: " + seconds);
        }
    }
    

    5. DurationPeriod

  • Duration 用于表示两个时间点之间的 时间差(例如:秒、分钟、小时等)。
  • Period 用于表示两个日期之间的 日期差(例如:天、月、年)。
  • import java.time.Duration;
    import java.time.LocalTime;
    
    public class DurationExample {
        public static void main(String[] args) {
            LocalTime startTime = LocalTime.of(14, 30);
            LocalTime endTime = LocalTime.of(16, 45);
            
            Duration duration = Duration.between(startTime, endTime);
            System.out.println("Duration: " + duration.toMinutes() + " minutes");
        }
    }
    

    6. 不记录时区类总结

  • LocalDate:表示无时区的日期(年月日)。
  • LocalTime:表示无时区的时间(小时:分钟:秒)。
  • LocalDateTime:表示无时区的日期和时间(年月日 小时:分钟:秒)。
  • Instant:表示 UTC 时间戳,常用于机器时间。
  • Duration:表示时间间隔,通常用来计算时间差。
  • Period:表示日期间隔,通常用来计算日期差。
  • 这些新 API 不仅简洁清晰,而且避免了老旧的 DateCalendar 类的许多问题,使得日期和时间的操作更加直观和易于理解。

    7.带时区的日期时间存储

    如果你需要存储 带时区的日期和时间,在 Java 8 中应该使用 ZonedDateTime 类。它不仅包含了日期和时间信息(如年、月、日、时、分、秒),还包含了时区信息,能够处理不同地区的时间转换问题。

    ZonedDateTime

    ZonedDateTime 表示带有时区的完整日期时间,可以处理时区相关的操作,比如转换不同地区的时间、处理夏令时等问题。

    常用方法

  • ZonedDateTime.now():获取当前日期和时间,默认使用系统时区。
  • ZonedDateTime.of():创建指定时区的日期时间。
  • withZoneSameInstant():将当前日期时间转换为指定时区的同一时刻。
  • toLocalDateTime():获取不带时区的 LocalDateTime
  • import java.time.ZoneId;
    import java.time.ZonedDateTime;
    
    public class ZonedDateTimeExample {
        public static void main(String[] args) {
            // 获取当前时区的日期时间
            ZonedDateTime now = ZonedDateTime.now();
            System.out.println("Current DateTime with Timezone: " + now);
    
            // 创建特定时区的日期时间
            ZonedDateTime specificDateTime = ZonedDateTime.of(2025, 3, 8, 14, 30, 0, 0, ZoneId.of("Asia/Tokyo"));
            System.out.println("Specific DateTime in Asia/Tokyo: " + specificDateTime);
    
            // 将当前时区的时间转换成另一个时区(例如 UTC)
            ZonedDateTime utcDateTime = now.withZoneSameInstant(ZoneId.of("UTC"));
            System.out.println("UTC DateTime: " + utcDateTime);
    
            // 获取不带时区的 LocalDateTime
            System.out.println("Local DateTime: " + now.toLocalDateTime());
        }
    }
    

    关键点

    1. 时区支持ZonedDateTime 使用 ZoneId 来指定时区(如 Asia/TokyoUTC 等),并能够在不同时区之间进行转换。
    2. 转换时区:通过 withZoneSameInstant() 方法可以将一个 ZonedDateTime 转换为另一个时区的相同时间点(即将时区调整为指定时区,但保持同一瞬间的时间)。
    3. 夏令时处理ZonedDateTime 自动处理夏令时(DST)的问题,不同的时区可能会有不同的时间规则。

    ZonedDateTime 的使用场景

  • 跨时区操作:需要处理跨时区的日期和时间时,例如,记录和显示全球用户的事件时间。
  • 时区转换:当需要根据用户所在的时区进行日期时间显示,或者将日期时间从一个时区转换到另一个时区时。
  • 时间记录:对于需要精确记录时间并附带时区信息的系统(如日志、金融交易等)。
  • 其他相关类

  • OffsetDateTime:类似于 ZonedDateTime,但 OffsetDateTime 只包含时区偏移量(如 +02:00)而不包含完整的时区信息(如 Asia/Tokyo)。
  • Instant:表示时间线上的一个点,通常与时区无关,但可以与 ZonedDateTimeOffsetDateTime 一起使用来表示带时区的时间。
  • 带时区日期时间类总结

  • ZonedDateTime 是最适合存储带时区的日期和时间的类,提供了时区转换、夏令时处理等功能,是现代 Java 日期时间处理中的首选。
  • 如果仅需要时区偏移信息,而不关心具体时区名称,可以使用 OffsetDateTime
  • 作者:新停浊酒杯

    物联沃分享整理
    物联沃-IOTWORD物联网 » Java 8日期时间API详解:LocalDate、LocalTime、LocalDateTime及ZonedDateTime的使用指南

    发表回复