当前位置: 首页 > news >正文

Java 时间处理:轻松掌握 java.time 包

前言

在 Java 开发中,日期和时间处理一直是令人头疼的问题。传统的 Date​ 和 Calendar​ 类不仅复杂,还充满了线程安全和时区处理的坑。Java 8 引入的 java.time​ 包彻底改变了这一局面,带来了现代化、直观且功能强大的日期时间 API。

本文将带你深入了解 java.time​ 包的核心功能,从基础的 LocalDate​ 和 LocalTime​ 到强大的 Duration​ 和 Period​,再到灵活的 DateTimeFormatter​,让你轻松掌握日期时间处理的最佳实践。

一、关于java.time包

1.1 简介

java.time​ 包是 Java 8 中引入的,用于处理日期和时间的新 API。它旨在克服旧版 java.util.Date​ 和 java.util.Calendar​ 类中的一些缺点,提供更现代、更简洁、线程安全和不可变的日期和时间处理方式。该 API 基于 ISO-8601 标准,并支持更多的时区、日期/时间格式以及各种常见的时间计算需求。

8db441735eb31b8b78b3bc48855dd98

1.2 核心类和接口

  • LocalDate:表示没有时区的日期(年、月、日)。例如,2025年3月28日。
  • LocalTime:表示没有时区的时间(时、分、秒)。例如,14:30:00。
  • LocalDateTime:表示没有时区的日期和时间(年、月、日、时、分、秒)。例如,2025年3月28日 14:30:00。
  • ZonedDateTime:表示带时区的日期和时间。它不仅包含日期和时间信息,还包含时区信息(例如 UTC+08:00)。
  • Instant:表示时间戳(从1970年1月1日0时0分0秒到某一时刻的秒数或毫秒数),通常用于与 Unix 时间戳和其他基于秒的时间戳的交互。
  • Duration:表示时间段,用于表示两个时间点之间的差异,精度为秒和纳秒。
  • Period:表示日期段,用于表示两个日期之间的差异,精度为年、月和日。
  • Month:表示一个月(如 JANUARY、FEBRUARY 等),是枚举类型。
  • DayOfWeek:表示一周中的某一天(如 MONDAY、TUESDAY 等),也是枚举类型。

java.time包目录结构

image

二、核心类

2.1 LocalDate类

简介

LocalDate​ 类是 Java 8 引入的日期和时间 API(java.time 包)的一部分。它表示一个没有时间部分的日期(例如:2025-03-31),适用于处理年、月、日等信息,而不涉及时间、时区等。

LocalDate​ 代表不带时区的日期。

  • 表示不带时区的日期(年-月-日)。
  • 示例:2023-10-01​。

image

LocalDate​ 使用 ISO-8601 标准来处理日期,并将日期表示为 YYYY-MM-DD​ 的格式。ISO-8601日历系统是当今世界大部分地区使用的现代民用日历系统。相当于现在的公历日历体系,其中表示闰年规则永远适用。

方法

常用方法

  • now()​:获取当前日期。
  • of(int year, int month, int dayOfMonth)​:创建指定日期。
  • plusDays(long days)​:增加天数。
  • minusMonths(long months)​:减少月数。
  • getYear()​, getMonth()​, getDayOfMonth()​:获取日期的各个部分。
  • isLeapYear()​:判断是否为闰年。
  • isBefore(LocalDate other)​:判断当前日期是否在指定日期之前。
  • isAfter(LocalDate other)​:判断当前日期是否在指定日期之后。

示例

import java.time.LocalDate;

public class LocalDateExample {
    public static void main(String[] args) {
        // 获取当前日期
        LocalDate today = LocalDate.now();
        System.out.println("今天: " + today);

        // 创建指定日期
        LocalDate specificDate = LocalDate.of(2025, 3, 31);
        System.out.println("指定日期: " + specificDate);

        // 日期操作
        LocalDate tomorrow = today.plusDays(1);
        System.out.println("明天: " + tomorrow);

        LocalDate yesterday = today.minusDays(1);
        System.out.println("昨天: " + yesterday);

        // 判断是否为闰年
        boolean isLeapYear = today.isLeapYear();
        System.out.println("是否为闰年: " + isLeapYear);

        // 日期比较
        boolean isBefore = today.isBefore(specificDate);
        System.out.println("今天是否在指定日期之前? " + isBefore);
    }
}

image

2.2 LocalTime类

简介

  • 表示不带时区的时间(小时:分钟:秒.纳秒)。
  • 示例:15:30:45.123​。

