在閱讀本文之前,請先看上一篇文章 有關機器時間、UTC時間、本地時間的總結。
Java新時間API中有三個特別重要的類,分別是Instant、LocalDateTime、ZonedDateTime,它們分別對應到上一篇文章中講到的時間概念爲:機器時間、無時區的本地時間、有時區的本地時間。
機器時間其實可以理解爲UTC時間的另一種表現形式,其可以唯一確定時間線上的某一時刻。
無時區的本地時間因爲沒有時區信息,所以其無法唯一確定時間線上的某一時刻。
有時區的本地時間其實是在UTC時間的基礎上加一些時間偏移,所以也是可以唯一確定時間線上的某一時刻。
Java的新時間API其實都是圍繞這三個類來實現的,所以,徹底理解這三個類的目的及使用場景對於靈活使用Java新時間API來說非常重要。
下面我們用示例來講解下Java的新時間API究竟怎麼用。
- 獲取當前時間的年月日等信息。
static void t1() {
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt.getYear());
ZonedDateTime zdt = ZonedDateTime.now();
System.out.println(zdt.getYear());
// 對於獲取當前時刻的human time信息(年月日時分秒)來說
// 用LocalDateTime或者ZonedDateTime都是一樣的
// 他們的底層都是先獲取machine time,然後再按照所在時區
// 將machine time轉成human time
// ZonedDateTime比LocalDateTime的唯一區別就是攜帶了時區信息
// 但如果只是爲了獲取年月日等信息,時區是沒用的
}
- 獲取某一機器時間的年月日等信息。
static void t2() {
long millis = System.currentTimeMillis();
Instant instant = Instant.ofEpochMilli(millis);
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
System.out.println(ldt.getYear());
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
System.out.println(zdt.getYear());
// 機器時間要先轉成Instant實例後,才能被Java新時間API使用
}
- 人類時間轉機器時間。
static void t3() {
// 由於LocalDateTime沒有時區信息,所以它無法直接轉成機器時間
// 只能通過主動提供時區信息的方式纔可以
LocalDateTime ldt = LocalDateTime.now();
long millis = ldt.toInstant(ZoneOffset.of("+08:00")).toEpochMilli();
System.out.println(millis);
// 由於ZonedDateTime內已經有時區信息了,所以它可以直接轉成機器時間
ZonedDateTime zdt = ZonedDateTime.now();
millis = zdt.toInstant().toEpochMilli();
System.out.println(millis);
// 還需要注意的是,代表人類時間的類並不是直接轉成的機器時間,而是通過Instant類間接完成
}
- 解析時間字符串。
static void t4() {
// 被解析的字符串不能有時區信息
LocalDateTime ldt = LocalDateTime.parse("2019-09-25T16:32:42");
System.out.println(ldt);
// 被解析的字符串必須有時區信息
ZonedDateTime zdt = ZonedDateTime.parse("2019-09-25T16:32:42+08:00");
System.out.println(zdt);
}
- 時間的運算。
static void t5() {
// LocalDateTime的時間加減就是純粹的加減
LocalDateTime ldt = LocalDateTime.parse("2019-03-10T01:59:59");
System.out.println(ldt.plusHours(1).getHour()); // 輸出:2
// ZonedDateTime的時間加減還會考慮時區信息
// 比如2019-03-10T02:00:00開始,美國開始施行 daylight saving time (夏令時)
// 他們的本地時間會向後撥一個小時,即:凌晨2點會變成凌晨3點
// 有關 daylight saving time 更多信息,請看以下文章:
// https://en.wikipedia.org/wiki/Daylight_saving_time
ZonedDateTime zdt = ldt.atZone(ZoneId.of("America/New_York"));
System.out.println(zdt.plusHours(1).getHour()); // 輸出:3
// 所以說,如果涉及到時間的運算,要用ZonedDateTime
}
- 獲取某一機器時間所屬那天的零點的機器時間。
static long startOfDay(long millis) {
return LocalDate.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault())
.atStartOfDay(ZoneId.systemDefault())
.toInstant()
.toEpochMilli();
}
- 獲取某一機器時間所屬那個星期的星期一零點的機器時間。
static long startOfWeek(long millis) {
return LocalDate.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault())
.atStartOfDay(ZoneId.systemDefault())
.with(DayOfWeek.MONDAY)
.toInstant()
.toEpochMilli();
}
- 獲取某一機器時間所屬那個月的一號零點的機器時間。
static long startOfMonth(long millis) {
return LocalDate.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault())
.atStartOfDay(ZoneId.systemDefault())
.withDayOfMonth(1)
.toInstant()
.toEpochMilli();
}
好,例子就這麼多吧,我覺得到這裏大家都差不多懂了。
有關Java新時間API更多介紹,請參考Java官方教程:
https://docs.oracle.com/javas...
希望對大家有所幫助。
完。
更多原創文章,請關注我微信公衆號: