一文帶你學會Java8的時間API!

前言

Java8以前日期/時間API存在的問題

  • 非線程安全 − java.util.Date 是非線程安全的,全部的日期類都是可變的,這是Java日期類最大的問題之一。
  • 設計不好 − Java的日期/時間類的定義並不一致,在java.util和java.sql的包中都有日期類,此外用於格式化和解析的類在java.text包中定義。java.util.Date同時包含日期和時間,而java.sql.Date僅包含日期,將其歸入java.sql包並不合理。另外這兩個類都有相同的名字,這自己就是一個很是糟糕的設計。
  • 時區處理麻煩 − 日期類並不提供國際化,沒有時區支持,所以Java引入了java.util.Calendar和java.util.TimeZone類,但他們一樣存在上述全部的問題。

​ 由於上面這些緣由,誕生了第三方庫Joda-Time,能夠替代Java的時間管理API。Java 8中新的時間和日期管理API深受Joda-Time影響,並吸取了不少Joda-Time的精華。新的java.time包包含了全部關於日期、時間、時區、Instant(跟日期相似可是精確到納秒)、duration(持續時間)和時鐘操做的類。新設計的API認真考慮了這些類的不變性(從java.util.Calendar吸收的教訓),若是某個實例須要修改,則返回一個新的對象。html

Java8新日期/時間API的改變

Java 8日期/時間API是JSR-310的實現,它的實現目標是克服舊的日期時間實現中全部的缺陷,新的日期/時間API的一些設計原則是:java

  • 不變性:新的日期/時間API中,全部的類都是不可變的,這對多線程環境有好處。
  • 關注點分離:新的API將人可讀的日期時間和機器時間(unix timestamp)明確分離,它爲日期(Date)、時間(Time)、日期時間(DateTime)、時間戳(unix timestamp)以及時區定義了不一樣的類。
  • 清晰:在全部的類中,方法都被明肯定義用以完成相同的行爲。舉個例子,要拿到當前實例咱們可使用now()方法,在全部的類中都定義了format()和parse()方法,而不是像之前那樣專門有一個獨立的類。爲了更好的處理問題,全部的類都使用了工廠模式和策略模式,一旦你使用了其中某個類的方法,與其餘類協同工做並不困難。
  • 實用操做:全部新的日期/時間API類都實現了一系列方法用以完成通用的任務,如:加、減、格式化、解析、從日期/時間中提取單獨部分,等等。
  • 可擴展性:新的日期/時間API是工做在ISO-8601日曆系統上的,但咱們也能夠將其應用在非IOS的日曆上。

Java日期/時間API包含如下相應的包:git

  • java.time包:這是新的Java日期/時間API的基礎包,全部的主要基礎類都是這個包的一部分,如:LocalDate, LocalTime, LocalDateTime, Instant, Period, Duration等等。全部這些類都是不可變的和線程安全的,在絕大多數狀況下,這些類可以有效地處理一些公共的需求。
  • java.time.chrono包:這個包爲非ISO的日曆系統定義了一些泛化的API,咱們能夠擴展AbstractChronology類來建立本身的日曆系統。
  • java.time.format包:這個包包含可以格式化和解析日期時間對象的類,在絕大多數狀況下,咱們不該該直接使用它們,由於java.time包中相應的類已經提供了格式化和解析的方法。
  • java.time.temporal包:這個包包含一些時態對象,咱們能夠用其找出關於日期/時間對象的某個特定日期或時間,好比說,能夠找到某月的第一天或最後一天。你能夠很是容易地認出這些方法,由於它們都具備「withXXX」的格式。
  • java.time.zone包:這個包包含支持不一樣時區以及相關規則的類。

Java8提供的LocalDate和DateTimeFormat是如何保證線程安全的?

LocalDate類和DateTimeFormatter類都是final類型的,也就是說,它們是不可變的,一旦實例化,值就固定了。而Java8以前的Date類和SimpleDateFormat類都不是final的。github

分析一下源碼。sql

LocalDateTime-Src
LocalDateTime-Src
DateTimeFormatter-Src
DateTimeFormatter-Src