方法

  • 常用方法:

    • now()​:获取当前时间。
    • of(int hour, int minute, int second)​:创建指定时间。
    • plusHours(long hours)​:增加小时数。
    • minusMinutes(long minutes)​:减少分钟数。
    • getHour()​, getMinute()​, getSecond()​:获取时间的各个部分。

示例

import java.time.LocalTime;

public class LocalTimeExample {
    public static void main(String[] args) {
        LocalTime time = LocalTime.now();  // 获取当前时间
        System.out.println(time);  // 输出当前时间,格式如 14:30:00
  
        LocalTime specificTime = LocalTime.of(14, 30);  // 创建特定时间
        System.out.println(specificTime);  // 输出:14:30
    }
}

image

2.3 LocalDateTime类

关于

简介

LocalDateTime​ 是 java.time​ 包中的一个类,用于表示没有时区信息的日期和时间。它结合了 LocalDate​ 和 LocalTime​,可以表示年份、月份、日期、小时、分钟、秒以及纳秒的信息,但不包含时区。LocalDateTime​ 是不可变的,意味着它的实例一旦创建后就不能被修改,因此它是线程安全的。

  • 表示不带时区的日期和时间(年-月-日T小时:分钟:秒.纳秒)。
  • 示例:2023-10-01T15:30:45.123​。

主要特点
  • 无时区LocalDateTime​ 不包含时区信息,仅表示本地日期和时间。
  • 精确到纳秒:提供纳秒级别的精度。
  • 不可变和线程安全:一旦创建,LocalDateTime​ 的值不能改变,因此是线程安全的。

关联类对比
类名描述示例值
LocalDate仅日期(无时间)2023-10-01
LocalTime仅时间(无日期)15:30:45
LocalDateTime日期 + 时间(无时区)2023-10-01T15:30:45
ZonedDateTime日期时间 + 时区2023-10-01T15:30:45+08:00[Asia/Shanghai]
Instant时间戳(基于 UTC)2023-10-01T07:30:45Z

时间带T

LocalDateTime​ 类中,时间表示格式中的 T 是 ISO 8601 标准规定的日期和时间之间的分隔符。

解释:

在 ISO 8601 格式中,日期和时间通常由字母 “T” 分隔。例如:

2025-03-28T14:30:00

在这个示例中:

  • 2025-03-28​ 是日期部分(年-月-日)
  • 14:30:00​ 是时间部分(小时:分钟:秒)

字母 T 用来清楚地标识日期部分和时间部分的分隔,避免歧义。因此,它并不代表任何特殊的含义,而仅仅是作为分隔符来表示日期和时间的结合。

构造方法

LocalDateTime​ 类提供了多种构造方法来创建日期时间实例:

  • LocalDateTime.now()​:获取当前系统的日期和时间(根据默认时区)。
  • LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute)​:创建指定日期和时间的 LocalDateTime​。
  • LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute, int second)​:创建指定日期、时间和秒的 LocalDateTime​。
  • LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond)​:创建指定日期、时间、秒和纳秒的 LocalDateTime​。
  • LocalDateTime.parse(CharSequence text)​:通过字符串解析创建 LocalDateTime​ 对象。

解析字符串(ISO 格式)

LocalDateTime dt = LocalDateTime.parse("2023-10-01T15:30:45");

组合 LocalDate + LocalTime

LocalDateTime dt = LocalDate.now().atTime(LocalTime.of(12, 0));

LocalDate date1 = LocalDate.of(2023, 6, 7);
LocalTime time1 = LocalTime.of(11, 30, 0);
LocalDateTime dateTime1 = LocalDateTime.of(date1, time1);
System.out.println(dateTime1);
//2023-06-07T01:00

old

LocalDateTime startTime, endTime;

在您的代码片段中,声明了两个 LocalDateTime 类型的变量 startTime 和 endTime,但是并没有进行初始化赋值操作,因此它们的值默认为 null。

方法

以下是 LocalDateTime​ 类的常用方法概览:

