首页 > 编程笔记 > Java笔记

Java日期时间类详解(Date、SimpleDateFormat、Instant和LocalDateTime)

日期和时间在应用程序中具有非常广泛和多样的应用,包括日期时间数据的获取和封装、日期时间数据的计算,以及日期时间数据的时区转换和格式转换等多个方面。

在日期时间数据的获取和封装方面,大部分的应用程序都有日志模块,用来记录应用运行过程中程序的执行情况和用户的各类操作,以及添加每行日志时当前的系统时间。同时,一些特定的功能会用到计时器功能,如订单的支付限时为 15 分钟。

除了日期和时间信息的封装,应用程序中还需要对日期时间进行计算,如通过用户的生日和当前日期计算用户的年龄,以及通过用户的登录时间和当前时间计算用户的在线时长等。

另外,一些国际化的应用程序也存在日期时间数据的时区转换和格式转换的需求。例如,应用程序界面中需要根据当前时区显示当前时间,在推送消息中将活动时间自动转换为当前时区对应的时间,以及按照当前地区惯用的格式来展示时间等。

Java 提供了多种与日期时间相关的工具类和丰富的 API,使开发者可以简化日期时间操作,以提高应用程序的开发效率。

1、Date类

java.util.Date 类表示一个特定的瞬间,时间可以精确到毫秒。

Date 类常用的方法如下。
【实例 1】创建Date对象。
import java.util.Date;

public class Demo {
    public static void main(String[] args) {
        // 打印当前日期和时间
        System.out.println(new Date());

        // 创建日期对象,将当前的毫秒值转换为日期对象
        System.out.println(new Date(0L));
    }
}
运行结果为:

Thu Aug 08 13:59:10 CST 2024
Thu Jan 01 08:00:00 CST 1970

2、SimpleDateFormat类

在输出 Date 对象代表的时间时,会自动调用 Date 类中的 toString() 方法。Date 类对 Object 类中的 toString() 方法进行了重写,按照“dow mon dd hh:mm:ss zzz yyyy”(星期 月份 日期 小时:分钟:秒 时区 年份)的格式输出该 Date 对象代表的时间。

在很多应用中,开发者需要指定自定义时间的输出格式。Java 提供的 java.text.DateFormat 类可以用来满足开发者对日期时间格式化的需求。

DateFormat 是日期时间格式化子类的抽象类,通过这个类可以完成日期和文本之间的转换。DateFormat 类支持日期的格式化(日期→文本)、日期的解析(文本→日期)和日期的规范化。

注意,DateFormat 类不能直接使用,实际开发中比较常用的是 SimpleDateFormat 类,它是 DateFormat 类的子类。

SimpleDateFormat 类常用的方法如下:
【实例 2】日期格式化的应用。
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo {
    public static void main(String[] args) {
        // 创建日期对象,获取当前的日期和时间
        Date date = new Date();

        // 创建日期格式化对象,在获取格式化对象时可以指定pattern
        DateFormat df = new SimpleDateFormat("yyyy年MM月dd日");

        // 调用format()方法格式化Date对象
        String str = df.format(date);

        // 输出格式化后的结果
        System.out.println(str);
    }
}
运行结果为:

2024年08月08日


【实例 3】日期解析的应用。
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo {
    public static void main(String[] args) throws ParseException {
        // 创建日期格式化对象,在获取格式化对象时可以指定pattern
        DateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
       
        // 创建一个包含日期信息的字符串对象
        String str = "2022年7月15日";
       
        // 调用parse()方法,解析日期字符串的内容,创建Date对象
        Date date = df.parse(str);
       
        // 以默认格式输出Date对象中的日期数据
        System.out.println(date);
    }
}
运行结果为:

Fri Jul 15 00:00:00 CST 2022

3、Instant类

java.time.Instant 类是 Java 8 提供的新的日期时间类。

和 Date 类相似,Instant 类的对象也代表时间线上的瞬时点。但是,与 Date 类精确到秒的设计不同,Instant 类可以精确到纳秒。

精确到纳秒的设计需要存储超过 1 个 long 型的数字,Instant 类采用两个 long 型的数字来存储数据:
这一设计有助于简化多个日期时间之间的比较计算,如判断日期先后顺序、求和运算和求差运算等。

Instant 类提供了丰富的 API 来支持上述操作。在创建 Instant 对象时需要注意,Instant 类未提供公有的构造方法,需要使用 Instant 类提供的静态方法来获取 Instant 对象。

Instant 类常用的方法如下:
【实例 4】获取 Instant 对象的应用。
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;

public class Demo {
    public static void main(String[] args) {
        // 获取当前时间对象
        Instant il = Instant.now();

        // 输出当前时间,默认使用零时区
        System.out.println("default:\t" + il);

        // 通过Clock的API获取东八区对应的时钟
        Clock offsetClock = Clock.offset(Clock.systemUTC(),
                                         Duration.ofHours(8));

        // 获取当前时间对象,设置使用东八区时钟
        Instant i2 = Instant.now(offsetClock);

        // 输出当前时间
        System.out.println("UTC+8: \t " + i2);

        // 基于指定时间获取Instant对象
        Instant i3 = Instant.ofEpochSecond(System.currentTimeMillis() / 1000 - 3600);
        System.out.println("one hour ago: \t " + i3);

        // 基于字符串获取Instant对象
        Instant i4 = Instant.parse("2022-09-18T06:00:00Z");
        System.out.println("from String:\t " + i4);
    }
}
运行结果为:
default:    2024-08-08T06:12:05.643802900Z
UTC+8:   2024-08-08T14:12:05.677713100Z
one hour ago:    2024-08-08T05:12:05Z
from String:     2022-09-18T06:00:00Z

【实例 5】Instant 类常用的方法的应用。
import java.time.Instant;
import java.time.temporal.ChronoUnit;

public class Demo {
    public static void main(String[] args) {
        // 解析字符串为Instant对象,表示2022年9月18日06:00:00 UTC
        Instant i1 = Instant.parse("2022-09-18T06:00:00Z");
       
        // 输出初始时间
        System.out.println("i1:\t" + i1);
       
        // 时间的加法运算,给i1增加3小时
        Instant i2 = i1.plus(3L, ChronoUnit.HOURS);
        System.out.println("i1+3 hours:\t" + i2);
       
        // 时间的减法运算,给i1减去5小时
        Instant i3 = i1.minus(5L, ChronoUnit.HOURS);
        System.out.println("i1-5 hours:\t" + i3);
       
        // 两个时间的差值,计算i1和i2之间的秒数差
        System.out.println("i1-i2 in seconds: " + i1.until(i2, ChronoUnit.SECONDS));
       
        // 判断时间先后,i1是否在i2之前
        System.out.println("i1 is before i2: " + i1.isBefore(i2));
       
        // 判断时间先后,i1是否在i2之后
        System.out.println("i1 is after i2: " + i1.isAfter(i2));
    }
}
运行结果为:

i1: 2022-09-18T06:00:00Z
i1+3 hours: 2022-09-18T09:00:00Z
i1-5 hours: 2022-09-18T01:00:00Z
i1-i2 in seconds: 10800
i1 is before i2: true
i1 is after i2: false

4、LocalDateTime类

Instant 类默认基于零时区构建 Instant 对象,所以在非零时区使用 Instant 对象时需要考虑时区问题。但是在很多本地化的应用中,考虑时区是没有必要的。

Java  8的 java.time 包中提供了简化版的日期时间操作类,包括 LocalDate、LocalTime 和 LocalDateTime。从这些类的名称可以看出,LocalDate 表示本地日期,LocalTime 表示本地时间,LocalDateTime 可以看成前两者的组合,表示本地日期时间。

由于这3个类的设计相似度较高,考虑到篇幅因素,下面仅对 LocalDateTime 类展开介绍,读者可以在此基础上,结合官方 API 文档,了解 LocalDate 类和 LocalTime 类。

与 Instant 类相似,LocalDateTime 类的对象也能封装日期时间数据。与 Instant 类不同的是,LocalDateTime 类中不包含时区的概念。可以将 LocalDateTime 类看成对本地日期时间的简单描述,所以该类适用于需要使用日期或本地时间的场景,比 Instant 更轻量级。

LocalDateTime 类常用的方法如下。
【实例 6】LocalDateTime类常用的方法的应用。
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class Demo {
    public static void main(String[] args) {
        System.out.println("---构建LocalDateTime 对象---");
        // 获取当前时间的ldt1对象
        LocalDateTime ldt1 = LocalDateTime.now();
        System.out.println("ldt1:\t" + ldt1);

        // 获取表示指定时间的ldt2对象
        LocalDateTime ldt2 = LocalDateTime.of(2022, 9, 18, 22, 0, 0, 0);
        System.out.println("ldt2:\t" + ldt2);

        System.out.println("---日期时间信息获取方法---");
        // 获取日期时间信息
        System.out.println(ldt1.getYear() + ":" + ldt1.getMonthValue() +
                ":" + ldt1.getDayOfMonth());
        System.out.println(ldt1.getHour() + ":" + ldt1.getMinute() +
                ":" + ldt1.getSecond());
        System.out.println("---日期时间计算方法---");

        // 日期时间计算
        LocalDateTime ldt3 = ldt1.plus(6, ChronoUnit.HOURS)
                .plusMinutes(10);
        System.out.println("ldt3:\t" + ldt3);

        // 这里假设l是一个整型变量,代表小时数,但图片中未给出其定义,可能需要根据上下文补充
        int l = 1; // 假设l的值为1,仅作为示例
        LocalDateTime ldt4 = ldt1.minus(l, ChronoUnit.HOURS)
                .minusMonths(1);
        System.out.println("ldt4:\t" + ldt4);
    }
}
运行结果为:
---构建LocalDateTime 对象---
ldt1:   2024-08-08T14:20:33.539289700
ldt2:   2022-09-18T22:00
---日期时间信息获取方法---
2024:8:8
14:20:33
---日期时间计算方法---
ldt3:   2024-08-08T20:30:33.539289700
ldt4:   2024-07-08T13:20:33.539289700

声明:《Java系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。