Java8日期/時間API介紹

Java8新增類型

Instant:時間戳
Duration:持續時間,時間差
LocalDate:只包含日期,好比:2016-10-20
LocalTime:只包含時間,好比:23:12:10
LocalDateTime:包含日期和時間,好比:2016-10-20 23:14:21
Period:時間段
ZoneOffset:時區偏移量,好比:+8:00
ZonedDateTime:帶時區的時間
Clock:時鐘,好比獲取目前美國紐約的時間
java.time.format.DateTimeFormatter:時間格式化類
複製代碼

下面介紹下如何使用:api

LocalDate 只會獲取年月日

// 建立 LocalDate
// 獲取當前年月日 LocalDate localDate = LocalDate.now(); // 構造指定的年月日 LocalDate localDate1 = LocalDate.of(2019, 9, 12); // 獲取年、月、日、星期幾 int year = localDate1.getYear(); int year1 = localDate1.get(ChronoField.YEAR); Month month = localDate1.getMonth(); int month1 = localDate1.get(ChronoField.MONTH_OF_YEAR); // 月份中的第幾天:12 int day = localDate1.getDayOfMonth(); int day1 = localDate1.get(ChronoField.DAY_OF_MONTH); // 一週的第幾天:THURSDAY DayOfWeek dayOfWeek = localDate1.getDayOfWeek(); // 一週的第幾天:4 int dayOfWeek1 = localDate1.get(ChronoField.DAY_OF_WEEK); // 是否爲閏年:false boolean leapYear = localDate1.isLeapYear(); // 紐約日期 LocalDate todayNewYork = LocalDate.now(ZoneId.of("America/New_York")); 複製代碼

LocalTime 只會獲取時分秒

// 建立 LocalTime
LocalTime localTime = LocalTime.of(14, 14, 14); LocalTime localTime1 = LocalTime.now(); // 獲取小時 int hour = localTime.getHour(); int hour1 = localTime.get(ChronoField.HOUR_OF_DAY); // 獲取分 int minute = localTime.getMinute(); int minute1 = localTime.get(ChronoField.MINUTE_OF_HOUR); // 獲取秒 int second = localTime.getMinute(); int second1 = localTime.get(ChronoField.SECOND_OF_MINUTE); // 紐約時間 LocalTime timeNewYork = LocalTime.now(ZoneId.of("America/New_York")); 複製代碼

LocalDateTime 獲取年月日時分秒

至關於 LocalDate + LocalTime安全

// 建立 LocalDateTime
LocalDateTime localDateTime = LocalDateTime.now(); LocalDateTime localDateTime1 = LocalDateTime.of(2019, Month.SEPTEMBER, 10, 14, 46, 56); LocalDateTime localDateTime2 = LocalDateTime.of(localDate, localTime); LocalDateTime localDateTime3 = localDate.atTime(localTime); LocalDateTime localDateTime4 = localTime.atDate(localDate); // 獲取LocalDate LocalDate localDate2 = localDateTime.toLocalDate(); // 獲取LocalTime LocalTime localTime2 = localDateTime.toLocalTime(); // 紐約日期+時間 LocalDateTime timeNewYork = LocalDateTime.now(ZoneId.of("America/New_York")); 複製代碼

Instant 獲取秒數

用於表示一個時間戳(精確到納秒)markdown

它與咱們常使用的System.currentTimeMillis()有些相似,不過Instant能夠精確到納秒(Nano-Second),System.currentTimeMillis()方法只精確到毫秒(Milli-Second)。若是查看Instant源碼,發現它的內部使用了兩個常量,seconds表示從1970-01-01 00:00:00開始到如今的秒數,nanos表示納秒部分(nanos的值不會超過999,999,999)。Instant除了使用now()方法建立外,還能夠經過ofEpochSecond方法建立.多線程

// ofEpochSecond()方法的第一個參數爲秒,第二個參數爲納秒,上面的代碼表示從1970-01-01 00:00:00開始後兩分鐘的10萬納秒的時刻,控制檯上的輸出爲:
// 1970-01-01T00:02:00.000100Z Instant instant = Instant.ofEpochSecond(120, 100000);  // 建立Instant對象 Instant instant = Instant.now(); // 獲取秒數 long currentSecond = instant.getEpochSecond(); // 獲取毫秒數 long currentMilli = instant.toEpochMilli(); 複製代碼

Period/Duration 時間差

  • Period - 處理有關基於時間的日期數量。
  • Duration - 處理有關基於時間的時間量。

Duration 表示一個時間段

// Duration.between()方法建立 Duration 對象
LocalDateTime from = LocalDateTime.of(2017, Month.JANUARY, 1, 00, 0, 0); // 2017-01-01 00:00:00 LocalDateTime to = LocalDateTime.of(2019, Month.SEPTEMBER, 12, 14, 28, 0); // 2019-09-15 14:28:00 Duration duration = Duration.between(from, to); // 表示從 from 到 to 這段時間 long days = duration.toDays(); // 這段時間的總天數 long hours = duration.toHours(); // 這段時間的小時數 long minutes = duration.toMinutes(); // 這段時間的分鐘數 long seconds = duration.getSeconds(); // 這段時間的秒數 long milliSeconds = duration.toMillis(); // 這段時間的毫秒數 long nanoSeconds = duration.toNanos(); // 這段時間的納秒數 Duration duration1 = Duration.of(5, ChronoUnit.DAYS); // 5天 Duration duration2 = Duration.of(1000, ChronoUnit.MILLIS); // 1000毫秒 複製代碼

Period 表示日期上的時間差

Period在概念上和Duration相似,區別在於Period是以年月日來衡量一個時間段,好比2年3個月6天:oop

Period period = Period.of(2, 3, 6);

Period對象也能夠經過between()方法建立,值得注意的是,因爲Period是以年月日衡量時間段,因此between()方法只能接收LocalDate類型的參數:

// 2017-01-05 到 2017-02-05 這段時間
Period period = Period.between(  LocalDate.of(2017, 1, 5),  LocalDate.of(2017, 2, 5)); 複製代碼

ChronoUnit 時間枚舉類

LocalDate today = LocalDate.now();
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS); 複製代碼

Clock

它經過指定一個時區,而後就能夠獲取到當前的時刻,日期與時間。Clock能夠替換System.currentTimeMillis()與TimeZone.getDefault()。

Clock clock = Clock.systemUTC();
System.out.println(clock.instant() );//2020-05-26T16:54:54.141Z System.out.println(clock.millis() );//1590512094273 複製代碼

時區

Java 8中的時區操做被很大程度上簡化了,新的時區類java.time.ZoneId是原有的java.util.TimeZone類的替代品。ZoneId對象能夠經過ZoneId.of()方法建立,也能夠經過ZoneId.systemDefault()獲取系統默認時區:

ZoneId shanghaiZoneId = ZoneId.of("Asia/Shanghai");
ZoneId systemZoneId = ZoneId.systemDefault(); 複製代碼

of()方法接收一個「區域/城市」的字符串做爲參數,你能夠經過getAvailableZoneIds()方法獲取全部合法的「區域/城市」字符串:

Set<String> zoneIds = ZoneId.getAvailableZoneIds();
複製代碼

對於老的時區類TimeZone,Java 8也提供了轉化方法:

ZoneId oldToNewZoneId = TimeZone.getDefault().toZoneId();
複製代碼

有了ZoneId,咱們就能夠將一個LocalDateLocalTimeLocalDateTime對象轉化爲ZonedDateTime對象:

LocalDateTime localDateTime = LocalDateTime.now();
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, shanghaiZoneId); 複製代碼

zonedDateTime打印到控制檯爲:

2017-01-05T15:26:56.147+08:00[Asia/Shanghai]
複製代碼

ZonedDateTime 帶時區日期時間處理

對象由兩部分構成,LocalDateTimeZoneId,其中2017-01-05T15:26:56.147部分爲LocalDateTime+08:00[Asia/Shanghai]部分爲ZoneId

