Java 日期和時間
本小節(jié)我們將學(xué)習(xí) Java 中的日期和時間,日期和時間在我們的實際開發(fā)中非常常用,例如用戶的注冊、數(shù)據(jù)的增刪改、對敏感信息的操作等等都需要記錄下日期和時間。通過本小節(jié)的學(xué)習(xí),你將了解到什么是日期、什么是時間、什么是時區(qū),Java 中 Date
類的 API 介紹,Calendar
日歷類的使用,LocalDateTime
類的相關(guān) API 介紹等內(nèi)容。
1. 什么是日期和時間
日期指的是某一天,例如:
- 2020-10-24:2020 年 10 月 24 日;
- 1998-6-14:1998 年 6 月 14 日。
時間就是指某一個時刻,它分為兩種,一種是帶日期的時間,另外一種是不帶日期的時間,例如:
- 2020-10-24 08:30:23:2020 年 10 月 24 日 8 時 30 分 23 秒;
- 11:22:33:11 時 22 分 33 秒。
2. 什么是時區(qū)
我們知道,地球上的不同地區(qū)是有時差的,因此想要準(zhǔn)確定位一個時刻,還需要加上時區(qū)。
時區(qū)有以下 3 種表示方式:
GMT
或者UTC
加時區(qū)偏移表示:例如:GMT+08:00
或者UTC+08:00
表示東八區(qū);- 縮寫表示:例如:
CST
表示China Standard Time
(中國標(biāo)準(zhǔn)時間),但是此縮寫也可表示Central Standard Time USA
(美國中部時間),容易混淆不推薦使用; - 洲 / 城市:例如:
Asia/Shanghai
表示上海所在地的時區(qū)。注意城市名稱不是任意的城市,而是由國際標(biāo)準(zhǔn)組織規(guī)定的城市。
3. Date 類的使用
java.util.Date
類日期表示特定的時間瞬間,精度為毫秒。我們下面來看一下這個類的構(gòu)造方法和常用方法。
3.1 構(gòu)造方法
Date()
:創(chuàng)建一個對應(yīng)當(dāng)前時間的日期對象;Date(long date)
:創(chuàng)建指定毫秒數(shù)的日期對象。
由于其他 4 個構(gòu)造方法已經(jīng)過期,這里我們不進行介紹。
3.2 常用方法
String toString()
:將此日期對象轉(zhuǎn)換為以下形式的字符串:星期 月 日 時:分: 秒 時區(qū) 年;long getTime()
:返回此日期對象表示的自 1970 年 1 月 1 日 00:00:00 GMT 以來的毫秒數(shù);void setTime()
:將此日期對象設(shè)置為表示 1970 年 1 月 1 日 00:00:00 GMT 之后的時間點(毫秒)。
大多數(shù)其他方法都已經(jīng)過期,此處不再一一列舉,可翻閱官方文檔以了解更多內(nèi)容。
Tips:除了
java.util
包下的Date
類,在java.sql
包下也有一個Date
類。它是對應(yīng)數(shù)據(jù)庫字段的日期類型的類,與數(shù)據(jù)庫交互的時候才會用到,由于目前我們不涉及數(shù)據(jù)庫相關(guān)知識,此處做一個了解即可。我們更常用的還是java.util
包下的Date
類。
3.3 實例
創(chuàng)建日期對象,并打印 toString()
方法的結(jié)果:
import java.util.Date;
/**
* @author colorful@TaleLin
*/
public class DateDemo1 {
public static void main(String[] args) {
// 實例化一個date對象
Date date = new Date();
// 調(diào)用 toString() 方法
String s = date.toString();
System.out.println(s);
}
}
運行結(jié)果:
Wed Jun 10 10:21:10 CST 2020
我執(zhí)行代碼的時間是 2020 年 06 月 10 日 10:22:10 星期三,因此得到了如上的運行結(jié)果。
調(diào)用 getTime()
方法獲取當(dāng)前日期對象自 1970 年 1 月 1 日 00:00:00 GMT 以來的毫秒數(shù):
import java.util.Date;
/**
* @author colorful@TaleLin
*/
public class DateDemo2 {
public static void main(String[] args) {
// 實例化一個date對象
Date date = new Date();
// 調(diào)用 getTime() 方法
long time = date.getTime();
System.out.println(time);
}
}
運行結(jié)果:
1591755946922
4. Calendar 類的使用
Calendar 類是一個抽象類,它提供了一些方法,用于在特定的時間瞬間與一組日歷字段(如年、月、月、日、小時等)之間進行轉(zhuǎn)換,以及用于處理日歷字段(如獲取下一周的日期)。
4.1 實例化
由于 Calendar
類是一個抽象類,不能直接實例化,想要獲取其實例對象通常有兩種方法:
- 使用
Calendar.getInstance()
方法(更常用); - 調(diào)用它的子類的
GregorianCalendar
的構(gòu)造方法。
實例如下:
Calendar calendar = Calendar.getInstance();
4.3 常用方法
static Calendar getInstance()
:使用默認時區(qū)和區(qū)域設(shè)置獲取日歷;int get(int field)
:返回給定日歷字段的值;void set(int field, int value)
:將給定的日歷字段設(shè)置為給定值。(此外,set()
還有很多重載方法)
get(int field)
和 set(int field, int value)
方法的 field
參數(shù)是 int
類型,我們可以使用 Calendar
類下的一些靜態(tài)字段來表示,如下是官方文檔關(guān)于 Calendar
類的部分靜態(tài)字段的截圖:

