在Java8之前,我們通常使用java.util.Date
和java.util.Calendar
類來處理日期和時間相關(guān)的操作,例如:
//創(chuàng)建一個Date對象
Date date = new Date();
//獲取當(dāng)前的年月日時分秒
int year = date.getYear() + 1900;
int month = date.getMonth() + 1;
int day = date.getDate();
int hour = date.getHours();
int minute = date.getMinutes();
int second = date.getSeconds();
//打印當(dāng)前的日期和時間
System.out.println(year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second);
這種方式雖然可以實現(xiàn)功能,但是有一些缺點:
- 可變性:
Date
和Calendar
類都是可變的,這意味著它們的值可以被修改,這可能會導(dǎo)致一些線程安全和邏輯錯誤的問題。 - 可讀性差:
Date
和Calendar
類的方法命名和設(shè)計都不夠清晰和一致,例如getYear()
方法返回的是從1900年開始的年份,而不是實際的年份;getMonth()
方法返回的是從0開始的月份,而不是從1開始的月份;set(int field, int value)
方法可以設(shè)置任意的字段和值,但是可能會導(dǎo)致不合理的結(jié)果,例如2月30日等。 - 時區(qū)問題:
Date
和Calendar
類都不能很好地處理時區(qū)相關(guān)的問題,例如在不同的時區(qū)下顯示或轉(zhuǎn)換日期和時間。
為了解決這些問題,Java8引入了一套全新的日期和時間API,在java.time
包中。這套API基于JSR-310規(guī)范設(shè)計,提供了一系列不可變且線程安全的類來表示日期、時間、時區(qū)、時段等概念。這套API有以下特點:
- 不可變性:所有的日期和時間類都是不可變的,這意味著它們的值不能被修改,只能通過創(chuàng)建新的對象來表示不同的值。這樣可以避免線程安全和邏輯錯誤的問題。
- 可讀性好:所有的日期和時間類都有清晰和一致的方法命名和設(shè)計,例如
getYear()
方法返回的是實際的年份;getMonth()
方法返回的是一個枚舉類型,而不是一個整數(shù);with(TemporalAdjuster adjuster)
方法可以根據(jù)指定的規(guī)則調(diào)整日期或時間,例如獲取下一個周一等。 - 時區(qū)支持:所有的日期和時間類都可以與時區(qū)相關(guān)聯(lián),例如使用
ZonedDateTime
類可以表示帶有時區(qū)信息的日期和時間;使用ZoneId
類可以表示時區(qū)標(biāo)識符;使用ZoneOffset
類可以表示時區(qū)偏移量。
Java8 Date Time API使用示例
為了方便理解Java8 Date Time API,我們可以將其分為四個層次:
- 本地日期和時間:表示不帶有時區(qū)信息的日期和時間,主要有以下幾個類:
-
LocalDate
:表示年月日,例如2021-10-31。 -
LocalTime
:表示時分秒納秒,例如23:59:59.999999999。 -
LocalDateTime
:表示年月日時分秒納秒,例如2021-10-31T23:59:59.999999999。 -
MonthDay
:表示月日,例如10-31。 -
YearMonth
:表示年月,例如2021-10。 -
Year
:表示年,例如2021。
-
- 帶時區(qū)的日期和時間:表示帶有時區(qū)信息的日期和時間,主要有以下幾個類:
-
ZonedDateTime
:表示帶有時區(qū)信息的年月日時分秒納秒,例如2021-10-31T23:59:59.999999999+08:00[Asia/Shanghai]。 -
OffsetDateTime
:表示帶有時區(qū)偏移量的年月日時分秒納秒,例如2021-10-31T23:59:59.999999999+08:00。 -
OffsetTime
:表示帶有時區(qū)偏移量的時分秒納秒,例如23:59:59.999999999+08:00。 -
ZoneId
:表示時區(qū)標(biāo)識符,例如Asia/Shanghai。 -
ZoneOffset
:表示時區(qū)偏移量,例如+08:00。
-
- 機(jī)器時間:表示以Unix時間戳的形式表示的日期和時間,主要有以下幾個類:
-
Instant
:表示一個瞬時點,以1970-01-01T00:00:00Z為基準(zhǔn),以秒和納秒為單位,例如2021-10-31T15:59:59.999999999Z。 -
Duration
:表示兩個瞬時點之間的時間間隔,以秒和納秒為單位,例如PT23H59M59.999999999S。
-
- 人類時間:表示以人類可讀的方式表示的日期和時間,主要有以下幾個類:
-
Period
:表示兩個日期之間的時間間隔,以年月日為單位,例如P1Y2M3D。 -
ChronoUnit
:表示時間單位,例如年、月、日、小時、分鐘、秒等。 -
ChronoField
:表示時間字段,例如年、月、日、小時、分鐘、秒等。 -
DayOfWeek
:表示星期幾,例如MONDAY、TUESDAY等。 -
Month
:表示月份,例如JANUARY、FEBRUARY等。
-
下面我們來看一些使用這些類的示例:
//創(chuàng)建一個本地日期
LocalDate date = LocalDate.of(2021, 10, 31);
System.out.println(date); //輸出2021-10-31
//獲取當(dāng)前的本地日期
LocalDate today = LocalDate.now();
System.out.println(today); //輸出當(dāng)前的日期
//獲取本地日期的年月日
int year = date.getYear();
int month = date.getMonthValue();
int day = date.getDayOfMonth();
System.out.println(year + "-" + month + "-" + day); //輸出2021-10-31
//獲取本地日期的星期幾
DayOfWeek dow = date.getDayOfWeek();
System.out.println(dow); //輸出SUNDAY
//獲取本地日期的一些屬性
boolean isLeapYear = date.isLeapYear(); //是否是閏年
boolean isBefore = date.isBefore(today); //是否在今天之前
boolean isAfter = date.isAfter(today); //是否在今天之后
boolean isEqual = date.isEqual(today); //是否等于今天
System.out.println(isLeapYear); //輸出false
System.out.println(isBefore); //輸出false或true,取決于當(dāng)前日期
System.out.println(isAfter); //輸出false或true,取決于當(dāng)前日期
System.out.println(isEqual); //輸出false或true,取決于當(dāng)前日期
//調(diào)整本地日期
LocalDate nextDay = date.plusDays(1); //加一天
LocalDate nextWeek = date.plusWeeks(1); //加一周
LocalDate nextMonth = date.plusMonths(1); //加一個月
LocalDate nextYear = date.plusYears(1); //加一年
LocalDate firstDayOfMonth = date.with(TemporalAdjusters.firstDayOfMonth()); //獲取當(dāng)月第一天
LocalDate lastDayOfMonth = date.with(TemporalAdjusters.lastDayOfMonth()); //獲取當(dāng)月最后一天
LocalDate firstDayOfNextMonth = date.with(TemporalAdjusters.firstDayOfNextMonth()); //獲取下個月第一天
System.out.println(nextDay); //輸出2021-11-01
System.out.println(nextWeek); //輸出
System.out.println(nextWeek); //輸出2021-11-07 System.out.println(nextMonth); //輸出2021-11-30 System.out.println(nextYear); //輸出2022-10-31 System.out.println(firstDayOfMonth); //輸出2021-10-01 System.out.println(lastDayOfMonth); //輸出2021-10-31 System.out.println(firstDayOfNextMonth); //輸出2021-11-01
//創(chuàng)建一個本地時間
LocalTime time = LocalTime.of(23, 59, 59);
System.out.println(time); //輸出23:59:59
//獲取當(dāng)前的本地時間
LocalTime now = LocalTime.now();
System.out.println(now); //輸出當(dāng)前的時間
//獲取本地時間的時分秒納秒
int hour = time.getHour();
int minute = time.getMinute();
int second = time.getSecond();
int nano = time.getNano();
System.out.println(hour + “:”+minute + “:”+second + “.”+nano); //輸出23:59:59.0
//調(diào)整本地時間
LocalTime nextSecond = time.plusSeconds(1); //加一秒 LocalTime nextMinute = time.plusMinutes(1); //加一分鐘 LocalTime nextHour = time.plusHours(1); //加一小時 LocalTime withNano = time.withNano(999999999); //設(shè)置納秒為999999999 System.out.println(nextSecond); //輸出00:00:00 System.out.println(nextMinute); //輸出00:00:59 System.out.println(nextHour); //輸出00:59:59 System.out.println(withNano); //輸出23:59:59.999999999
//創(chuàng)建一個本地日期時間
LocalDateTime dateTime = LocalDateTime.of(2021, 10, 31, 23, 59, 59);
System.out.println(dateTime); //輸出2021-10-31T23:59:59
//獲取當(dāng)前的本地日期時間
LocalDateTime nowDateTime = LocalDateTime.now();
System.out.println(nowDateTime); //輸出當(dāng)前的日期時間
//獲取本地日期時間的年月日時分秒納秒
int year = dateTime.getYear();
int month = dateTime.getMonthValue();
int day = dateTime.getDayOfMonth();
int hour = dateTime.getHour();
int minute = dateTime.getMinute();
int second = dateTime.getSecond();
int nano = dateTime.getNano();
System.out.println(year + “ -”+month + “-”+day + " " + hour + “:”+minute + “:”+second + “.”+nano); //輸出2021-10-31 23:59:59.0
//調(diào)整本地日期時間
LocalDateTime nextSecond = dateTime.plusSeconds(1); //加一秒 LocalDateTime nextMinute = dateTime.plusMinutes(1); //加一分鐘 LocalDateTime nextHour = dateTime.plusHours(1); //加一小時 LocalDateTime nextDay = dateTime.plusDays(1); //加一天 LocalDateTime nextWeek = dateTime.plusWeeks(1); //加一周 LocalDateTime nextMonth = dateTime.plusMonths(1); //加一個月 LocalDateTime nextYear = dateTime.plusYears(1); //加一年 LocalDateTime firstDayOfMonth = dateTime.with(TemporalAdjusters.firstDayOfMonth()); //獲取當(dāng)月第一天 LocalDateTime lastDayOfMonth = dateTime.with(TemporalAdjusters.lastDayOfMonth()); //獲取當(dāng)月最后一天 LocalDateTime firstDayOfNextMonth = dateTime.with(TemporalAdjusters.firstDayOfNextMonth()); //獲取下個月第一天 System.out.println(nextSecond); //輸出2021-11-01T00:00:00 System.out.println(nextMinute); //輸出2021-11-01T00:00:59 System.out.println(nextHour); //輸出2021-11-01T00:59:59 System.out.println(nextDay); //輸出2021-11-01T23:59:59 System.out.println(nextWeek); //輸出2021-11-07T23:59:59 System.out.println(nextMonth); //輸出2021-11-30T23:59:59 System.out.println(nextYear); //輸出2022-10-31T23:59:59 System.out.println(firstDayOfMonth); //輸出2021-10-01T23:59:59 System.out.println(lastDayOfMonth); //輸出2021-10-31T23:59:59 System.out.println(firstDayOfNextMonth); //輸出2021-11-01T23:59:59
//創(chuàng)建一個帶時區(qū)的日期時間
ZonedDateTime zonedDateTime = ZonedDateTime.of(2021, 10, 31, 23, 59, 59, 0, ZoneId.of(“Asia / Shanghai”));
System.out.println(zonedDateTime); //輸出2021-10-31T23:59:59+08:00[Asia/Shanghai]
//獲取當(dāng)前的帶時區(qū)的日期時間
ZonedDateTime nowZonedDateTime = ZonedDateTime.now();
System.out.println(nowZonedDateTime); //輸出當(dāng)前的帶時區(qū)的日期時間
//獲取帶時區(qū)的日期時間的年月日時分秒納秒和時區(qū)信息
int year = zonedDateTime.getYear();
int month = zonedDateTime.getMonthValue();
int day = zonedDateTime.getDayOfMonth();
int hour = zonedDateTime.getHour();
int minute = zonedDateTime.getMinute();
int second = zonedDateTime.getSecond();
int nano = zonedDateTime.getNano();
ZoneId zoneId = zonedDateTime.getZone();
ZoneOffset zoneOffset = zonedDateTime.getOffset();
System.out.println(year + “ -”+month + “-”+day + " " + hour + “:”+minute + “:”+second + “.”
+nano + " " + zoneId + " " + zoneOffset); //輸出2021-10-31 23:59:59.0 Asia/Shanghai +08:00
//調(diào)整帶時區(qū)的日期時間
ZonedDateTime nextSecond = zonedDateTime.plusSeconds(1); //加一秒 ZonedDateTime nextMinute = zonedDateTime.plusMinutes(1); //加一分鐘 ZonedDateTime nextHour = zonedDateTime.plusHours(1); //加一小時 ZonedDateTime nextDay = zonedDateTime.plusDays(1); //加一天 ZonedDateTime nextWeek = zonedDateTime.plusWeeks(1); //加一周 ZonedDateTime nextMonth = zonedDateTime.plusMonths(1); //加一個月 ZonedDateTime nextYear = zonedDateTime.plusYears(1); //加一年 ZonedDateTime firstDayOfMonth = zonedDateTime.with(TemporalAdjusters.firstDayOfMonth()); //獲取當(dāng)月第一天 ZonedDateTime lastDayOfMonth = zonedDateTime.with(TemporalAdjusters.lastDayOfMonth()); //獲取當(dāng)月最后一天 ZonedDateTime firstDayOfNextMonth = zonedDateTime.with(TemporalAdjusters.firstDayOfNextMonth()); //獲取下個月第一天 ZonedDateTime withZoneId = zonedDateTime.withZoneSameInstant(ZoneId.of(“Europe/London”)); //轉(zhuǎn)換為另一個時區(qū),保持瞬時點不變 System.out.println(nextSecond); //輸出2021-11-01T00:00:00+08:00[Asia/Shanghai] System.out.println(nextMinute); //輸出2021-11-01T00:00:59+08:00[Asia/Shanghai] System.out.println(nextHour); //輸出2021-11-01T00:59:59+08:00[Asia/Shanghai] System.out.println(nextDay); //輸出2021-11-01T23:59:59+08:00[Asia/Shanghai] System.out.println(nextWeek); //輸出2021-11-07T23:59:59+08:00[Asia/Shanghai] System.out.println(nextMonth); //輸出2021-11-30T23:59:59+08:00[Asia/Shanghai] System.out.println(nextYear); //輸出2022-10-31T23:59:59+08:00[Asia/Shanghai] System.out.println(firstDayOfMonth); //輸出2021-10-01T23:59:59+08:00[Asia/Shanghai] System.out.println(lastDayOfMonth); //輸出2021-10-31T23:59:59+08:00[Asia/Shanghai] System.out.println(firstDayOfNextMonth); //輸出2021-11-01T23:59:59+08:00[Asia/Shanghai] System.out.println(withZoneId); //輸出2021-10-31T15:59:59+00:00[Europe/London]
//創(chuàng)建一個機(jī)器時間
Instant instant = Instant.ofEpochSecond(1635705599);
System.out.println(instant); //輸出2021-10-31T15:59:59Z
//獲取當(dāng)前的機(jī)器時間
Instant nowInstant = Instant.now();
System.out.println(nowInstant); //輸出當(dāng)前的機(jī)器時間
//獲取機(jī)器時間的秒和納秒
long epochSecond = instant.getEpochSecond();
int nano = instant.getNano();
System.out.println(epochSecond + “.”+nano); //輸出1635705599.0
//調(diào)整機(jī)器時間
Instant nextSecond = instant.plusSeconds(1);//加一秒
Instant nextMinute = instant.plusMinutes(1);//加一分鐘
Instant nextHour = instant.plusHours(1);//加一小時
Instant nextDay = instant.plus(1, ChronoUnit.DAYS);//加一天
Instant nextWeek = instant.plus(1, ChronoUnit.WEEKS);//加一周
Instant nextMonth = instant.plus(1, ChronoUnit.MONTHS);// 加一個月
Instant nextYear = instant.plus(1, ChronoUnit.YEARS);// 加一年
System.out.println(nextSecond);// 輸出2021-10-31T16:00:00Z
System.out.println(nextMinute);// 輸出2021-10-31T16:00:59Z
System.out.println(nextHour);// 輸出2021-10-31T16:59:59Z
System.out.println(nextDay);// 輸出2021-11-01T15:59:59Z
System.out.println(nextWeek);// 輸出2021-11-07T15:59:59Z
System.out.println(nextMonth);// 輸出2021-11-30T15:59:59Z
System.out.println(nextYear);// 輸出2022-10-31T15:59:59Z
//創(chuàng)建一個人類時間
Period period = Period.of(1, 2, 3);
System.out.println(period); //輸出P1Y2M3D
//獲取人類時間的年月日
int years = period.getYears();
int months = period.getMonths();
int days = period.getDays();
System.out.println(years + " years " + months + " months " + days + " days"); //輸出1 years 2 months 3 days
// 調(diào)整人類時間
Period plusPeriod = period.plus(Period.of(1, 1, 1));//加上另一個時間間隔
Period minusPeriod = period.minus(Period.of(0, 0, 1));//減去另一個時間間隔
Period multipliedPeriod = period.multipliedBy(2);//乘以一個因子
Period normalizedPeriod = period.normalized();//標(biāo)準(zhǔn)化為年和月的形式
System.out.println(plusPeriod);// 輸出P2Y3M4D
System.out.println(minusPeriod); //輸出P1Y2M2D
System.out.println(multipliedPeriod); //輸出P2Y4M6D
System.out.println(normalizedPeriod); //輸出P14M3D
Java8 Date Time API的優(yōu)缺點分析對比
Java8 Date Time API是Java語言發(fā)展的一個重要的進(jìn)步,它們?yōu)镴ava開發(fā)者提供了一套全新的日期和時間處理方式,可以使代碼更加簡潔和清晰,提高了開發(fā)效率和可讀性。同時,它們也為Java引入了一些新的特性和概念,例如不可變性,時區(qū)支持,機(jī)器時間,人類時間等,使得Java更加豐富和強(qiáng)大。
但是,Java8 Date Time API也有一些缺點和限制,例如:
- 兼容性問題:Java8 Date Time API只能在Java8或更高版本的環(huán)境中運(yùn)行,如果需要在低版本的環(huán)境中運(yùn)行,就需要使用其他的工具或者框架來支持。
- 性能問題:Java8 Date Time API在運(yùn)行時會生成一些額外的對象和方法,這可能會影響程序的性能和內(nèi)存占用。雖然Java虛擬機(jī)會進(jìn)行一些優(yōu)化和緩存,但是仍然需要注意避免過度使用或者濫用這些特性。
- 復(fù)雜性問題:Java8 Date Time API提供了很多不同的類和方法來表示不同的日期和時間概念,這可能會導(dǎo)致一些復(fù)雜性和混亂。例如,在不同的場景下需要使用不同的類和方法,例如
LocalDate
,LocalTime
,LocalDateTime
,ZonedDateTime
,Instant
等;在不同的類和方法之間需要進(jìn)行轉(zhuǎn)換,例如使用toInstant()
,ofInstant()
,withZoneSameInstant()
等方法。
因此,在使用Java8 Date Time API時,需要根據(jù)具體的場景和需求來選擇合適的方式,避免盲目地追求新特性而忽略了其他方面的影響。
Java8 Date Time API的使用場景和注意事項
Java8 Date Time API可以用來處理很多與日期和時間相關(guān)的操作,例如:
- 獲取當(dāng)前的日期和時間
- 解析和格式化日期和時間字符串
- 計算日期和時間的差值和間隔
- 調(diào)整日期和時間的值
- 轉(zhuǎn)換日期和時間的時區(qū)
- 比較日期和時間的大小
- 驗證日期和時間的合法性
在使用Java8 Date Time API時,有一些注意事項,例如:文章來源:http://www.zghlxwxcb.cn/news/detail-505840.html
- 使用不可變對象:所有的日期和時間類都是不可變的,這意味著它們的值不能被修改,只能通過創(chuàng)建新的對象來表示不同的值。這樣可以避免線程安全和邏輯錯誤的問題。因此,在使用這些類時,不要試圖修改它們的值,而是使用返回新對象的方法來進(jìn)行操作。
- 使用合適的類:Java8 Date Time API提供了很多不同的類來表示不同的日期和時間概念,這可能會導(dǎo)致一些復(fù)雜性和混亂。因此,在使用這些類時,要根據(jù)具體的場景和需求來選擇合適的類。例如,在不需要時區(qū)信息的場景下,可以使用
LocalDate
,LocalTime
,LocalDateTime
等類;在需要時區(qū)信息的場景下,可以使用ZonedDateTime
,OffsetDateTime
,OffsetTime
等類;在需要以Unix時間戳的形式表示日期和時間的場景下,可以使用Instant
類;在需要以人類可讀的方式表示日期和時間的場景下,可以使用Period
,ChronoUnit
等類。 - 使用正確的方法:Java8 Date Time API提供了很多不同的方法來對日期和時間進(jìn)行操作,這可能會導(dǎo)致一些復(fù)雜性和混亂。因此,在使用這些方法時,要根據(jù)具體的場景和需求來選擇正確的方法。例如,在調(diào)整日期和時間時,可以使用
plus()
,minus()
等方法來加減指定的值;可以使用with()
等方法來設(shè)置指定的字段或者規(guī)則;可以使用truncatedTo()
等方法來截斷指定的單位;在轉(zhuǎn)換日期和時間時,可以使用toInstant()
,ofInstant()
等方法來轉(zhuǎn)換為機(jī)器時間;可以使用withZoneSameInstant()
等方法來轉(zhuǎn)換為帶時區(qū)的日期時間;在解析和格式化日期和時間字符串時,可以使用parse()
,format()
等方法,并且指定合適的格式化器。
?文章來源地址http://www.zghlxwxcb.cn/news/detail-505840.html
到了這里,關(guān)于Java8 時間處理API(Date Time API)詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!