日期和时间在应用程序中具有非常广泛和多样的应用,包括日期时间数据的获取和封装、日期时间数据的计算,以及日期时间数据的时区转换和格式转换等多个方面。
在日期时间数据的获取和封装方面,大部分的应用程序都有日志模块,用来记录应用运行过程中程序的执行情况和用户的各类操作,以及添加每行日志时当前的系统时间。同时,一些特定的功能会用到计时器功能,如订单的支付限时为 15 分钟。
除了日期和时间信息的封装,应用程序中还需要对日期时间进行计算,如通过用户的生日和当前日期计算用户的年龄,以及通过用户的登录时间和当前时间计算用户的在线时长等。
另外,一些国际化的应用程序也存在日期时间数据的时区转换和格式转换的需求。例如,应用程序界面中需要根据当前时区显示当前时间,在推送消息中将活动时间自动转换为当前时区对应的时间,以及按照当前地区惯用的格式来展示时间等。
Java 提供了多种与日期时间相关的工具类和丰富的 API,使开发者可以简化日期时间操作,以提高应用程序的开发效率。
1、Date类
java.util.Date 类表示一个特定的瞬间,时间可以精确到毫秒。
Date 类常用的方法如下。
Date():构造方法,创建 Date 对象并初始化此对象,以表示创建它的时间(精确到毫秒);
Date(long date):构造方法,创建 Date 对象并初始化此对象,以表示自从标准基准时间(称为“历元”,即 1970 年 1 月 1 日 00:00:00 GMT)以来的指定毫秒数,由于我国处于东八区,因此基准时间为 1970 年 1 月 1 日 8 时 0 分 0 秒;
long getTime():将日期对象代表的时间转换成对应的毫秒值;
boolean before(Date when):判断当前日期对象代表的时间是否在 when 对象代表的日期之前;
boolean after(Date when):判断当前日期对象代表的时间是否在 when 对象代表的日期之后。
【实例 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 类常用的方法如下:
SimpleDateFormat(String pattern):构造方法,用给定的日期时间格式 pattern 和默认的日期格式符构造 SimpleDateFormat 对象,参数 pattern 是一个字符串,代表日期时间的自定义格式,常用的格式为“yyyy-MM-dd HH:mm:ss”。其中,yyyy 表示年份,MM 表示月份,dd 表示日期,HH 表示小时,mm 表示分钟,ss 表示秒;
String format(Date date):将 Date 对象代表的时间格式化为字符串;
Date parse(String source):将字符串解析为 Date 对象。
【实例 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 型的数字来存储数据:
第一部分保存的是自 1970 年 1 月 1 日开始到现在的秒数,即纪元秒(Epoch Second);
第二部分保存的是纳秒数(永远不会超过 999 999 999)。
这一设计有助于简化多个日期时间之间的比较计算,如判断日期先后顺序、求和运算和求差运算等。
Instant 类提供了丰富的 API 来支持上述操作。在创建 Instant 对象时需要注意,Instant 类未提供公有的构造方法,需要使用 Instant 类提供的静态方法来获取 Instant 对象。
Instant 类常用的方法如下:
static Instant now():基于系统时钟获取一个代表当前时间的 Instant 对象;
static Instant ofEpochSecond(long epochSecond):返回一个基于传入的纪元秒 epochSecond 构建的 Instant 对象,纳秒部分的值为 0;
static Instant ofEpochSecond(long epochSecond, long nano):返回一个基于传入的纪元秒 epochSecond 和纳秒 nano 构建的 Instant 对象;
static Instant ofEpochMilli(long epochMilli):返回一个基于传入的纪元毫秒 epochMilli 构建的 Instant 对象;
Instant plus(TemporalAmount amount):返回当前 Instant 对象的一个副本,其中添加了由 amount 指定的时间长度;
Instant plus(long amount, TemporalUnit unit):返回当前 Instant 对象的一个副本,其中添加了由 amount 指定的时间长度,unit 用于定义 amount 的单位;
Instant minus(TemporalAmount amount):返回当前 Instant 对象的一个副本,其中减小了由 amount 指定的时间长度;
Instant minus(long amount, TemporalUnit unit):返回当前 Instant 对象的一个副本,其中减小了由 amount 指定的时间长度,unit 用于定义 amount 的单位;
long until(Temporal end, TemporalUnit unit):根据指定的单位计算到另一个 Instant 对象的时间长度,如果当前对象代表的时间晚于 end 代表的时间,那么将返回负值;
boolean isAfter(Instant otherInstant):检查当前 Instant 对象代表的时间是否在 otherInstant 对象代表的时间之后;
boolean isBefore(Instant otherInstant):检查当前 Instant 对象代表的时间是否在 otherInstant 对象代表的时间之前。
【实例 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 类常用的方法如下。
static LocalDateTime now():获取一个当前本地日期时间对象,基于默认时区的系统时钟产生;
static LocalDateTime now(Clock clock):获取一个当前本地日期时间对象,基于 clock 指定的时钟产生;
static LocalDateTime of(int year,Month month,int dayOfMonth,int hour,int minute,int second,int nanoOfSecond):获取一个基于给定的年、月、日、时、分、秒和纳秒信息构建的本地日期时间对象,该方法存在多个重载方法,可以基于各类信息构建日期时间对象,读者可以自行查阅;
static LocalDateTime ofInstant(Instant instant,ZoneId zone):基于 Instant 对象和时区 ID 构建本地日期时间对象;
int getYear():返回本地日期时间对象中的年份值,该类设计了返回日期时间各部分数据的方法,读者可以自行查阅;
LocalDateTime plus(long amount,TemporalUnit unit):返回本地日期时间对象的副本,其中添加了指定的时间,unit 用于指定单位;
LocalDateTime minus(long amount,TemporalUnit unit):返回本地日期时间对象的副本,其中减去了指定的时间,unit 用于指定单位。
【实例 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笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。