更多常用方法和靜態(tài)字段請查閱官方文檔。
4.3 實例
4.3.1 get () 方法實例
import java.util.Calendar;
/**
* @author colorful@TaleLin
*/
public class CalendarDemo1 {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
// 獲取今天是這一周的第幾天
int i = calendar.get(Calendar.DAY_OF_WEEK);
// 獲取今天是這一月的第幾天
int i1 = calendar.get(Calendar.DAY_OF_MONTH);
// 獲取今天是這一月的第幾周
int i2 = calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH);
// 獲取今天是這一年的第幾天
int i3 = calendar.get(Calendar.DAY_OF_YEAR);
System.out.println("今天是這一周的第" + i + "天");
System.out.println("今天是這一月的第" + i1 + "天");
System.out.println("今天是這一月的第" + i2 + "周");
System.out.println("今天是這一年的第" + i3 + "天");
}
}
運行此段代碼的時間是 2020 年 06 月 10 日,運行結(jié)果如下:
今天是這一周的第4天
今天是這一月的第10天
今天是這一月的第2周
今天是這一年的第162天
通過調(diào)用 get()
方法,我們很方便地獲取到了當(dāng)前時間在日歷上是第幾天。要特別注意的是,獲取月份,返回的值是從 0 開始的(0 ~ 11),依次表示 1 月到 12 月;獲取一周的第 n
天,這里的返回值為 1~7
,1 表示周日,2 表示周一,以此類推。
4.3.2 set () 方法實例
import java.util.Calendar;
/**
* @author colorful@TaleLin
*/
public class CalendarDemo2 {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
// 設(shè)置2022年:
calendar.set(Calendar.YEAR, 2022);
// 設(shè)置9月: (8表示9月)
calendar.set(Calendar.MONTH, 8);
// 設(shè)置9日:
calendar.set(Calendar.DATE, 9);
// 設(shè)置時間:
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
System.out.println(calendar.getTime().toString());
}
}
運行結(jié)果:
Fri Sep 09 00:00:00 CST 2022
上面代碼分別設(shè)置了日歷的年、月、日、時、分、秒,Calendar.getTime()
可以將一個 Calendar
對象轉(zhuǎn)換成 Date
對象,最后再打印這個對象。
5. Java8 后新的日期和時間 API
5.1 為什么要提供新的 API
在 Java8 以后,提供了新的日期和時間 API,舊 API 的如下缺點得到了解決:
- 可變性:舊的 API 日期和時間是可變的,日期和時間這樣的類應(yīng)該是不可變的;
- 偏移性:
Date
中的年份是從 1990 年開始,月份是從 0 開始,星期天是用 1 表示的,不了解 API 的開發(fā)者很容易用錯; - 格式化:
SimpleDateFormat
只能用于格式化Date
類型,不能格式化Calendar
類型。
5.2 新 API 概述
新的日期時間 API 吸取了 Joda-Time 的精華,提供了更優(yōu)秀易用的 API,位于 java.time
包中,包含了 LocalTime
(本地時間)、LocalDate
(本地日期)、LocalDateTime
(本地日期時間)、ZonedDateTime
(帶時區(qū)的日期時間)和 Duration
(時間間隔)類。
而 java.util.Date
類下面增加了 toInstant()
方法,用于把 Date
轉(zhuǎn)換為新的類型。這些 API 大大簡化了日期時間的運算。
對偏移性的不合理設(shè)計也有修正:月份使用 1~12
表示 1 月 到 12 月,星期使用 1 ~ 7
表示星期一到星期天。
另外,使用了新的 DateTimeFormatter
來取代舊的 SimpleDateFormat
。
5.3 LocalDateTime 相關(guān)類的使用
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
* @author colorful@TaleLin
*/
public class LocalDateTimeDemo1 {
public static void main(String[] args) {
// 獲取當(dāng)前日期
LocalDate localDate = LocalDate.now();
// 獲取當(dāng)前時間
LocalTime localTime = LocalTime.now();
// 獲取當(dāng)前日期和時間
LocalDateTime localDateTime = LocalDateTime.now();
// 打印
System.out.println(localDate);
System.out.println(localTime);
System.out.println(localDateTime);
}
}
運行結(jié)果:
2020-06-10
14:17:48.618294
2020-06-10T14:17:48.618421
在實際開發(fā)中,LocalDateTime
相較于 LocalDate
和 LocalTime
更加常用。
本地日期和時間通過 now()
獲取到的總是以當(dāng)前默認時區(qū)返回的。
另外,可以使用 of()
方法來設(shè)置當(dāng)前日期和時間:
// 2020-9-30
LocalDate date = LocalDate.of(2020, 9, 30);
// 14:15:10
LocalTime time = LocalTime.of(14, 15, 10);
// 將date和time組合成一個LocalDateTime
LocalDateTime dateTime1 = LocalDateTime.of(date, time);
// 設(shè)置 年、月、日、時、分、秒
LocalDateTime dateTime2 = LocalDateTime.of(2020, 10, 21, 14, 14);
6. 小結(jié)
通過本小節(jié)的學(xué)習(xí),我們知道了日期、時間和時區(qū)的基本概念,在 Java 8 之前,通過 Date
類、Calendar
類以及 SimpleDateFormat
類來操作日期和時間,Java 8 以后,java.time
包下新增了一批新的日期時間 API,修復(fù)了舊 API 的一些缺點,簡化了開發(fā)者操作日期和時間的難度。本小節(jié)內(nèi)容比較簡單,梳理了 Java 對于日期時間處理的相關(guān) API,大家參照文檔,加以練習(xí)即可。