另外一種表示時區的方式是使用ZoneOffset,它是以當前時間和**世界標準時間(UTC)/格林威治時間(GMT)**的誤差來計算,例如:

ZoneOffset zoneOffset = ZoneOffset.of("+09:00");
LocalDateTime localDateTime = LocalDateTime.now(); OffsetDateTime offsetDateTime = OffsetDateTime.of(localDateTime, zoneOffset); 複製代碼

GMT(格林威治時間)、CST(可視爲美國、澳大利亞、古巴或中國的標準時間)、PST(太平洋時間)

GMT: UTC +0    =    GMT: GMT +0
CST: UTC +8    =    CST: GMT +8
PST: UTC -8    =    PST: GMT -8
複製代碼
ZonedDateTime
ZonedDateTime

從上面的圖中咱們能夠看出,LocalDateTime,並不能表示咱們人類世界中完整的時間,而ZonedDateTime能夠。

並且上面的轉換中咱們能夠知道,LocalDateTime轉Instant或者OffsetDatetime都是須要加上偏移時區的(ZoneOffset)。

因此能夠得出 OffsetDatetime和Instant也是能夠表示人類世界中完整的時間的,和ZoneDateTime是等效的。

OffsetDatetime、Instant和 ZoneDateTime區別

OffsetDateTime ,ZonedDateTime 和 Instant 都會在時間線上存儲一個納秒級精度。 Instant 是最簡單的,只需表明instant。 OffsetDateTime 添加到UTC / Greenwich的偏移瞬間,這容許得到本地日期時間。 ZonedDateTime 添加完整的時區規則。

所以 OffsetDateTime 和之間的區別ZonedDateTime 是後者包括涵蓋夏令時調整的規則。

國際時區 TimeZone ID列表 獲取方法:TimeZone.getAvailableIDs()

其餘曆法

Java中使用的歷法是ISO 8601日曆系統,它是世界民用曆法,也就是咱們所說的公曆。平年有365天,閏年是366天。閏年的定義是:非世紀年,能被4整除;世紀年能被400整除。爲了計算的一致性,公元1年的前一年被當作公元0年,以此類推。

此外Java 8還提供了4套其餘曆法(很奇怪爲何沒有漢族人使用的農曆),每套曆法都包含一個日期類,分別是:

  • ThaiBuddhistDate:泰國佛教歷
  • MinguoDate:中華民國曆
  • JapaneseDate:日本歷
  • HijrahDate:伊斯蘭曆

每一個日期類都繼承ChronoLocalDate類,因此能夠在不知道具體曆法的狀況下也能夠操做。不過這些曆法通常不經常使用,除非是有某些特殊需求狀況下才會使用。

這些不一樣的歷法也能夠用於向公曆轉換:

LocalDate date = LocalDate.now();
JapaneseDate jpDate = JapaneseDate.from(date); 複製代碼

因爲它們都繼承ChronoLocalDate類,因此在不知道具體曆法狀況下,能夠經過ChronoLocalDate類操做日期:

Chronology jpChronology = Chronology.ofLocale(Locale.JAPANESE);
ChronoLocalDate jpChronoLocalDate = jpChronology.dateNow(); 複製代碼

咱們在開發過程當中應該儘可能避免使用ChronoLocalDate,儘可能用與曆法無關的方式操做時間,由於不一樣的歷法計算日期的方式不同,好比開發者會在程序中作一些假設,假設一年中有12個月,若是是中國農曆中包含了閏月,一年有多是13個月,但開發者認爲是12個月,多出來的一個月屬於明年的。再好比假設年份是累加的,過了一年就在原來的年份上加一,但日本天皇在換代以後須要從新紀年,因此過了一年年份可能會從1開始計算。

在實際開發過程當中建議使用LocalDate,包括存儲、操做、業務規則的解讀;除非須要將程序的輸入或者輸出本地化,這時可使用ChronoLocalDate類。

日期的操做和格式化

增長和減小日期-簡單操做