一、获取当前日期时间
方法名描述
now()获取当前的日期和时间。
now(ZoneId zone)根据指定的时区获取当前日期和时间。
now(Clock clock)根据指定的时钟获取当前日期和时间。
二、创建特定日期时间
方法名描述
of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nano)创建指定日期和时间的 LocalDateTime​ 对象。
of(int year, int month, int dayOfMonth, int hour, int minute, int second)创建指定日期和时间的 LocalDateTime​ 对象(毫秒和纳秒为 0)。
of(int year, int month, int dayOfMonth, int hour, int minute)创建指定日期和时间的 LocalDateTime​ 对象(秒、毫秒和纳秒为 0)。
of(int year, Month month, int dayOfMonth, int hour, int minute, int second, int nano)使用 Month​ 枚举创建指定日期和时间的 LocalDateTime​ 对象。
三、解析和格式化
方法名描述
parse(CharSequence text, DateTimeFormatter formatter)使用指定的格式化程序解析字符串,创建 LocalDateTime​ 对象。
format(DateTimeFormatter formatter)使用指定的格式化程序将 LocalDateTime​ 格式化为字符串。
四、获取日期和时间部分
方法名描述
toLocalDate()获取 LocalDateTime​ 对象的日期部分,返回一个 LocalDate​ 对象。
toLocalTime()获取 LocalDateTime​ 对象的时间部分,返回一个 LocalTime​ 对象。
getYear()获取年份。
getMonthValue()获取月份(1-12)。
getDayOfMonth()获取当月的日期(1-31)。
getHour()获取小时(0-23)。
getMinute()获取分钟(0-59)。
getSecond()获取秒(0-59)。
getNano()获取纳秒(0-999,999,999)。
五、日期时间的加减
方法名描述
plusYears(long years)增加指定的年数。
plusMonths(long months)增加指定的月数。
plusWeeks(long weeks)增加指定的周数。
plusDays(long days)增加指定的天数。
plusHours(long hours)增加指定的小时数。
plusMinutes(long minutes)增加指定的分钟数。
plusSeconds(long seconds)增加指定的秒数。
plusNanos(long nanos)增加指定的纳秒数。
minusYears(long years)减少指定的年数。
minusMonths(long months)减少指定的月数。
minusWeeks(long weeks)减少指定的周数。
minusDays(long days)减少指定的天数。
minusHours(long hours)减少指定的小时数。
minusMinutes(long minutes)减少指定的分钟数。
minusSeconds(long seconds)减少指定的秒数。
minusNanos(long nanos)减少指定的纳秒数。
六、比较日期时间
方法名描述
isBefore(LocalDateTime other)判断此日期时间是否在指定的日期时间之前。
isAfter(LocalDateTime other)判断此日期时间是否在指定的日期时间之后。
isEqual(LocalDateTime other)判断此日期时间是否等于指定的日期时间。
compareTo(LocalDateTime other)比较两个日期时间的大小,返回负数、零或正数。
七、时间戳转换
方法名描述
toEpochSecond(ZoneOffset offset)将此日期时间转换为从 1970-01-01T00:00:00Z 开始的秒数。
ofEpochSecond(long epochSecond, int nano, ZoneOffset offset)从秒数和纳秒数创建 LocalDateTime​ 对象。
八、其他方法
方法名描述
with(TemporalAdjuster adjuster)使用指定的调整器调整日期时间。
withYear(int year)设置年份。
withMonth(int month)设置月份。
withDayOfMonth(int dayOfMonth)设置当月的日期。
withHour(int hour)设置小时。
withMinute(int minute)设置分钟。
withSecond(int second)设置秒。
withNano(int nano)设置纳秒。
atZone(ZoneId zone)将此日期时间转换为指定时区的 ZonedDateTime​ 对象。
toLocalDate()获取日期部分。
toLocalTime()获取时间部分。

这些方法提供了丰富的功能来处理日期和时间,包括获取当前日期时间、创建特定日期时间、解析和格式化、日期时间的加减、比较日期时间以及与时间戳的转换等。通过使用这些方法,可以更方便、更准确地处理日期时间相关的操作。

示例

import java.time.LocalDateTime;

public class LocalDateTimeExample {
    public static void main(String[] args) {
        LocalDateTime dateTime = LocalDateTime.now();  // 获取当前日期和时间
        System.out.println(dateTime);  // 输出:2025-03-28T14:30:00.123
  
        LocalDateTime specificDateTime = LocalDateTime.of(2025, 3, 28, 14, 30);  // 创建特定日期和时间
        System.out.println(specificDateTime);  // 输出:2025-03-28T14:30
    }
}

image

2.4 DateTimeFormatter

关于

简介

Java 的 DateTimeFormatter​ 类是 java.time.format​ 包中用于格式化和解析日期时间对象的核心工具,专为 java.time​(Java 8+ 引入的日期时间 API)设计。它替代了旧的 SimpleDateFormat​,具备线程安全更清晰的API设计,支持 ISO-8601 标准及自定义模式。

image

功能
  1. 格式化(Formatting)
    LocalDate​、LocalDateTime​、ZonedDateTime​ 等对象转换为字符串。
  2. 解析(Parsing)
    将字符串解析为日期时间对象。
  3. ISO-8601 兼容
    直接支持 ISO 格式的日期时间表示。
  4. 自定义模式
    通过模式字符串定义灵活的日期时间格式。

