在Java 8以前,日期和時(shí)間處理一直被廣大java程序員抱怨太難用,首先是java.util和java.sql中,都包含Date類,如果要進(jìn)行時(shí)間格式化,還需要java.text.DateFormat類處理。同時(shí)java.util.Date中既包含了日期,又包含了時(shí)間,所以java8新的日期和時(shí)間庫(kù),很好的解決了以前日期和時(shí)間類的很多弊端。并且也借鑒了第三方日期庫(kù)joda很多的優(yōu)點(diǎn)。
在java8中,java.time包下主要包含下面幾個(gè)主要的類:
Instant:時(shí)間戳
Duration:持續(xù)時(shí)間,時(shí)間差
LocalDate:只包含日期,比如:2016-10-20
LocalTime:只包含時(shí)間,比如:23:12:10
LocalDateTime:包含日期和時(shí)間,比如:2016-10-20 23:14:21
Period:時(shí)間段
ZoneOffset:時(shí)區(qū)偏移量,比如:+8:00
ZonedDateTime:帶時(shí)區(qū)的時(shí)間
Clock:時(shí)鐘,比如獲取目前美國(guó)紐約的時(shí)間
以及java.time.format包中的
DateTimeFormatter:時(shí)間格式化
下面我們通過(guò)例子來(lái)看如何使用java8新的日期時(shí)間庫(kù)
1、獲取今天的日期
LocalDate todayDate = LocalDate.now();
System.out.println("今天的日期:"+todayDate);
//結(jié)果
今天的日期:2016-10-20
2、指定日期,進(jìn)行相應(yīng)操作
//取2016年10月的第1天
LocalDate firstDay = oneday.with(TemporalAdjusters.firstDayOfMonth());
System.out.println(firstDay);
//取2016年10月的第1天,另外一種寫法
LocalDate firstDay2 = oneday.withDayOfMonth(1);
System.out.println(firstDay2);
//取2016年10月的最后1天,不用考慮大月,小月,平年,閏年
LocalDate lastDay = oneday.with(TemporalAdjusters.lastDayOfMonth());
System.out.println(lastDay);
//當(dāng)前日期+1天
LocalDate tomorrow = oneday.plusDays(1);
System.out.println(tomorrow);
//判斷是否為閏年
boolean isLeapYear = tomorrow.isLeapYear();
System.out.println(isLeapYear);
//運(yùn)行結(jié)果
2016-10-20
2016-10-01
2016-10-01
2016-10-31
2016-10-21
true
3、生日檢查或者賬單日檢查
開(kāi)發(fā)過(guò)程中,經(jīng)常需要為過(guò)生日的用戶送上一些祝福,例如,用戶的生日為1990-10-12,如果今天是2016-10-12,那么今天就是用戶的生日(按公歷/身份證日期來(lái)算),那么通過(guò)java8新的日期庫(kù),我們?cè)撊绾蝸?lái)進(jìn)行判斷?
在java8中,可以使用MonthDay,該類不包含年份信息,當(dāng)然還有一個(gè)類是YearMonth
LocalDate birthday = LocalDate.of(1990, 10, 12);
MonthDay birthdayMd = MonthDay.of(birthday.getMonth(), birthday.getDayOfMonth());
MonthDay today = MonthDay.from(LocalDate.of(2016, 10, 12));
System.out.println(today.equals(birthdayMd));
//結(jié)果
true
4、獲取當(dāng)前的時(shí)間
日期主要是使用LocalTime,該類不包含日期,只有時(shí)間信息
//獲取當(dāng)前的時(shí)間
LocalTime nowTime = LocalTime.now(); //結(jié)果14:29:40.558
//如果不想顯示毫秒
LocalTime nowTime2 = LocalTime.now().withNano(0); //14:43:14
//指定時(shí)間
LocalTime time = LocalTime.of(14, 10, 21); //14:10:21
LocalTime time2 = LocalTime.parse("12:00:01"); // 12:00:01
//當(dāng)前時(shí)間增加2小時(shí)
LocalTime nowTimePlus2Hour = nowTime.plusHours(2); //16:47:23.144
//或者
LocalTime nowTimePlus2Hour2 = nowTime.plus(2, ChronoUnit.HOURS);
5、日期前后比較
比較2個(gè)日期哪個(gè)在前,哪個(gè)在后,java8 LocalDate提供了2個(gè)方法,isAfter(),isBefore
LocalDate today = LocalDate.now();
LocalDate specifyDate = LocalDate.of(2015, 10, 20);
System.out.println(today.isAfter(specifyDate)); //true
6、處理不同時(shí)區(qū)的時(shí)間
java8中,將日期,時(shí)間,時(shí)區(qū)都很好的進(jìn)行了分離。
//查看當(dāng)前的時(shí)區(qū)
ZoneId defaultZone = ZoneId.systemDefault();
System.out.println(defaultZone); //Asia/Shanghai
//查看美國(guó)紐約當(dāng)前的時(shí)間
ZoneId america = ZoneId.of("America/New_York");
LocalDateTime shanghaiTime = LocalDateTime.now();
LocalDateTime americaDateTime = LocalDateTime.now(america);
System.out.println(shanghaiTime); //2016-11-06T15:20:27.996
System.out.println(americaDateTime); //2016-11-06T02:20:27.996 ,可以看到美國(guó)與北京時(shí)間差了13小時(shí)
//帶有時(shí)區(qū)的時(shí)間
ZonedDateTime americaZoneDateTime = ZonedDateTime.now(america);
System.out.println(americaZoneDateTime); //2016-11-06T02:23:44.863-05:00[America/New_York]
7、比較兩個(gè)日期之前時(shí)間差
在項(xiàng)目中,經(jīng)常需要比較兩個(gè)日期之間相差幾天,或者相隔幾個(gè)月,我們可以使用java8的Period來(lái)進(jìn)行處理。
LocalDate today = LocalDate.now();
LocalDate specifyDate = LocalDate.of(2015, 10, 2);
Period period = Period.between(specifyDate, today);
System.out.println(period.getDays()); //4
System.out.println(period.getMonths()); //1
System.out.println(specifyDate.until(today, ChronoUnit.DAYS)); //401
//輸出結(jié)果
4
1
401
我們可以看到,我們使用Period類比較天數(shù),比較奇怪,他返回的值,并不是2個(gè)日期之間總共的天數(shù)差,而是一個(gè)相對(duì)天數(shù)差,比如,5月1日,和10月2日,他比較的是僅僅2個(gè)天之間的差,那1號(hào)和2號(hào),相差1天,而實(shí)際上,因?yàn)橹虚g相差了好幾個(gè)月,所以真正的天數(shù)差肯定不是1天,所以我們可以使用until,并指明精度單位是days,就可以計(jì)算真正的天數(shù)差了。
8、日期時(shí)間格式解析、格式化
在java8之前,我們進(jìn)行時(shí)間格式化主要是使用SimpleDateFormat,而在java8中,主要是使用DateTimeFormatter,java8中,預(yù)定義了一些標(biāo)準(zhǔn)的時(shí)間格式,我們可以直接將時(shí)間轉(zhuǎn)換為標(biāo)準(zhǔn)的時(shí)間格式:
String specifyDate = "20151011";
DateTimeFormatter formatter = DateTimeFormatter.BASIC_ISO_DATE;
LocalDate formatted = LocalDate.parse(specifyDate,formatter);
System.out.println(formatted);
//輸出
2015-10-11
當(dāng)然,很多時(shí)間標(biāo)準(zhǔn)的時(shí)間格式可能也不滿足我們的要求,我們需要轉(zhuǎn)為自定義的時(shí)間格式
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("YYYY MM dd");
System.out.println(formatter2.format(LocalDate.now()));
//結(jié)果
2015 10 11
9、java8 時(shí)間類與Date類的相互轉(zhuǎn)化
在轉(zhuǎn)換中,我們需要注意,因?yàn)閖ava8之前Date是包含日期和時(shí)間的,而LocalDate只包含日期,LocalTime只包含時(shí)間,所以與Date在互轉(zhuǎn)中,勢(shì)必會(huì)丟失日期或者時(shí)間,或者會(huì)使用起始時(shí)間。如果轉(zhuǎn)LocalDateTime,那么就不存在信息誤差。
//Date與Instant的相互轉(zhuǎn)化
Instant instant = Instant.now();
Date date = Date.from(instant);
Instant instant2 = date.toInstant();
//Date轉(zhuǎn)為L(zhǎng)ocalDateTime
Date date2 = new Date();
LocalDateTime localDateTime2 = LocalDateTime.ofInstant(date2.toInstant(), ZoneId.systemDefault());
//LocalDateTime轉(zhuǎn)Date
LocalDateTime localDateTime3 = LocalDateTime.now();
Instant instant3 = localDateTime3.atZone(ZoneId.systemDefault()).toInstant();
Date date3 = Date.from(instant);
//LocalDate轉(zhuǎn)Date
//因?yàn)長(zhǎng)ocalDate不包含時(shí)間,所以轉(zhuǎn)Date時(shí),會(huì)默認(rèn)轉(zhuǎn)為當(dāng)天的起始時(shí)間,00:00:00
LocalDate localDate4 = LocalDate.now();
Instant instant4 = localDate4.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
Date date4 = Date.from(instant);
總結(jié),其實(shí)想說(shuō)的這,這篇文章是一篇難產(chǎn)很久的文章,自從十一假期后,一直找不到寫代碼的感覺(jué),所以這篇文章拖了1個(gè)月。
?聲明:除非注明,本站所有文章皆為原創(chuàng),轉(zhuǎn)載請(qǐng)以鏈接形式標(biāo)明本文地址。
?轉(zhuǎn)載請(qǐng)注明來(lái)源:https://www.rjkf.cn/java8-date-localdate/