LocalDate date = LocalDate.of(2017, 1, 5);          // 2017-01-05
LocalDate date1 = date.withYear(2016); // 修改成 2016-01-05 LocalDate date2 = date.withMonth(2); // 修改成 2017-02-05 LocalDate date3 = date.withDayOfMonth(1); // 修改成 2017-01-01  LocalDate date4 = date.plusYears(1); // 增長一年 2018-01-05 LocalDate date5 = date.minusMonths(2); // 減小兩個月 2016-11-05 LocalDate date6 = date.plus(5, ChronoUnit.DAYS); // 增長5天 2017-01-10 複製代碼

像LocalDate、LocalTime、LocalDateTime以及Instant這樣表示時間點的日期-時間類提供了大量通用的方法,

下表對這些通用的方法進行了總結

方法名 描述
from 靜態方法,依據傳入的 Temporal 對象建立對象實例
now 靜態方法,依據系統時鐘建立 Temporal 對象
of 靜態方法,由 Temporal 對象的某個部分建立該對象的實例
parse 靜態方法,由字符串建立 Temporal 對象的實例
atOffset 非靜態方法,將 Temporal 對象和某個時區偏移相結合
atZone 非靜態方法,將 Temporal 對象和某個時區相結合
format 非靜態方法,使用某個指定的格式器將Temporal對象轉換爲字符串(Instant類不提供該方法)
get 非靜態方法,讀取 Temporal 對象的某一部分的值
minus 非靜態方法,建立 Temporal 對象的一個副本,經過將當前 Temporal 對象的值減去必定的時長建立該副本
plus 非靜態方法,建立 Temporal 對象的一個副本,經過將當前 Temporal 對象的值加上必定的時長建立該副本
with 非靜態方法,以該 Temporal 對象爲模板,對某些狀態進行修改建立該對象的副本

TemporalField-複雜操做

TemporalField是一個接口,它定義瞭如何訪問temporal對象某個字段的值。ChronoField枚舉類實現了這一接口,因此你能夠很方便地使用get方法獲得枚舉元素的值:

int year = LocalDate.now().get(ChronoField.YEAR); 
 LocalDate date1 = LocalDate.now(); // 下一個週二  LocalDate nextTuesday = date1.with(TemporalAdjusters.next(DayOfWeek.TUESDAY)); // 當月的第二個週六 LocalDate firstInMonth = LocalDate.of(date1.getYear(), date1.getMonth(), 1); LocalDate secondSaturday = firstInMonth.with(TemporalAdjusters.nextOrSame(DayOfWeek.SATURDAY)).with(TemporalAdjusters.next(DayOfWeek.SATURDAY));  複製代碼

注:TemporalAdjusters類中有許多經常使用的特殊的日期的方法(類方法),使用時能夠仔細查看,能夠很大程度減小日期判斷的代碼量!

TemporalAdjusters 包含許多靜態方法,能夠直接調用,如下列舉一些:

方法名 描述
dayOfWeekInMonth 返回同一個月中每週的第幾天
firstDayOfMonth 返回當月的第一天
firstDayOfNextMonth 返回下月的第一天
firstDayOfNextYear 返回下一年的第一天
firstDayOfYear 返回本年的第一天
firstInMonth 返回同一個月中第一個星期幾
lastDayOfMonth 返回當月的最後一天
lastDayOfNextMonth 返回下月的最後一天
lastDayOfNextYear 返回下一年的最後一天
lastDayOfYear 返回本年的最後一天
lastInMonth 返回同一個月中最後一個星期幾
next / previous 返回後一個/前一個給定的星期幾
nextOrSame / previousOrSame 返回後一個/前一個給定的星期幾,若是這個值知足條件,直接返回

DateTimeFormatter 格式化日期