方法

方法说明示例
ofPattern(String pattern)创建自定义格式DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
format(TemporalAccessor temporal)格式化日期时间对象localDateTime.format(formatter)
parse(CharSequence text)解析字符串为日期时间对象LocalDate.parse("2023-10-05", formatter)
withZone(ZoneId zone)指定时区formatter.withZone(ZoneId.of("Asia/Shanghai"))

DateTimeFormatter​ 预定义了 ISO 标准的格式化常量,例如:

  • ISO_LOCAL_DATE: yyyy-MM-dd​(如 2023-10-05​)
  • ISO_LOCAL_TIME: HH:mm:ss.SSS​(如 15:30:45.123​)
  • ISO_DATE_TIME: yyyy-MM-dd'T'HH:mm:ss.SSSZ​(如 2023-10-05T15:30:45.123+08:00​)

常见模式符号:

通过模式字符串定义格式:

符号含义示例
yyyy4位年份2023
MM2位月份10
dd2位日期05
HH24小时制小时15
mm分钟30
ss45
SSS毫秒123
Z时区偏移+0800

示例

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
  
        // 定义格式模板
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        // 格式化 LocalDateTime → String
        String formattedDate = now.format(formatter);
        System.out.println(formattedDate);

        // 解析 String → LocalDateTime
        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        LocalDateTime parsedDate = LocalDateTime.parse("2024-10-01 15:30", formatter1);
        System.out.println(parsedDate);
    }
}

image

2.5 Duration类(时间间隔)

关于

简介

Java 的 Duration​ 类是 java.time​ 包中用于表示基于时间的量(如小时、分钟、秒、纳秒)的不可变类,专为处理时间间隔设计。它与 Period​ 类(处理基于日期的量,如年、月、日)互补,适用于需要精确时间计算的场景。

  • 表示两个时间点之间的时间间隔,单位为秒和纳秒。
  • 示例:计算两个 LocalTime​ 或 LocalDateTime​ 之间的时间差。

image

核心特性
  • 时间单位:支持秒、纳秒,自动转换为标准单位(如 1 小时 = 3600 秒​)。
  • 不可变与线程安全:所有操作返回新对象,适合多线程环境。
  • ISO-8601 兼容:默认遵循 PnYnMnDTnHnMnS​ 格式(如 PT8H30M​ 表示 8 小时 30 分钟)。
  • 精确计算:处理纳秒级精度的时间间隔。

方法

方法说明示例
ofDays(long)​ / ofHours(long)创建指定天、小时的 DurationDuration.ofHours(2)​ → PT2H
ofMinutes(long)​ / ofSeconds(long)创建分钟、秒的 DurationDuration.ofSeconds(90)​ → PT1M30S
between(Temporal start, Temporal end)计算两个时间点之间的间隔Duration.between(startTime, endTime)
plus(Duration)​ / minus(Duration)时间间隔的加减duration.plus(Duration.ofMinutes(10))
toHours()​ / toMinutes()​ / toMillis()转换为其他时间单位duration.toMinutes()​ → 总分钟数
parse(CharSequence)解析 ISO-8601 格式字符串Duration.parse("PT2H30M")​ → 2小时30分钟
isNegative()判断是否为负时间间隔duration.isNegative()

示例

import java.time.Duration;
import java.time.LocalDateTime;

public class DurationExample {
    public static void main(String[] args) {
        // 创建两个时间点
        LocalDateTime start = LocalDateTime.of(2025, 3, 31, 10, 0, 0);
        LocalDateTime end = LocalDateTime.of(2025, 3, 31, 12, 30, 0);

        // 计算两个时间点之间的持续时间
        Duration duration = Duration.between(start, end);

        // 输出持续时间
        System.out.println("Duration (in hours): " + duration.toHours());        // 2小时
        System.out.println("Duration (in minutes): " + duration.toMinutes());    // 150分钟
        System.out.println("Duration (in seconds): " + duration.getSeconds());   // 5400秒
    }
}

image

2.6 Period类(日期间隔)

关于

简介

Java 的 Period​ 类是 java.time​ 包中用于表示基于日历的日期间隔(如年、月、日)的不可变类,专为处理与日历相关的周期设计(如“2年3个月10天”)。

  • 表示两个日期之间的间隔,单位为年、月和日。
  • 示例:计算两个 LocalDate​ 之间的日期差。

核心特性
  • 日历单位:支持年、月、日,自动处理不同月份和闰年的差异。
  • 不可变与线程安全:所有操作返回新对象,适合多线程环境。
  • ISO-8601 兼容:默认遵循 PnYnMnD​ 格式(如 P1Y2M3D​ 表示1年2个月3天)。
  • 自然日期计算:加减周期时考虑月份和年的实际天数(如 2024-02-28 + P1M = 2024-03-28​)。

