文章目录
作为开发者,经常需要处理日期时间。这里总结一下Java7常用的日期时间API。
Date
使用 java.util.Date
表示日期与时间,其承载了毫秒级精度的 Unix 时间。除此之外的功能(包括:承载 “年、月、日、时、分、秒” 字段,格式化,字符串解析),均标记为 @Deprecated
。
构造函数与常用方法
Date
类支持两个构造函数,如下表所示。
编号 | 构造函数 | 描述 |
---|---|---|
1 | Date() | 此构造函数使用当前日期和时间来初始化对象。 |
2 | Date(long millisec) | 此构造函数接受一个参数,该参数等于自1970年1月1日午夜以来经过的毫秒数。 |
以下是Date
类的方法列表
编号 | 方法 | 描述 |
---|---|---|
1 | boolean after(Date date) | 如果调用Date 对象包含的日期晚于date 指定的日期,则返回true ,否则返回false 。 |
2 | boolean before(Date date) | 如果调用Date 对象包含的日期早于date 指定的日期,则返回true ,否则返回false 。 |
3 | Object clone( ) | 复制调用的Date 对象。 |
4 | int compareTo(Date date) | 将调用对象的值与date 的值进行比较。 如果值相等则返回0 。 如果调用对象早于date ,则返回负值。 如果调用对象晚于date ,则返回正值。 |
5 | int compareTo(Object obj) | 如果obj 对象是Date 类对象,则与compareTo(Date) 操作相同。 否则,它会抛出ClassCastException 。 |
6 | boolean equals(Object date) | 如果调用Date 对象包含与date 指定的时间和日期相同的时间和日期,则返回true ,否则返回false 。 |
7 | long getTime() | 返回自1970年1月1日以来经过的毫秒数。 |
8 | int hashCode() | 返回调用对象的哈希码。 |
9 | void setTime(long time) | 设置时间指定的时间和日期,表示从1970年1月1日午夜开始的经过时间(以毫秒为单位)。 |
10 | String toString( ) | 将调用Date 对象转换为字符串并返回结果。 |
11 | static Date from(Instant instant) | 从Instant 对象获取一个Date 的实例。jdk1.8新增 |
12 | Instant toInstant() | 将此Date 对象转换为Instant 。jdk1.8新增 |
日期比较
Java使用以下三种方法来比较两个日期:
- 使用 getTime() 方法获取两个日期(自1970年1月1日经历的毫秒数值),然后比较这两个值。
- 使用方法 before(),after() 和 equals()。例如,一个月的12号比18号早,则 new Date(99, 2, 12).before(new Date (99, 2, 18)) 返回true。
- 使用 compareTo() 方法,它是由 Comparable 接口定义的,Date 类实现了这个接口。
测试Date构造方法和常用方法
/**
* 测试Date构造方法和常用方法
*/
@Test
public void testDate() {
// 参数表示1970-01-01 00:00:00到指定时间的毫秒数
// Sat Dec 05 12:49:59 CST 2020
Date date1 = new Date(1607143799610L);
System.out.println(date1);
// 当前时间
Date date2 = new Date();
System.out.println(date2);
// date1是否date2之后
System.out.println(date1.after(date2));
// date1和date2是否相等
System.out.println(date1.equals(date2));
// 返回自1970年1月1日以来经过的毫秒数
System.out.println(date2.getTime());
}
输出结果
Sat Dec 05 12:49:59 CST 2020
Sat Dec 05 17:39:23 CST 2020
false
false
1607161163418
SimpleDateFormat
DateFormat是抽象类,能够快速地进行日期与时间的格式化输出和字符串解析,它与以语言无关的方式格式化并解析日期或时间,所以使用其子类SimpleDateFormat实现日期和字符串的相互转换。
使用SimpleDateFormat测试日期和字符串的相互转换
/**
* 使用SimpleDateFormat测试日期和字符串的相互转换
*
* @throws ParseException
*/
@Test
public void testSimpleDateFormat() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 将字符串转化为日期
Date date = sdf.parse("2020-12-05 16:31:39");
System.out.println(date);
// 将日期转化为字符串
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String str = dateFormat.format(date);
System.out.println(str);
}
输出结果
Sat Dec 05 16:31:39 CST 2020
2020/12/05 16:31:39
DateFormat格式代码
要指定时间格式,请使用时间模式字符串。 在此模式中,所有ASCII字母都保留为模式字母,其定义如下
编号 | 字符 | 描述 | 示例 |
---|---|---|---|
1 | G | 时代指示符 | AD |
2 | y | 四位数的年份值 | 2019 |
3 | M | 月份 | July or 07 |
4 | d | 日 | 10 |
5 | h | 小时 A.M./P.M. (1~12) | 12 |
6 | H | 24小时制的小时表示 (0~23) | 22 |
7 | m | 分钟 | 30 |
8 | s | 秒钟 | 55 |
9 | S | 毫秒 | 234 |
10 | E | 星期几 | Tuesday |
11 | D | 一年中的第几天 | 360 |
12 | F | 一个月中的某一天 | 2 (second Wed. in July) |
13 | w | 一年中的第几个星期 | 40 |
14 | W | 一月中的第几个星期 | 1 |
15 | a | A.M./P.M. 标记 | PM |
16 | k | 小时 (1~24) | 24 |
17 | K | 小时 A.M./P.M. (0~11) | 10 |
18 | z | 时区 | Eastern Standard Time |
19 | ‘ | 转义文本 | Delimiter |
20 | " | 单引号 | ` |
Calendar
相比较于 java.util.Date
,java.util.Calendar
除了承载毫秒级的 Unix 时间,还承载了时区信息(默认使用系统的时区),并且,提供了诸多接口:“年、月、日、时、分、秒” 字段的获取与设置,时区设置,日期与时间的偏移调整。
从JDK1.1版本开始,在处理日期和时间时,系统推荐使用Calendar类进行实现。在设计上,Calendar类的功能要比Date类强大很多,而且在实现方式上也比Date类要复杂一些
Calendar类是一个抽象类,在实际使用时实现特定的子类的对象,创建对象的过程对程序员来说是透明的,只需要使用getInstance方法创建即可。
创建一个代表系统当前日期的Calendar对象
// 默认是当前日期
Calendar c = Calendar.getInstance();
创建一个指定日期的Calendar对象
使用Calendar类代表特定的时间,需要首先创建一个Calendar的对象,然后再设定该对象中的年月日参数来完成。
// 创建一个代表2020年6月12日的Calendar对象
Calendar c1 = Calendar.getInstance();
c1.set(2020, 6 - 1, 12);
Calendar类对象字段类型
Calendar类中用以下这些常量表示不同的意义,jdk内的很多类其实都是采用的这种思想
序号 | 常量 | 描述 |
---|---|---|
1 | Calendar.YEAR | 年份 |
2 | Calendar.MONTH | 月份 |
3 | Calendar.DATE | 日期 |
4 | Calendar.DAY_OF_MONTH | 日期,和上面的字段意义完全相同 |
5 | Calendar.HOUR | 12小时制的小时 |
6 | Calendar.HOUR_OF_DAY | 24小时制的小时 |
7 | Calendar.MINUTE | 分钟 |
8 | Calendar.SECOND | 秒 |
9 | Calendar.DAY_OF_WEEK | 星期几 |
Calendar类对象信息的设置
set设置
Calendar c1 = Calendar.getInstance();
// 把Calendar对象c1的年月日分别设这为:2020、6、12
public final void set(int year,int month,int date)
c1.set(2020, 6-1, 12);
add设置
把c1对象的日期加上10,也就是c1也就表示为10天后的日期,其它所有的数值会被重新计算
Calendar c1 = Calendar.getInstance();
c1.add(Calendar.DATE, 10);
其他字段属性的add的意义以此类推
测试Calendar类对象信息的获得,创建一个指定日期的Calendar对象
测试Calendar类对象信息的获得,创建一个指定日期的Calendar对象
/**
* 测试Calendar类对象信息的获得,创建一个指定日期的Calendar对象
*/
@Test
public void testCalendar() {
Calendar c1 = Calendar.getInstance();
// 获得年份
int year = c1.get(Calendar.YEAR);
// 获得月份
int month = c1.get(Calendar.MONTH) + 1;
// 获得日期
int date = c1.get(Calendar.DATE);
// 获得小时
int hour = c1.get(Calendar.HOUR_OF_DAY);
// 获得分钟
int minute = c1.get(Calendar.MINUTE);
// 获得秒
int second = c1.get(Calendar.SECOND);
// 获得星期几(注意(这个与Date类是不同的):1代表星期日、2代表星期1、3代表星期二,以此类推)
int day = c1.get(Calendar.DAY_OF_WEEK);
System.out.println("星期" + day + " " + year + "-" + month + "-" + date + " " + hour + ":" + minute + ":" + second);
// 创建一个指定日期的Calendar对象
Calendar c2 = Calendar.getInstance();
c2.set(2020, (12 - 1), 5);
System.out.println(c2.get(Calendar.YEAR) + "年" + (c2.get(Calendar.MONTH) + 1) + "月" + c2.get(Calendar.DATE) + "日");
}
输出结果
星期7 2020-12-5 17:42:47
2020年12月5日
GregorianCalendar
GregorianCalendar是Calendar类的子类,并提供世界上大多数国家/地区使用的标准日历系统。GregorianCalendar定义了两个字段:AD和BC。这是代表公历定义的两个时代。
构造函数与常用方法
下面列出GregorianCalendar对象的几个构造方法:
序号 | 构造函数 | 说明 |
---|---|---|
1 | GregorianCalendar() | 在具有默认语言环境的默认时区内使用当前时间构造一个默认的 GregorianCalendar。 |
2 | GregorianCalendar(int year, int month, int date) | 在具有默认语言环境的默认时区内构造一个带有给定日期设置的 GregorianCalendar |
3 | GregorianCalendar(int year, int month, int date, int hour, int minute) | 为具有默认语言环境的默认时区构造一个具有给定日期和时间设置的 GregorianCalendar。 |
4 | GregorianCalendar(int year, int month, int date, int hour, int minute, int second) | 为具有默认语言环境的默认时区构造一个具有给定日期和时间设置的 GregorianCalendar。 |
5 | GregorianCalendar(Locale aLocale) | 在具有给定语言环境的默认时区内构造一个基于当前时间的 GregorianCalendar。 |
6 | GregorianCalendar(TimeZone zone) | 在具有默认语言环境的给定时区内构造一个基于当前时间的 GregorianCalendar。 |
7 | GregorianCalendar(TimeZone zone, Locale aLocale) | 在具有给定语言环境的给定时区内构造一个基于当前时间的 GregorianCalendar。 |
这里是GregorianCalendar 类提供的一些有用的方法列表:
序号 | 方法 | 说明 |
---|---|---|
1 | void add(int field, int amount) | 根据日历规则,将指定的(有符号的)时间量添加到给定的日历字段中。 |
2 | protected void computeFields() | 转换UTC毫秒值为时间域值 |
3 | protected void computeTime() | 覆盖Calendar ,转换时间域值为UTC毫秒值 |
4 | boolean equals(Object obj) | 比较此 GregorianCalendar 与指定的 Object。 |
5 | int get(int field) | 获取指定字段的时间值 |
6 | int getActualMaximum(int field) | 返回当前日期,给定字段的最大值 |
7 | int getActualMinimum(int field) | 返回当前日期,给定字段的最小值 |
8 | int getGreatestMinimum(int field) | 返回此 GregorianCalendar 实例给定日历字段的最高的最小值。 |
9 | Date getGregorianChange() | 获得格里高利历的更改日期。 |
10 | int getLeastMaximum(int field) | 返回此 GregorianCalendar 实例给定日历字段的最低的最大值 |
11 | int getMaximum(int field) | 返回此 GregorianCalendar 实例的给定日历字段的最大值。 |
12 | Date getTime() | 获取日历当前时间。 |
13 | long getTimeInMillis() | 获取用长整型表示的日历的当前时间 |
14 | TimeZone getTimeZone() | 获取时区。 |
15 | int getMinimum(int field) | 返回给定字段的最小值。 |
16 | int hashCode() | 重写hashCode. |
17 | boolean isLeapYear(int year) | 确定给定的年份是否为闰年。 |
18 | void roll(int field, boolean up) | 在给定的时间字段上添加或减去(上/下)单个时间单元,不更改更大的字段。 |
19 | void set(int field, int value) | 用给定的值设置时间字段。 |
20 | void set(int year, int month, int date) | 设置年、月、日的值。 |
21 | void set(int year, int month, int date, int hour, int minute) | 设置年、月、日、小时、分钟的值。 |
22 | void set(int year, int month, int date, int hour, int minute, int second) | 设置年、月、日、小时、分钟、秒的值。 |
23 | void setGregorianChange(Date date) | 设置 GregorianCalendar 的更改日期。 |
24 | void setTime(Date date) | 用给定的日期设置Calendar的当前时间。 |
25 | void setTimeInMillis(long millis) | 用给定的long型毫秒数设置Calendar的当前时间。 |
26 | void setTimeZone(TimeZone value) | 用给定时区值设置当前时区。 |
27 | String toString() | 返回代表日历的字符串。 |
测试GregorianCalendar构造方法和常用方法
/**
* 测试GregorianCalendar构造方法和常用方法
*/
@Test
public void testGregorianCalendar() {
String months[] = {
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"};
int year;
// 初始化 Gregorian 日历
// 使用当前时间和日期
// 默认为本地时间和时区
GregorianCalendar gcalendar = new GregorianCalendar();
// 显示当前时间和日期的信息
System.out.print("Date: ");
System.out.print(months[gcalendar.get(Calendar.MONTH)]);
System.out.print(" " + gcalendar.get(Calendar.DATE) + " ");
System.out.println(year = gcalendar.get(Calendar.YEAR));
System.out.print("Time: ");
System.out.print(gcalendar.get(Calendar.HOUR_OF_DAY) + ":");
System.out.print(gcalendar.get(Calendar.MINUTE) + ":");
System.out.println(gcalendar.get(Calendar.SECOND));
// 测试当前年份是否为闰年
if (gcalendar.isLeapYear(year)) {
System.out.println("当前年份是闰年");
} else {
System.out.println("当前年份不是闰年");
}
}
输出结果
Date: Dec 5 2020
Time: 17:33:12
当前年份是闰年
Timestamp
java.sql.Timestamp继承java.util.Date,表示1970年1月1日午夜以来经过的毫秒数时间戳。可以精度达到纳秒级,保留SQL TIMESTAMP小数秒值的功能,时间戳还提供格式化和解析操作,以支持时间戳值的JDBC转义语法。
构造方法
编号 | 构造方法 | 描述 |
---|---|---|
1 | Timestamp(long time) | 构造一个 Timestamp 对象,使用毫秒时间值。 |
常用方法
编号 | 方法 | 描述 |
---|---|---|
1 | boolean | after(Timestamp ts) 判断此 Timestamp 对象是否晚于给定的 Timestamp 对象。 |
2 | boolean | before(Timestamp ts) 判断此 Timestamp 对象是否早于给定的 Timestamp 对象。 |
3 | long | getTime() 返回此 Timestamp 对象所表示的 00:00:00 GMT 以来 1970 年 1 月 1 日的毫秒数。 |
4 | String | toString() 设置 JDBC 时间戳转义格式的时间戳的格式。 |
5 | Instant | toInstant() 将此 Timestamp 对象转换为 Instant 。 |
6 | LocalDateTime | toLocalDateTime() 将此 Timestamp 对象转换为 LocalDateTime 。 |
在 Java 8 之前,我们使用 java.sql.Timestamp 来表示时间戳对象,可以通过以下方式创建与获取对象:
@Test
public void testTimestamp() {
// 利用系统标准时间创建
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
// 获取自 1970-01-01 00:00:00 GMT 以来的毫秒数
System.out.println(timestamp.getTime());
// 从 Date 对象中创建
Timestamp timestamp1 = new Timestamp((new Date()).getTime());
System.out.println(timestamp1.toString());
}
输出结果
1607750356429
2020-12-12 13:19:16.429