LocalDate localDate = LocalDate.of(2019, 9, 12);
String s1 = localDate.format(DateTimeFormatter.BASIC_ISO_DATE); String s2 = localDate.format(DateTimeFormatter.ISO_LOCAL_DATE); System.out.println("s1:"+ s1); // 20190912 System.out.println("s2:"+ s2); // 2019-09-12 LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("獲取當前時間:"+localDateTime); // 2019-09-16T14:54:36.520 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:MM:SS"); String s = localDateTime.format(formatter); System.out.println("格式化當前時間:"+ s); // 2019-09-16 14:09:52   LocalDate localDate1 = LocalDate.parse("20190912", DateTimeFormatter.BASIC_ISO_DATE); LocalDate localDate2 = LocalDate.parse("2019-09-12", DateTimeFormatter.ISO_LOCAL_DATE); 複製代碼

DateTimeFormatter咱們更多的是直接使用pattern來作轉換,其實這個類自己已經提供了一些預約義好的實例供咱們使用。 下面把二者的具體釋義和示例都貼出來供你們參考。

預約義

Predefined Formatters Formatter Description Example
ofLocalizedDate(dateStyle) Formatter with date style from the locale '2011-12-03'
ofLocalizedTime(timeStyle) Formatter with time style from the locale '10:15:30'
ofLocalizedDateTime(dateTimeStyle) Formatter with a style for date and time from the locale '3 Jun 2008 11:05:30'
ofLocalizedDateTime(dateStyle,timeStyle) Formatter with date and time styles from the locale '3 Jun 2008 11:05'
BASIC_ISO_DATE Basic ISO date '20111203'
ISO_LOCAL_DATE ISO Local Date '2011-12-03'
ISO_OFFSET_DATE ISO Date with offset '2011-12-03+01:00'
ISO_DATE ISO Date with or without offset '2011-12-03+01:00'; '2011-12-03'
ISO_LOCAL_TIME Time without offset '10:15:30'
ISO_OFFSET_TIME Time with offset '10:15:30+01:00'
ISO_TIME Time with or without offset '10:15:30+01:00'; '10:15:30'
ISO_LOCAL_DATE_TIME ISO Local Date and Time '2011-12-03T10:15:30'
ISO_OFFSET_DATE_TIME Date Time with Offset '2011-12-03T10:15:30+01:00'
ISO_ZONED_DATE_TIME Zoned Date Time '2011-12-03T10:15:30+01:00[Europe/Paris]'
ISO_DATE_TIME Date and time with ZoneId '2011-12-03T10:15:30+01:00[Europe/Paris]'
ISO_ORDINAL_DATE Year and day of year '2012-337'
ISO_WEEK_DATE Year and Week '2012-W48-6'
ISO_INSTANT Date and Time of an Instant '2011-12-03T10:15:30Z'
RFC_1123_DATE_TIME RFC 1123 / RFC 822 'Tue, 3 Jun 2008 11:05:30 GMT'

Pattern

All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters. The following pattern letters are defined:

Symbol Meaning Presentation Examples
G era text AD; Anno Domini; A
u year year 2004; 04
y year-of-era year 2004; 04
D day-of-year number 189
M/L month-of-year number/text 7; 07; Jul; July; J
d day-of-month number 10
Q/q quarter-of-year number/text 3; 03; Q3; 3rd quarter
Y week-based-year year 1996; 96
w week-of-week-based-year number 27
W week-of-month number 4
E day-of-week text Tue; Tuesday; T
e/c localized day-of-week number/text 2; 02; Tue; Tuesday; T
F week-of-month number 3
a am-pm-of-day text PM
h clock-hour-of-am-pm (1-12) number 12
K hour-of-am-pm (0-11) number 0
k clock-hour-of-am-pm (1-24) number 0
H hour-of-day (0-23) number 0
m minute-of-hour number 30
s second-of-minute number 55
S fraction-of-second fraction 978
A milli-of-day number 1234
n nano-of-second number 987654321
N nano-of-day number 1234000000
V time-zone ID zone-id America/Los_Angeles; Z; -08:30
z time-zone name zone-name Pacific Standard Time; PST
O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00;
X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15;
x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15;
Z zone-offset offset-Z +0000; -0800; -08:00;
p pad next pad modifier 1
' escape for text delimiter
'' single quote literal '
[ optional section start
] optional section end
# reserved for future use
{ reserved for future use
} reserved for future use

