日期时间类

在程序开发中,经常需要处理日期时间,Java 中提供了专门的日期时间类来处理相应的问题,本节将对 Java 中的日期时间类进行详细讲解。

Date类

Date 类用于表示日期时间,使用该类表示时间需要使用其构造方法创建对象,其构造方法及其说明如表11.14所示。

image 2024 03 01 20 33 23 412
Figure 1. 表11.14 Date类的构造方法及其说明

例如,使用 Date 类的第 2 种构造方法创建一个 Date 类的对象,代码如下:

long timeMillis = System.currentTimeMillis();  //当前系统时间所经历的毫秒数
Date date = new Date(timeMillis);

上述代码中的 System 类的 currentTimeMillis() 方法主要用来获取当前系统时间距标准基准时间的毫秒数。另外,这里需要注意的是,创建 Date 对象时使用的是 long 型整数,而不是 double 型,这主要是因为 double 类型可能会损失精度。Date 类的常用方法及其说明如表11.15所示。

image 2024 03 01 20 46 22 423
Figure 2. 表11.15 Date类的常用方法及其说明

【例11.16】获取当前的日期和时间(实例位置:资源包\TM\sl\11\16)

创建 Date 对象获取当前日期和时间并输出。

import java.util.Date;
public class DateDemo {
	public static void main(String[] args) {
		Date date = new Date(); // 创建现在的日期
		long value = date.getTime(); // 获得毫秒数
		System.out.println("日期:" + date);
		System.out.println("到现在所经历的毫秒数为: " + value);
	}
}

运行此代码后,将在控制台中输出日期及自1970年1月1日00:00:00 GMT开始至本程序运行时所经历过的毫秒数,结果如下:

     日期:Wed Jan 18 17:01:48 CST 2023
     到现在所经历的毫秒数为: 1674032508698
  1. 本节介绍的 Date 类在 java.util 包下,但 java.sql 包下也有一个 Date 类,不要将二者搞混。

  2. 因为代码执行的时间不同,所以每次 “获取的当前时间” 得到的结果都不会一样。

日期时间格式化类

如果在程序中直接输出 Date 对象,显示的是 “Mon Feb 29 17:39:50 CST 2016” 这种格式的日期时间,那么应该如何将其显示为 “2016-02-29” 或者 “17:39:50” 这样的日期时间格式呢?Java 中提供了 DateFormat 类来实现类似的功能。

DateFormat 类是日期时间格式化子类的抽象类,可以按照指定的格式对日期或时间进行格式化。DateFormat 类提供了很多类方法,以获得基于默认或给定语言环境和多种格式化风格的默认日期时间 Formatter,格式化风格主要包括 SHORT、MEDIUM、LONG 和 FULL 4 种。

  • SHORT:完全为数字,如 12.13.52 或 3:30pm。

  • MEDIUM:较长,如Jan 12, 1952。

  • LONG:更长,如January 12, 1952 或 3:30:32pm。

  • FULL:完全指定,如 Tuesday、April 12、1952 AD 或 3:30:42pm PST。

另外,使用 DateFormat 类还可以自定义日期时间的格式。要格式化一个当前语言环境下的日期,首先需要创建 DateFormat 类的一个对象,由于它是抽象类,因此可以使用其静态方法 getDateInstance() 进行创建,语法如下:

DateFormat df = DateFormat.getDateInstance();

使用 getDateInstance() 方法获取的是所在国家或地区的标准日期格式。另外,DateFormat 类还提供了一些其他静态方法。例如,使用 getTimeInstance() 方法可获取所在国家或地区的时间格式,使用 getDateTimeInstance() 方法可获取日期和时间格式。DateFormat 类的常用方法及其说明如表11.16所示。

image 2024 03 01 20 55 57 959
Figure 3. 表11.16 DateFormat类的常用方法及其说明

例如,将当前日期按照 DateFormat 类默认格式进行输出:

DateFormat df = DateFormat.getInstance();
System.out.println(df.format(new Date()));

结果如下:

2023/1/18 17:03

输出长类型格式的当前时间:

DateFormat df = DateFormat.getTimeInstance(DateFormat.LONG);
System.out.println(df.format(new Date()));

结果如下:

CST 17:04:56

输出长类型格式的当前日期:

DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
System.out.println(df.format(new Date()));

结果如下:

2023年1月18日

输出长类型格式的当前日期和时间:

DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
System.out.println(df.format(new Date()));

结果如下:

2023年1月18日 CST 17:06:44

由于 DateFormat 类是一个抽象类,不能用 new 创建实例对象。因此,除了使用 getXXXInstance() 方法创建其对象,还可以使用其子类,如 SimpleDateFormat 类,该类是一个以与语言环境相关的方式来格式化和分析日期的具体类,它允许进行格式化(日期→文本)、分析(文本→日期)和规范化。

SimpleDateFormat 类提供了 19 个格式化字符,可以让开发者随意编写日期格式,这 19 个格式化字符如表11.17所示。

image 2024 03 01 21 02 35 081
Figure 4. 表11.17 SimpleDateFormat的格式化字符

通常表11.17中的字符出现的数量会影响数字的格式。例如:yyyy 表示4位年份,这样输入会显示 2023;yy 表示两位,这样输入就会显示为 23;只有一个y的话,会按照yyyy 显示;如果超过 4 个 y,如 yyyyyy,会在4位年份左侧补 0,结果为 02023。一些常用的日期时间格式如表11.18所示。

