深入了解Java 8 新特性-日期時間API之LocalDate類
LocalDate
Java 8的LocalDate類是Java日期和時間API的一部分,沒有時間和時區的概念,是線程安全的,用于表示不包含時間的日期,位于java.time包下。
核心方法
now()
按系統默認的時區來獲取當前日期,返回代表當前日期的 LocalDate 實例。
@Test
public void test() {
LocalDate now = LocalDate.now();//當前日期
String format = now.format(DateTimeFormatter.ISO_DATE);
System.out.println(format);//輸出結果:2023-11-23 }
of(...)
接受一個年份(int)和兩個日期(int)作為參數,返回一個表示該年某一天的 LocalDate 實例。日期的第一個參數范圍是1到31,第二個參數范圍是0到23。
public void test2() {
LocalDate localDate = LocalDate.of(2023, 2, 1);//定義一個日期:2023-02-01
LocalDate localDate1 = LocalDate.of(2023, Month.FEBRUARY, 1);//定義一個日期:2023-02-01
boolean equals = localDate1.equals(localDate);
System.out.println(equals);//輸出結果:true
}
ofEpochDay(...)
用于將給定的Unix時間戳(自1970年1月1日以來的天數)轉換為 LocalDate 對象。這個方法返回一個表示該日期的 LocalDate 實例
@Test
public void test3() {
LocalDate localDate2 = LocalDate.ofEpochDay(1);// 假設給定的Unix時間戳為1天
String format = localDate2.format(DateTimeFormatter.ISO_DATE);
System.out.println(format);//輸出結果:1970-01-02
}
ofInstant(...)
Instant 是 Java 中的一個時間類,表示一個瞬時的時間點,精確到納秒。Instant.ofEpochSecond()用于根據秒數(從1970年1月1日00:00:00 UTC開始)創建一個新的 Instant 對象。LocalDate.ofInstant() 可以將給定的 Instant 對象轉換為 LocalDate 對象。
@Test
public void test4() {
Long seconds = 24 * 60 * 60L;//一天的秒數
LocalDate localDate = LocalDate.ofInstant(Instant.ofEpochSecond(seconds), ZoneId.systemDefault());
String format = localDate.format(DateTimeFormatter.ISO_DATE);
System.out.println(format);//輸出結果:1970-01-02
}
ofYearDay(...)
LocalDate.ofYearDay() 用于創建一個表示某一年中特定天數的 LocalDate 對象。方法接受兩個參數:年份和一年中的天數。年份表示自1970年以來的年數,天數表示一年中的第幾天。例如,1月1日是第1天,2月15日是第46天。需要注意的是,這個方法并不會對輸入的天數進行有效性檢查,因此如果輸入的天數超出了給定年份的范圍(例如,在2月輸入了30),那么創建出來的 LocalDate 對象可能不準確。
@Test
public void test5() {
LocalDate localDate = LocalDate.ofYearDay(2023, 2);
String format = localDate.format(DateTimeFormatter.ISO_DATE);
System.out.println(format);//輸出結果:2023-01-02
}
get(...)
LocalDate.get(...) 可以獲取給定日期的特定部分,如年份、月份或日期。具體來說,如果你調用 LocalDate.get(ChronoField),其中 ChronoField 是 java.time.temporal.ChronoField 的實例,那么就會返回該日期對應的特定部分。ChronoField 是一個枚舉類型,包含如 YEAR、MONTH_OF_YEAR、DAY_OF_MONTH 等各種表示時間的字段。
@Test
public void test6() {
LocalDate localDate = LocalDate.now();
int year = localDate.get(ChronoField.YEAR);//得到年份
int month = localDate.get(ChronoField.MONTH_OF_YEAR);//得到月份
int day = localDate.get(ChronoField.DAY_OF_MONTH);//得到當月中第幾天
int weekOfMonth = localDate.get(ChronoField.ALIGNED_WEEK_OF_MONTH);//得到當月的第幾周
System.out.println("year:"+year+",month:"+month+",day:"+day+",weekOfMonth:"+weekOfMonth);
}
getYear()、getMonthValue() 、getDayOfMonth()、getDayOfWeek()、getDayOfYear()
- getYear(): 獲取該日期的年份部分。例如,對于日期 "2023-06-24",該方法將返回2023。
- getMonthValue(): 獲取該日期的月份部分。例如,對于日期 "2023-06-24",該方法將返回6。
- getDayOfMonth(): 獲取該日期中的月份中的日期部分。例如,對于日期 "2023-06-24",該方法將返回24。
- getDayOfWeek(): 獲取該日期是星期幾的信息。該方法將返回一個枚舉類型的值,如MONDAY、TUESDAY等。
- getDayOfYear(): 獲取該日期是當年的第幾天。例如,對于日期 "2023-06-24",該方法將返回175。
@Test
public void test13() {
LocalDate d1 = LocalDate.of(2023, 11, 23);
int year = d1.getYear();//年份:023
int monthValue = d1.getMonthValue();//月份:11
int dayOfMonth = d1.getDayOfMonth();//當月第幾天:23
int dayOfWeek = d1.getDayOfWeek().getValue();//當前周第幾天:4
int dayOfYear = d1.getDayOfYear();//當前年第幾天:327
}
parse(...)
LocalDate的parse()用于從字符串值創建LocalDate的實例。這個方法需要一個參數,即要解析的字符串。該字符串不能為空。此方法返回的是從作為參數傳遞的字符串值獲得的LocalDate實例。
@Test
public void test7() {
LocalDate parse = LocalDate.parse("2023-11-23", DateTimeFormatter.ISO_DATE);
LocalDate parse1 = LocalDate.parse("2023-11-23");
System.out.println(parse1.equals(parse));//輸出結果:true
}
format(...)
LocalDate的format()方法的功能是將日期進行格式化,使用指定的格式化程序。具體來說,這個方法接受一個DateTimeFormatter對象作為參數,這個對象定義了一個日期時間的格式。然后,這個方法會返回一個字符串,該字符串表示按照指定格式化程序格式化的日期。例如,如果我們有一個LocalDate對象代表著2019年5月8日的日期,我們可以使用format方法將它格式化為"MMM dd, yyyy"的格式,即"May 08, 2019"。
@Test
public void test8() {
LocalDate now = LocalDate.now();
String format = now.format(DateTimeFormatter.ISO_DATE);
String format1 = now.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
System.out.println(format);//輸出結果:2023-11-23
System.out.println(format1);//輸出結果:2023/11/23
}
atTime(...)
LocalDate.atTime(hour, minute)的功能是將給定的日期與特定時間進行組合,生成一個LocalDateTime對象。具體來說,這個方法可以將日期部分和時間部分進行組合。例如,如果你有一個LocalDate對象表示今天的日期,并且你想在下午3點鐘添加30分鐘的時間,你可以使用atTime方法來實現這個功能。
@Test
public void test9(){
LocalDate now = LocalDate.now();
LocalDateTime localDateTime = now.atTime(13, 30,59);
String format = localDateTime.format(DateTimeFormatter.ISO_DATE_TIME);
System.out.println(format);//輸出結果:2023-11-23T13:30:59
}
compareTo(...)
LocalDate.compareTo() 用于比較兩個日期對象。具體來說,這個方法將此日期與另一個日期進行比較。如果此日期在時間上大于、等于或小于指定日期,則分別返回正整數、零或負整數。
@Test
public void test10() {
LocalDate t1 = LocalDate.of(2023, 2, 1);//定義一個日期:2023-02-01
LocalDate t2 = LocalDate.of(2023, Month.FEBRUARY, 2);//定義一個日期:2023-02-02
int i = t2.compareTo(t1);//如果t2>t1,,返回正數;如果t2=t1,返回0;如果t2<t1,返回負數;System.out.println(i);//
}
datesUntil(...)
LocalDate.datesUntil(...) 用于計算從當前日期到指定日期之間的日期范圍。該方法返回一個表示該日期范圍的流(Stream)。具體來說,datesUntil(LocalDate endExclusive) 重載形式接受一個終止日期參數,并返回從調用 datesUntil() 方法的 LocalDate 對象(起始日期)到終止日期之前的所有日期的流。
@Test
public void test11() {
LocalDate d1 = LocalDate.of(2023, 2, 26);
LocalDate d2 = LocalDate.of(2023, 3, 26);
Stream<LocalDate> stream = d1.datesUntil(d2);
stream.forEach(System.out::println);//注意:輸出結果不包含結束日期
Stream<LocalDate> stream1 = d1.datesUntil(d2, Period.ofDays(5));//輸出的日期之間的間隔是5天
stream1.forEach(System.out::println);
}
from(...)
LocalDate.from(...) 用于從給定的 TemporalAccessor 對象創建 LocalDate 的實例。TemporalAccessor 是Java時間日期API中的一個接口,它提供了對日期和時間信息的訪問權限,LocalDate、LocalDateTime等都實現了該接口;
@Test
public void test12(){
LocalDateTime nowTime = LocalDateTime.now();
LocalDate from = LocalDate.from(nowTime);
String format = from.format(DateTimeFormatter.ISO_DATE);
System.out.println(format);
}
isAfter(...)、isBefore(...)
LocalDate類的isAfter()和isBefore()方法分別用于檢查一個日期是否在另一個日期之后或之前。
具體來說:
- isAfter(ChronoLocalDate other): 此方法檢查此日期是否在給定日期之后。如果當前日期在給定日期之后,它將返回true,否則返回false。
- isBefore(ChronoLocalDate other): 此方法檢查此日期是否在給定日期之前。如果當前日期在給定日期之前,它將返回true,否則返回false。
@Test
public void test14() {
LocalDate d1 = LocalDate.of(2023, 11, 23);
LocalDate d2 = LocalDate.of(2023, 11, 24);
boolean after = d1.isAfter(d2);
System.out.println(after);//輸出結果:false
boolean before = d1.isBefore(d2);
System.out.println(before);//輸出結果:true
}
isLeapYear()
LocalDate.isLeapYear() 用于判斷給定的年份是否為閏年。閏年的判斷規則是這樣的:如果年份能被4整除但不能被100整除,或者能被400整除,那么這個年份就是閏年。
@Test
public void test15() {
LocalDate d1 = LocalDate.of(2020, 11, 23);
LocalDate d2 = LocalDate.of(2023, 11, 24);
boolean after = d1.isLeapYear();
System.out.println(after);//輸出結果:true
boolean before = d2.isLeapYear();
System.out.println(before);//輸出結果:false
}
lengthOfMonth()、lengthOfYear()
LocalDate的lengthOfMonth()方法用于獲取此LocalDate表示的月份的長度,即該月份的天數。而lengthOfYear()方法則用于獲取此LocalDate表示的年份的長度,即該年份的總天數。這兩個方法都是用于計算日期時間的長度,方便進行日期的計算和比較。
@Test
public void test16() {
LocalDate d1 = LocalDate.of(2020, 2, 23);
int i = d1.lengthOfYear();
System.out.println(i);//輸出結果:366
int j = d1.lengthOfMonth();
System.out.println(j);//輸出結果:29
}
minus(...)、minusDays(...)、minusMonths(...)、minusWeeks(...)、minusYears(...)
這些方法都是Java中LocalDate類的方法,用于進行日期減法操作,返回一個新的LocalDate對象,表示減去指定時間間隔后的日期。
- minus(...):此方法用于減去給定的時間間隔。它接受一個TemporalAmount參數,可以是時間單位(如小時,分鐘,天,月,年等)。
- minusDays(int n):此方法用于減去給定數量的天數。參數n是一個整數,表示要減去的天數。
- minusMonths(int n):此方法用于減去給定數量的月份。參數n是一個整數,表示要減去的月份數。
- minusWeeks(int n):此方法用于減去給定數量的周數。參數n是一個整數,表示要減去的周數。
- minusYears(int n):此方法用于減去給定數量的年數。參數n是一個整數,表示要減去的年數。
@Test
public void test17() {
LocalDate d1 = LocalDate.of(2023, 11, 23);
LocalDate minus = d1.minus(Period.ofDays(3));//當前日期+3天
String format = minus.format(DateTimeFormatter.ISO_DATE);
System.out.println(format);//輸出結果:2023-11-20
LocalDate minus2 = d1.minusDays(3);//當前日期減去3天
String format2 = minus2.format(DateTimeFormatter.ISO_DATE);
System.out.println(format2);//輸出結果:2023-11-20
LocalDate minus3 = d1.minusMonths(1);//當前日期減去1月
String format3 = minus3.format(DateTimeFormatter.ISO_DATE);
System.out.println(format3);//輸出結果:2023-10-23
LocalDate minus4 = d1.minusWeeks(1);//當前日期減去1周
String format4 = minus4.format(DateTimeFormatter.ISO_DATE);
System.out.println(format4);//輸出結果:2023-11-16
LocalDate minus5 = d1.minusYears(1);//當前日期減去1年
String format5 = minus5.format(DateTimeFormatter.ISO_DATE);
System.out.println(format5);//輸出結果:2022-11-23
}
plus(...)、plusDays(...)、plusMonths(...)、plusWeeks(...)、plusYears(...)
LocalDate類的plus(...)方法是一個通用方法,用于在給定時間單位上增加日期。具體的單位可以通過傳遞一個ChronoUnit對象來指定,例如plusDays(int days)、plusMonths(int months)、plusWeeks(int weeks)、plusYears(int years)等。
這些方法用于增加LocalDate對象的日期。例如:
- plusDays(int days):增加給定天數。
- plusMonths(int months):增加給定月數。
- plusWeeks(int weeks):增加給定周數。
- plusYears(int years):增加給定年數。
需要注意的是,這些方法返回的是一個新的LocalDate對象,而不是修改原有的對象。因此,需要將結果賦值給一個變量來使用增加后的日期。
@Test
public void test17() {
LocalDate d1 = LocalDate.of(2023, 11, 23);
LocalDate plus = d1.plus(Period.ofDays(3));//當前日期+3天
String format = plus.format(DateTimeFormatter.ISO_DATE);
System.out.println(format);//輸出結果:2023-11-26
LocalDate plus2 = d1.plusDays(3);//當前日期+3天
String format2 = plus2.format(DateTimeFormatter.ISO_DATE);
System.out.println(format2);//輸出結果:2023-11-26
LocalDate plus3 = d1.plusMonths(1);//當前日期+1月
String format3 = plus3.format(DateTimeFormatter.ISO_DATE);
System.out.println(format3);//輸出結果:2023-12-23
LocalDate plus4 = d1.plusWeeks(1);//當前日期+1周
String format4 = plus4.format(DateTimeFormatter.ISO_DATE);
System.out.println(format4);//輸出結果:2023-11-30
LocalDate plus5 = d1.plusYears(1);//當前日期+1年
String format5 = plus5.format(DateTimeFormatter.ISO_DATE);
System.out.println(format5);//輸出結果:2024-11-23
}
toEpochDay()、toEpochSecond(...)
LocalDate.toEpochDay()的功能是將LocalDate對象轉換為自1970年1月1日以來的天數。這個方法返回的是一個長整型(long)的值,它將此本地日期與指定的時間和作為參數傳遞的偏移量相結合,以計算epoch-second值,該值是從1970-01-01T00:00:00Z開始經過的秒數。
LocalDate.toEpochSecond(LocalTime time, ZoneOffset offset)的功能是將此本地日期與指定的時間和作為參數傳遞的偏移量相結合,以計算epoch-second值。這個方法接受兩個參數,time和offset,它們是本地時間和區域偏移。該方法返回一個長整型(long)的值,表示自1970-01-01T00:00:00Z以來的秒數。
@Test
public void test19() {
LocalDate d1 = LocalDate.of(2023, 11, 23);
long epochDay = d1.toEpochDay();//自1970-01-01年到當前日期的天數
System.out.println(epochDay);
long epochSecond = d1.toEpochSecond(LocalTime.now(), ZoneOffset.ofHours(8));//自1970-01-01到當前日期的秒數;中國位于東8區,區域偏移量為+8
LocalDate localDate = LocalDate.ofInstant(Instant.ofEpochSecond(epochSecond), ZoneId.systemDefault());//把得到秒數再轉換為locaDate
System.out.println(localDate.equals(d1));//輸出結果為true
}
with(...)
LocalDate.with(...)參數是一個 TemporalAdjuster,那么 with 方法會使用傳遞的調整器作為參數來調整此日期時間,并在調整后,返回調整后的日期時間的副本。
TemporalAdjuster是一個Java 8中引入的日期時間API,用于執行復雜的日期操作。它是一個函數式接口,可以在Temporal對象上執行操作,例如獲得下一個星期日、當月的最后一天或下一年的第一天。
TemporalAdjuster有幾個預定義的實現類,包括LocalDate、LocalDateTime和TemporalAdjuster接口本身。這些實現類可以用于調整Temporal對象的日期和時間。
使用TemporalAdjuster可以非常方便地執行各種日期操作,例如:
獲取下一個星期日的日期。
獲取當月的最后一天的日期。
獲取下一年的第一天的日期。
獲取某個日期之后的第N天、第N個星期或第N個月之后的日期。
獲取某個日期和時間之后的下一個工作日、下一個周末或下一個公眾假日。
@Test
public void test20() {
UnaryOperator<LocalDate> unaryOperator = item -> item.minusDays(1);//日期調節邏輯:減去1天
TemporalAdjuster temporalAdjuster = TemporalAdjusters.ofDateAdjuster(unaryOperator);//構造日期調節器類
LocalDate localDate1 = LocalDate.of(2023, 11, 22);//日期:2023-11-22
LocalDate localDate2 = localDate1.with(temporalAdjuster);//執行調節邏輯,并返回調節后結果
String dateStr2 = localDate2.format(DateTimeFormatter.ISO_DATE);
System.out.println(dateStr2);//輸出結果:2023-11-21
}
withDayOfMonth(...)、withDayOfYear(...)
LocalDate類中的withDayOfMonth(...)和withDayOfYear(...)方法用于調整日期的天數。
withDayOfMonth(int dayOfMonth)方法接受一個整數參數,表示月份中的某一天。該方法將此日期調整為給定日期的月份中的指定天數,并返回一個新的日期對象。例如,如果當前日期是2023年3月10日,調用withDayOfMonth(15)將返回一個新的日期對象,表示2023年3月15日。
withDayOfYear(int dayOfYear)方法接受一個整數參數,表示一年中的某一天。該方法將此日期調整為給定年份中的指定天數,并返回一個新的日期對象。例如,如果當前日期是2023年3月10日,調用withDayOfYear(150)將返回一個新的日期對象,表示2023年7月10日(因為7月有31天,所以150減去3月的剩余天數)。
這兩個方法都返回一個新的日期對象,不會修改原始的LocalDate對象。這些方法可以用于執行各種日期調整操作,例如計算下個月的第一天或上個月的最后一天等。
@Test
public void test21() {
LocalDate d1 = LocalDate.of(2023, 11, 22);//日期:2023-11-22
LocalDate d2 = d1.withDayOfMonth(1);
String format = d2.format(DateTimeFormatter.ISO_DATE);
System.out.println(format);//輸出結果:2023-11-01
LocalDate localDate3 = d1.withDayOfYear(1);
String format2 = localDate3.format(DateTimeFormatter.ISO_DATE);
System.out.println(format2);//輸出結果:2023-01-01
}
atStartOfDay()
LocalDate.atStartOfDay() 返回一個 LocalDateTime 實例,該實例表示給定日期的午夜時分。具體來說,它會把日期部分設為當前日期的開始時間(24小時制),時間部分設為 00:00:00。例如,如果今天是2023年6月24日,那么 LocalDate.now().atStartOfDay() 將返回一個表示2023年6月24日00:00:00的 LocalDateTime 對象。
@Test
public void test22() {
LocalDate d= LocalDate.of(2023, 11, 22);
LocalDateTime localDateTime = d.atStartOfDay();
String format = localDateTime.format(DateTimeFormatter.ISO_DATE_TIME);
System.out.println(format);//輸出結果:2023-11-22T00:00:00
}
適用場景
- 日期處理:LocalDate類適用于只需要處理日期的場景,而不考慮時間部分。例如,記錄生日、紀念日、賬單日等。
- 日期計算:可以使用LocalDate類進行日期的加減運算,例如計算兩個日期之間的天數、月數或年數。
- 日期格式化:可以使用LocalDate類和DateTimeFormatter類進行日期的格式化操作,將日期轉換為指定的字符串格式。
- 日期時間轉換:可以將帶有時間的日期轉換為不帶時間的LocalDate對象,或者將LocalDate對象轉換為帶有時間的日期時間對象(如LocalDateTime)。