方法

常用方法

方法说明示例
of(int years, int months, int days)创建指定年、月、日的 PeriodPeriod.of(1, 2, 3)​ → P1Y2M3D
between(LocalDate start, LocalDate end)计算两个日期之间的间隔Period.between(startDate, endDate)
plus(Period)​ / minus(Period)周期的加减period.plus(Period.ofMonths(1))
getYears()​ / getMonths()​ / getDays()获取年、月、日的数值period.getMonths()​ → 2
parse(CharSequence)解析 ISO-8601 格式字符串Period.parse("P3Y6M")​ → 3年6个月
isNegative()判断是否为负周期period.isNegative()

示例

示例1—创建 Period​ 对象:
import java.time.Period;

public class PeriodExample {
    public static void main(String[] args) {
        // 使用静态方法创建 Period 对象
        Period period1 = Period.of(1, 2, 10);  // 1年2个月10天
        Period period2 = Period.ofYears(3);    // 3年
        Period period3 = Period.ofMonths(5);   // 5个月
        Period period4 = Period.ofDays(20);    // 20天

        // 输出 Period 对象
        System.out.println("Period 1: " + period1);  // P1Y2M10D
        System.out.println("Period 2: " + period2);  // P3Y
        System.out.println("Period 3: " + period3);  // P5M
        System.out.println("Period 4: " + period4);  // P20D
    }
}

image

示例2—计算两个日期之间的差异
import java.time.LocalDate;
import java.time.Period;

public class PeriodExample {
    public static void main(String[] args) {
        // 创建两个日期
        LocalDate startDate = LocalDate.of(2020, 1, 1);
        LocalDate endDate = LocalDate.of(2023, 3, 15);

        // 计算两个日期之间的差异
        Period period = Period.between(startDate, endDate);

        // 输出差异
        System.out.println("Years: " + period.getYears());   // 3
        System.out.println("Months: " + period.getMonths()); // 2
        System.out.println("Days: " + period.getDays());     // 14
    }
}

image

三、总结

java.time​的诞生不仅是Java对开发者痛点的回应,更是面向未来时间处理的标杆。其不可变性、线程安全与ISO标准兼容性,使其成为高可靠系统的基石。无论是替换陈旧的Date​,还是应对全球化业务的时区挑战,java.time​都以优雅的设计降低认知成本。作为开发者,掌握这一工具不仅提升代码质量,更能在分布式系统、微服务架构中规避潜在风险。拥抱java.time​,让时间处理从“痛点”变为“亮点”,在复杂业务中真正实现时间自由

3ec794dacde34583aafafe15b1490012

http://www.dtcms.com/a/103309.html

相关文章:

  • 05-031-自考数据结构(20331)- 哈希表 - 例题分析
  • UE5学习记录part12
  • WebForms 事件
  • stm32第十天外部中断和NVIC讲解
  • 力扣刷题——排序链表
  • Lua语言脚本环境配置
  • 【uboot1】启动流程,环境变量,实例
  • Ubuntu上给AndroidStudio创建桌面图标
  • API 安全之认证鉴权
  • C++的指针数组、数组指针和指针数组指针
  • 怎么安装JSON服务器?JSON服务器最新安装教程
  • JavaScript中的模块化
  • GitHub Flow与GitLab Flow的详细
  • python求解常微分方程之Galerkin method:权函数
  • 【日期问题(判断星期几)】
  • 有哪些好用的项目管理工具推荐?并且支持AI定制和私有部署的?
  • 简单程序语言理论与编译技术·19 实现一个解释器
  • HTTP新的二进制格式与多路复用
  • 股指期货四个品种合约是什么意思?
  • OpenCV基础——图像滤波和形态学操作
  • 数字化计算机语言特性对比
  • 力扣HOT100之矩阵:48. 旋转图像
  • 《JVM考古现场(十四):混沌重启——从量子永生到宇宙热寂的终极编译》
  • 「Unity3D」TMP_InputField关闭虚拟键盘后,再次打开虚拟键盘,此时无法回调onSelect的问题
  • 文章配图新纪元:OpenAI新推出的GPT-4o原生图像生成功能启示
  • Joint Receiver Design for Integrated Sensing and Communications
  • 双向链表的理解
  • 【Kettle安装】Kettle安装过程, 电脑已安装java23,安装Kettle 出现报错:尝试启动 Java 虚拟机(JVM)时失败解决方法
  • JavaEE-MyBatis概述第一个程序
  • Redis GEO