舊的日期時間支持

Date 和 LocalDate 互轉

// Date -> LocalDateTime/LocalDate
Date date = new Date(); LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();  // LocalDate -> Date LocalDate nowLocalDate = LocalDate.now(); Date date = Date.from(nowLocalDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); // LocalDateTime -> Date LocalDateTime localDateTime = LocalDateTime.now(); Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); 複製代碼

Date 和 Instant 互轉

// Date -> Instant
Instant timestamp = new Date().toInstant(); // Instant -> Date Date date = Date.from(Instant.now()); 複製代碼

TimeZone 和 ZoneId 互轉

ZoneId defaultZone = TimeZone.getDefault().toZoneId();
TimeZone tz = TimeZone.getTimeZone(defaultZone); 複製代碼

ZonedDateTime 和 GregorianCalendar 互轉

ZonedDateTime gregorianCalendarDateTime = new GregorianCalendar().toZonedDateTime();//GregorianCalendar -> ZonedDateTime
GregorianCalendar gc = GregorianCalendar.from(gregorianCalendarDateTime);//ZonedDateTime -> GregorianCalendar 複製代碼

其餘相關轉換

Long時間戳 和 LocalDateTime 互轉

// Long時間戳 -> LocalDateTime
long timestamp = System.currentTimeMillis(); LocalDateTime localDateTime = Instant.ofEpochMilli(timestamp).atZone(ZoneId.systemDefault()).toLocalDateTime();  // LocalDate -> Long時間戳 LocalDate localDate = LocalDate.now(); long timestamp = localDate.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli(); // LocalDateTime -> Long時間戳 LocalDateTime localDateTime = LocalDateTime.now(); long timestamp = localDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli(); // GMT +8時區 複製代碼

Instant 和 LocalDateTime互轉

// LocalDateTime -> Instant 
Instant instant = LocalDateTime.now().toInstant(ZoneOffset.of("+8")); // 或者 Instant instant1 = LocalDateTime.now().toInstant(ZoneOffset.ofHours(8));  // Instant -> LocalDateTime LocalDateTime instantToLocalDateTime = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()); 複製代碼

String 和 LocalDateTime 互轉

// String -> LocalDateTime
LocalDateTime stringToLocalDateTime = LocalDateTime.parse("2018-03-11 15:30:11", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));  // LocalDateTime -> String String localDateTimeToString = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") 複製代碼

String 和 Date 互轉

// String -> Date
Date stringToDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2018-03-11 15:30:11");  //Date -> String String dateToString = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); 複製代碼

Timestamp 和 LocalDateTime 互轉

// Timestamp -> LocalDateTime
LocalDateTime timeStampToLocalDateTime = LocalDateTime.ofInstant(new Timestamp(1520754566856L).toInstant(), ZoneId.systemDefault());  // LocalDateTime -> TimeStamp Timestamp localDateTimeToTimeStamp = Timestamp.valueOf(LocalDateTime.now()); 複製代碼

Timestamp 和 Date 互轉

// Timestamp -> Date
Date timestampToDate = Date.from(new Timestamp(1520754566856L).toInstant());  // Date -> LocalDateTime LocalDateTime dateToLocalDateTime = LocalDateTime.ofInstant(new Date().toInstant(), ZoneId.systemDefault()); 複製代碼

參考

Java 8 日期時間 API 指南 | Java 8 教程彙總

Java8新特性之日期和時間 - mrjade - 博客園

Java 8新特性(四):新的時間和日期API | 一書生VOID的博客

Java8新特性總結 -6.Date/Time API_java_BlueKitty的博客-CSDN博客

Java8新特性整理之新的時間和日期API(終章)_java_一大三千的博客-CSDN博客

Java8學習筆記:LocalDateTime、Instant 和 OffsetDateTime 相互轉換_java_山鬼謠的專欄-CSDN博客


求關注、分享、在看!!! 你的支持是我創做最大的動力。

本文使用 mdnice 排版

相關文章
相關標籤/搜索