image 2024 03 01 21 07 30 943
Figure 5. 表11.18 常用日期时间格式

【例11.17】以中文形式输出当前的日期和时间(实例位置:资源包\TM\sl\11\17)

创建 DateFormatDemo 类,在主方法中创建日期格式化对象,将格式设定为 “某年某月某日星期几某时某分某秒”,以新闻开头的方法播报当前时间。

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateFormatDemo {
	public static void main(String[] args) {
		DateFormat df = new SimpleDateFormat("yyyy年MM月dd日 EEEE HH时mm分ss秒");
		System.out.print("各位观众大家好,现在是");
		System.out.print(df.format(new Date()));
		System.out.println(",欢迎收看新闻。");
	}

}

运行结果如下:

各位观众大家好,现在是2023年01月18日 星期三 17时14分59秒,欢迎收看新闻。

DateFormat 类提供的 Date parse(String source) 方法可以将字符串转为其字面日期对应的 Date 对象,整个过程相当于日期格式化的逆操作。

例如,将 “2023-1-18” 字符串转成 Date 对象,可以使用如下代码:

DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse("2023-1-18");

如果日期字符串不符合格式,则会抛出 java.text.ParseException 异常。

Calendar类

打开 Java API 文档可以看到 java.util.Date 类提供的大部分方法都已经过时了,因为 Date 类在设计之初没有考虑到国际化,而且很多方法也不能满足用户需求,比如需要获取指定时间的年月日时分秒信息,或者想要对日期时间进行加减运算等复杂的操作,Date 类已经不能胜任,因此JDK提供了新的时间处理类—Calendar日历类。

Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等日历字段之间的转换提供了一些方法,并为操作日历字段(如获得下星期的日期)提供了一些方法。另外,该类还为实现包范围外的具体日历系统提供了其他字段和方法,这些字段和方法被定义为 protected。

Calendar 提供了一个类方法 getInstance(),以获得此类型的一个通用的对象。Calendar 类的 getInstance() 方法返回一个 Calendar 对象,其日历字段已由当前日期和时间初始化,其使用方法如下:

Calendar rightNow = Calendar.getInstance();

由于 Calendar 类是一个抽象类,不能用 new 创建实例对象,因此只能使用 getInstance() 方法创建该类的实例对象。如果需要创建 Calendar 类的对象,必须使用其子类,如 GregorianCalendar 类。

Calendar 类提供的常用字段及其说明如表11.19所示。

image 2024 03 01 21 21 32 382
Figure 6. 表11.19 Calendar类提供的常用字段及其说明

Calendar 类提供的常用方法及其说明如表11.20所示。

image 2024 03 01 21 22 07 623
Figure 7. 表11.20 Calendar类提供的常用方法及其说明

从表11.20中可以看到,add() 方法和 roll() 方法都用来为给定的日历字段添加或减去指定的时间量,它们的主要区别在于:使用 add() 方法会影响大的字段,像数学里加法的进位或错位,而使用 roll() 方法设置的日期字段只是进行增加或减少,不会改变更大的字段。

【例11.18】今天离中华人民共和国成立100周年差多少天(实例位置:资源包\TM\sl\11\18)

创建 CountDown 类,通过 Calendar 类和 Date 类计算出2049年10月1日距今相差的毫秒数,根据毫秒数计算出相差的天数。

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class CountDown {
	public static void main(String[] args) {
		System.out.println("——————————共和国建立100周年倒计时——————————");
		Date date = new Date(); // 当前时间
		// 创建SimpleDateFormat对象,指定目标格式
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
		// 调用format方法,格式化时间,转换为指定方法
		String today = simpleDateFormat.format(date);
		System.out.println("今天是" + today); // 输出当前日期
		// 获取自1970年1月1日至当前时间所经过的毫秒数
		long time1 = date.getTime();
		// 使用默认时区和语言环境获得一个日历calendar
		Calendar calendar = Calendar.getInstance();
		// 设置日历calendar中的 年、月 和日的值。因为月份是从0开始计算的,所以这里要减一
		calendar.set(2049, 10 - 1, 1);
		// 计算自1970年1月1日至2049年10月1日所经过的毫秒数
		long time2 = calendar.getTimeInMillis();
		// 计算2049年10月1日距离当前时间相差的天数
		long day = (time2 - time1) / (1000 * 60 * 60 * 24);
		System.out.println("距离2049年10月1日还有 " + day + " 天!");
	}
}

运行结果如下:

     ——————————中华人民共和国成立100周年倒计时——————————
     今天是2023年01月18日
     距离2049年10月1日还有 9753 天!

最后对 Calendar 类的使用做出几点总结:

  • c.set(Calendar.DAY_OF_MONTH, 0) 获取的是上个月的最后一天,因此调用前需要将月份往后加一个月。

  • Calendar.MONTH 的第一个月是使用0记录的,因此在获得月份数字后要加1。年和日是从1开始记录的,不需要加1。

  • Calendar.DAY_OF_WEEK 的第一天是周日,周一是第二天,周六是最后一天。

编程训练(答案位置:资源包\TM\sl\11\编程训练)

【训练9】毫秒转时间 分别输出以下毫秒数对应的时间:1000,100000,1000000以及10000000。

【训练10】中文格式日期改英文格式 将“现在是2023年01月18日17时14分59秒”的日期字符串转为“2023/1/18 17:14:59”的格式。