1. 時間API
我們的時間在java里是long類型的整數,這個整數稱之為時間戳(也叫格林威治時間),即從1970-01-01到現在為止所經過的毫秒數,單有這個時間戳是不能准確表達世界各地的時間,還需加上時區。比如現在輸出筆者本地的時間Mon Feb 10 09:48:43 GMT+08:00 2020
,其中 GMT+08:00 表示格林威治時間的東8區,也就是北京時間。
2. 舊時間API
java有兩套與時間相關的API,分別位於java.util和java.time下,現在更推薦使用time包下的API,由於歷史原因,我們還需兼容以前版本的時間函數,所以util也要來學習一下
2.1 Date
Date類內部原理
private transient long fastTime;
public Date() {
this(System.currentTimeMillis());
}
public Date(long date) {
fastTime = date;
}
- 從變量可以看出java時間戳使用long類型存儲
- 默認構造函數中的
System.currentTimeMillis()
獲取的是當前的時間戳 - 有參構造說明Date類是依賴時間戳的
從API和JDK可以知道Date內部很多函數都棄用了,打上了@Deprecated標簽,舊API中也不推薦使用了,相對推薦使用后面的Calendar類
@Deprecated
public Date(int year, int month, int date) {}
@Deprecated
public Date(String s) {}
下面列出常用的方法
類型 | 函數名 | 解釋 |
---|---|---|
long | getTime | 返回Date對象表示的時間戳 |
int | getYear | 返回Date對象表示的年,需+1900 |
int | getMonth | 返回Date對象表示的月,需+1 |
int | getDate | 返回Date對象表示的日 |
int | getHours | 返回Date對象表示的小時 |
int | getMinutes | 返回Date對象表示的分鍾 |
int | getSeconds | 返回Date對象表示的秒 |
int | getDay | 返回Date對象表示的周幾 |
例子
Date date = new Date();
System.out.println(date.getTime());
System.out.println(date.getYear() + 1900);
System.out.println(date.getMonth() + 1);
System.out.println(date.getDate());
1581301070240
2020
2
10
簡單使用時間格式化類
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("簡單使用時間格式化類: " + sdf.format(date));
System.out.println("原本的輸出:" + date);
簡單使用時間格式化類: 2020-02-10 10:24:13
原本的輸出:Mon Feb 10 10:24:13 GMT+08:00 2020
2.2 Calendar
Calendar類比Date多了日期計算功能,還有時區。並且Calendar是抽象類,構造方法為protected即外部包沒有繼承關系不能訪問的,不過他提供了getInstance來獲取實例
獲取實例
protected Calendar(){
// 省略內部如何實現
}
public static Calendar getInstance(){
// 省略內部如何實現
}
常用方法
類型 | 函數名 | 解釋 |
---|---|---|
int | get(int field) | 返回日歷給定字段的值 |
Date | getTime | 返回當前Calendar表示的Date |
void | setTimeZone(TimeZone value) | 設置時區 |
void | add(int field, int amount) | 當前日歷在給定字段上增加給定值 |
void | setTime(Date date) | 將給定Date設置為日歷 |
栗子
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.get(Calendar.YEAR));
System.out.println(calendar.get(Calendar.MONTH) + 1);
System.out.println(calendar.get(Calendar.DATE));
calendar.add(Calendar.YEAR,200);
System.out.println(calendar.get(Calendar.YEAR));
Date date = calendar.getTime();
2020
2
10
2220
2.3 TimeZone
TimeZone類就是可以設置時區咯
常用方法
類型 | 函數名 | 解釋 |
---|---|---|
TimeZone | getDefault | 返回默認時區 |
TimeZone | getTimeZone(String ID / zoneId) | 返回給定字符串對應的時區 |
板栗
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.get(Calendar.HOUR)); // 筆者當前時間11:09
calendar.setTimeZone(TimeZone.getTimeZone("GMT+10:00"));
System.out.println(calendar.get(Calendar.HOUR)); // 東10區時間為01:09
11
1
3. java1.8的新時間API
推出新時間API是因為舊API飽受詬病,因為:
- Date為可變(多線程訪問時間會變化)
- 輸出不人性化(Mon Feb 10 10:24:13 GMT+08:00 2020,且從1900開始計算)
- 格式化類線程不安全(多線程訪問格式化不同)
所以新API,java.time包所有類都是不可變和線程安全,且區分日期與時間
LocalDate date = LocalDate.now();
LocalTime time = LocalTime.now();
LocalDateTime dateTime = LocalDateTime.now();
System.out.println(date);
System.out.println(time);
System.out.println(dateTime);
2020-02-10
11:39:57.147
2020-02-10T11:39:57.147
輸出看起來是不是很舒服,可是LocalDateTime的輸出有點懵?,特意找了LocalDateTime的toString方法
@Override
public String toString() {
return date.toString() + 'T' + time.toString();
}
從中可以看出內部是維護了LocalDate和LocalTime了,中間使用了字符 T
隔開,為什么不用空格????
3.1 LocalDate
常用方法
類型 | 函數名 | 解釋 |
---|---|---|
LocalDate | now | 返回當前日期 |
int | getYear | 返回年 |
int | getMonthValue | 返回月 |
int | getDayOfMonth | 返回日 |
LocalDate | of(int year, int month, int dayOfMonth) | 創建實例 |
西瓜
LocalDate localDate = LocalDate.now();
System.out.println(localDate.getYear());
System.out.println(localDate.getMonthValue());
System.out.println(localDate.getDayOfMonth());
2020
2
10
3.2 LocalTime
這些其實都差不多就不一一說明了
桃子
LocalTime localTime = LocalTime.now();
System.out.println(localTime.getHour());
System.out.println(localTime.getMinute());
System.out.println(localTime.getSecond());
12
1
18
3.3 LocalDateTime
這里新增了plus和minus方法,對應加減,因為是不可變性,所以和String類一樣,返回一個新副本
蘋果
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);
LocalDateTime localTime1 = localDateTime.plusYears(1).plusMonths(1).plusDays(1);
System.out.println(localTime1);
LocalDateTime localTime2 = localDateTime.minusYears(1).minusMonths(1).minusDays(1);
System.out.println(localTime2);
2020-02-10T12:07:44.403
2021-03-11T12:07:44.403
2019-01-09T12:07:44.403
3.4 獲取時間戳
Instant timestamp = Instant.now();
3.5 獲取時間差
LocalDateTime startDateTime = LocalDateTime.of(2020, 2, 10, 10, 10, 10);
LocalDateTime endDateTime = LocalDateTime.of(2019, 1, 9, 9, 9, 9);
Duration duration = Duration.between(startDateTime, endDateTime);
System.out.println(duration);
PT-9529H-1M-1S // 相隔9529小時1分1秒