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

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