Java日期时间类详解(Date、DateFormat和Calendar)
在程序开发中,经常需要处理日期时间,Java 中提供了专门的日期时间类来处理相应的问题,本节将对 Java 中的日期时间类进行详细讲解。
例如,使用 Date 类的第 2 种构造方法创建一个 Date 类的对象,代码如下:
Date 类的常用方法及其说明如下表所示:
【实例】获取当前的日期和时间,创建 Date 对象获取当前日期和时间并输出。
DateFormat 类是日期时间格式化子类的抽象类,可以按照指定的格式对日期或时间进行格式化。
DateFormat 类提供了很多类方法,以获得基于默认或给定语言环境和多种格式化风格的默认日期时间 Formatter,格式化风格主要包括 SHORT、MEDIUM、LONG 和 FULL 4种:
另外,使用 DateFormat 类还可以自定义日期时间的格式。要格式化一个当前语言环境下的日期,首先需要创建 DateFormat 类的一个对象,由于它是抽象类,因此可以使用其静态方法 getDateInstance() 进行创建,语法如下:
DateFormat 类还提供了一些其他静态方法。例如,使用 getTimeInstance() 方法可获取所在国家或地区的时间格式,使用 getDateTimeInstance() 方法可获取日期和时间格式。
DateFormat 类的常用方法及其说明如下表所示:
例如,将当前日期按照 DateFormat 类默认格式进行输出:
输出长类型格式的当前时间:
输出长类型格式的当前日期:
输出长类型格式的当前日期和时间:
SimpleDateFormat 类提供了 19 个格式化字符,可以让开发者随意编写日期格式,这 19 个格式化字符如下表所示。
通常上表中的字符出现的数量会影响数字的格式。例如:yyyy 表示 4 位年份,这样输入会显示 2025;yy 表示两位,这样输入就会显示为 23;只有一个 y 的话,会按照 yyyy 显示;如果超过 4 个 y,如 yyyyyy,会在 4 位年份左侧补 0,结果为 02025。
一些常用的日期时间格式如下表所示:
【实例】以中文形式输出当前的日期和时间。创建 DateFormatDemo 类,在主方法中创建日期格式化对象,将格式设定为“某年某月某日星期几某时某分某秒”,以新闻开头的方法播报当前时间。
DateFormat 类提供的 Date parse(String source) 方法可以将字符串转为其字面日期对应的 Date 对象,整个过程相当于日期格式化的逆操作。
例如,将“2025-1-18”字符串转成 Date 对象,可以使用如下代码:
Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOU R等日历字段之间的转换提供了一些方法,并为操作日历字段(如获得下星期的日期)提供了一些方法。
另外,Calendar 类还为实现包范围外的具体日历系统提供了其他字段和方法,这些字段和方法被定义为 protected。
Calendar 提供了一个类方法 getInstance(),以获得此类型的一个通用的对象。Calendar 类的 getInstance() 方法返回一个 Calendar 对象,其日历字段已由当前日期和时间初始化,其使用方法如下:
Calendar 类提供的常用字段及其说明如下表所示:
Calendar 类提供的常用方法及其说明如下表所示:
从表中可以看到,add() 方法和 roll() 方法都用来为给定的日历字段添加或减去指定的时间量,它们的主要区别在于:
【实例】今天离中华人民共和国成立 100 周年差多少天。创建 CountDown 类,通过 Calendar 类和 Date 类计算出 2049 年 10 月 1 日距今相差的毫秒数,根据毫秒数计算出相差的天数。
最后对 Calendar 类的使用做出几点总结:
Java Date类
Date 类用于表示日期时间,使用该类表示时间需要使用其构造方法创建对象,其构造方法及其说明如下表所示。构造方法 | 说明 |
---|---|
Date() | 分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒) |
Date(long date) | 分配 Date 对象并初始化此对象,以表示自标准基准时间(即 1970 年 1 月 1 日 00:00:00 GMT)起经过指定毫秒数 date 后的时间 |
例如,使用 Date 类的第 2 种构造方法创建一个 Date 类的对象,代码如下:
long timeMillis = System.currentTimeMillis(); //当前系统时间所经历的毫秒数 Date date = new Date(timeMillis);上述代码中的 System 类的 currentTimeMillis() 方法主要用来获取当前系统时间距标准基准时间的毫秒数。需要注意的是,创建 Date 对象时使用的是 long 型整数,而不是 double 型,这主要是因为 double 类型可能会损失精度。
Date 类的常用方法及其说明如下表所示:
方法 | 说明 |
---|---|
after(Date when) | 测试当前日期是否在指定的日期之后 |
before(Date when) | 测试当前日期是否在指定的日期之前 |
getTime() | 获得自 1970 年 1 月 1 日 00:00:00 GMT 开始到现在所经过的毫秒数 |
setTime(long time) | 设置当前 Date 对象所表示的日期时间值,该值用以表示 1970 年 1 月 1 日 00:00:00 GMT 后 time 毫秒的时间点 |
【实例】获取当前的日期和时间,创建 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 Apr 23 05:23:07 UTC 2025
到现在所经历的毫秒数为:1745385787942
注意,本节介绍的 Date 类在 java.util 包下,但 java.sql 包下也有一个 Date 类,不要将二者搞混。
Java DateFormat类
如果在程序中直接输出 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 类的常用方法及其说明如下表所示:
方法 | 说明 |
---|---|
format(Date date) | 将一个 Date 对象实例格式化为日期/时间字符串 |
getCalendar() | 获取与此日期/时间格式器关联的日历 |
getDateInstance() | 获取日期格式器,该格式器具有默认语言环境的默认格式化风格 |
getDateTimeInstance() | 获取日期/时间格式器,该格式器具有默认语言环境的默认格式化风格 |
getInstance() | 获取为日期和时间使用 SHORT 风格的默认日期/时间格式器 |
getTimeInstance() | 获取时间格式器,该格式器具有默认语言环境的默认格式化风格 |
parse(String source) | 将字符串解析成一个日期,并返回这个日期的 Date 对象 |
例如,将当前日期按照 DateFormat 类默认格式进行输出:
DateFormat df = DateFormat.getInstance(); System.out.println(df.format(new Date()));结果如下:
2025/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()));结果如下:
2025年1月18日
输出长类型格式的当前日期和时间:
DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, DateFormat.LONG); System.out.println(df.format(new Date()));结果如下:
2025年1月18日 CST 17:06:44
由于 DateFormat 类是一个抽象类,不能用 new 创建实例对象。因此,除了使用 getXXXInstance() 方法创建其对象,还可以使用其子类,如 SimpleDateFormat 类,该类是一个以与语言环境相关的方式来格式化和分析日期的具体类,它允许进行格式化(日期→文本)、分析(文本→日期)和规范化。SimpleDateFormat 类提供了 19 个格式化字符,可以让开发者随意编写日期格式,这 19 个格式化字符如下表所示。
字 母 | 日期或时间元素 | 类型 | 说明 |
---|---|---|---|
G | Era 标志符 | Text | AD |
y | 年 | Year | 1996,96 |
M | 年中的月份 | Month | July; Jul; 07 |
w | 年中的周数 | Number | 27 |
W | 月份中的周数 | Number | 2 |
D | 年中的天数 | Number | 189 |
d | 月份中的天数 | Number | 10 |
F | 月份中的星期 | Number | 2 |
E | 星期中的天数 | Text | Tuesday; Tue |
a | Am/pm 标记 | Text | PM |
H | 一天中的小时数(0~23) | Number | 0 |
h | am/pm 中的小时数(1~12) | Number | 12 |
k | 一天中的小时数(1~24) | Number | 24 |
K | am/pm 中的小时数(0~11) | Number | 0 |
m | 小时中的分钟数 | Number | 30 |
s | 分钟中的秒数 | Number | 555 |
S | 毫秒数 | Number | 978 |
z | 时区 | General time zone | Pacific Standard Time; PST; GMT-08:00 |
Z | 时区 | RFC 822 time zone | -800 |
通常上表中的字符出现的数量会影响数字的格式。例如:yyyy 表示 4 位年份,这样输入会显示 2025;yy 表示两位,这样输入就会显示为 23;只有一个 y 的话,会按照 yyyy 显示;如果超过 4 个 y,如 yyyyyy,会在 4 位年份左侧补 0,结果为 02025。
一些常用的日期时间格式如下表所示:
日期时间 | 对应的格式 |
---|---|
2025/1/18 | yyyy/MM/dd |
2025.1.18 | yyyy.MM.dd |
2025-1-18 17:06:444 | yyyy-MM-dd HH:mm:ss |
2025 年 1 月 18 日 17 时 06 分 44 秒 星期三 | yyyy 年 MM 月 dd 日 HH 时 mm 分 ss 秒 EEE |
下午 5 时 | ah 时 |
今年已经过去了17 天 | 今年已经过去了 D 天 |
【实例】以中文形式输出当前的日期和时间。创建 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.println("各位观众大家好,现在是"); System.out.println(df.format(new Date())); System.out.println(",欢迎收看新闻。"); } }运行结果如下:
各位观众大家好,现在是2025年01月18日 星期三 17时14分59秒,欢迎收看新闻。
DateFormat 类提供的 Date parse(String source) 方法可以将字符串转为其字面日期对应的 Date 对象,整个过程相当于日期格式化的逆操作。
例如,将“2025-1-18”字符串转成 Date 对象,可以使用如下代码:
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date date = sdf.parse("2025-1-18");如果日期字符串不符合格式,则会抛出 java.text.ParseException 异常。
Java Calendar类
打开 Java API 文档可以看到 java.util.Date 类提供的大部分方法都已经过时了,因为 Date 类在设计之初没有考虑到国际化,而且很多方法也不能满足用户需求,比如需要获取指定时间的年月日时分秒信息,或者想要对日期时间进行加减运算等复杂的操作,Date 类已经不能胜任,因此 JDK 提供了新的时间处理类—Calendar 日历类。Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOU R等日历字段之间的转换提供了一些方法,并为操作日历字段(如获得下星期的日期)提供了一些方法。
另外,Calendar 类还为实现包范围外的具体日历系统提供了其他字段和方法,这些字段和方法被定义为 protected。
Calendar 提供了一个类方法 getInstance(),以获得此类型的一个通用的对象。Calendar 类的 getInstance() 方法返回一个 Calendar 对象,其日历字段已由当前日期和时间初始化,其使用方法如下:
Calendar rightNow = Calendar.getInstance();由于 Calendar 类是一个抽象类,不能用 new 创建实例对象,因此只能使用 getInstance() 方法创建该类的实例对象。如果需要创建 Calendar 类的对象,必须使用其子类,如 GregorianCalendar 类。
Calendar 类提供的常用字段及其说明如下表所示:
字段名 | 说明 |
---|---|
DATE | get 和 set 的字段数字,指示一个月中的某天 |
DAY_OF_MONTH | get 和 set 的字段数字,指示一个月中的某天 |
DAY_OF_WEEK | get 和 set 的字段数字,指示一个星期中的某天 |
DAY_OF_WEEK_IN_MONTH | get 和 set 的字段数字,指示当前月中的第几个星期 |
DAY_OF_YEAR | get 和 set 的字段数字,指示当前年中的天数 |
HOUR | get 和 set 的字段数字,指示上午或下午的小时 |
HOUR_OF_DAY | get 和 set 的字段数字,指示一天中的小时 |
MILLISECOND | get 和 set 的字段数字,指示一秒中的毫秒 |
MINUTE | get 和 set 的字段数字,指示一小时中的分钟 |
MONTH | 指示月份的 get 和 set 的字段数字 |
SECOND | get 和 set 的字段数字,指示一分钟中的秒 |
time | 日历的当前设置时间,以毫秒为单位,表示自格林威治标准时间 1970 年 1 月 1 日 0:00:00 后经过的时间 |
WEEK_OF_MONTH | get 和 set 的字段数字,指示当前月中的星期数 |
WEEK_OF_YEAR | get 和 set 的字段数字,指示当前年中的星期数 |
YEAR | 指示年的 get 和 set 的字段数字 |
Calendar 类提供的常用方法及其说明如下表所示:
方法 | 说明 |
---|---|
add(int field, int amount) | 根据日历的规则,为给定的日历字段添加或减去指定的时间量 |
after(Object when) | 判断此 Calendar 对象表示的时间是否在指定 Object 表示的时间之后,返回判断结果 |
before(Object when) | 判断此 Calendar 对象表示的时间是否在指定 Object 表示的时间之前,返回判断结果 |
get(int field) | 返回给定日历字段的值 |
getInstance() | 使用默认时区和语言环境获得一个日历 |
getTime() | 返回一个表示此 Calendar 对象时间值(从历元至现在的毫秒偏移量)的 Date 对象 |
getTimeInMillis() | 返回此 Calendar 对象的时间值,以毫秒为单位 |
roll(int field, boolean up) | 在给定的时间字段上添加或减去(上/下)单个时间单元,不更改更大的字段 |
set(int field, int value) | 将给定的日历字段设置为给定值 |
set(int year, int month, int date) | 设置日历字段 YEAR、MONTH 和 DAY_OF_MONTH 的值 |
set(int year, int month, int date, int hourOfDay, int minute) | 设置日历字段 YEAR、MONTH、DAY_OF_MONTH、HOUR_OF_DAY 和 MINUTE 的值 |
set(int year, int month, int date, int hourOfDay, int minute, int second) | 设置字段 YEAR、MONTH、DAY_OF_MONTH、HOUR_OF_DAY、MINUTE 和 SECOND 的值 |
setTime(Date date) | 使用给定的 Date 对象设置此 Calendar 对象的时间 |
setTimeInMillis(long millis) | 用给定的 long 值设置此 Calendar 对象的当前时间值 |
从表中可以看到,add() 方法和 roll() 方法都用来为给定的日历字段添加或减去指定的时间量,它们的主要区别在于:
- 使用 add() 方法会影响大的字段,像数学里加法的进位或错位;
- 使用 roll() 方法设置的日期字段只是进行增加或减少,不会改变更大的字段。
【实例】今天离中华人民共和国成立 100 周年差多少天。创建 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 开始计算的,所以这里要减 1 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周年倒计时——
今天是 2025 年 04 月 23 日
距离 2049 年 10 月 1 日还有 8927 天!
最后对 Calendar 类的使用做出几点总结:
- c.set(Calendar.DAY_OF_MONTH, 0) 获取的是上个月的最后一天,因此调用前需要将月份往后加一个月。
- Calendar.MONTH 的第一个月是使用 0 记录的,因此在获得月份数字后要加 1。年和日是从 1 开始记录的,不需要加 1。
- Calendar.DAY_OF_WEEK 的第一天是周日,周一是第二天,周六是最后一天。
相关文章
- Java时间日期的处理:Java Date类、Calendar类详解
- Java LocalDate日期时间类的用法(附带实例)
- Java Date日期时间类的用法(附带实例)
- Java LocalDate、LocalTime和LocalDateTime日期时间类的用法(附带实例)
- Java日期时间格式化(DateFormate、SimpleDateFormat和DateTimeFormatter)
- Java日期格式化(DateFormat类和SimpleDateFormat类)
- Java日期查询
- Java计算课程结束的日期
- Java Calendar日历类的用法(附带实例)
- Java.util.logging:JDK自带记录日志类