Java8 日期、時(shí)間操作代碼
一、簡(jiǎn)介
在Java8之前,日期時(shí)間API一直被開(kāi)發(fā)者詬病,包括:java.util.Date是可變類(lèi)型,SimpleDateFormat非線程安全等問(wèn)題。故此,Java8引入了一套全新的日期時(shí)間處理API,新的API基于ISO標(biāo)準(zhǔn)日歷系統(tǒng)?!?/p>
Java 8通過(guò)發(fā)布新的Date-Time API (JSR 310)來(lái)進(jìn)一步加強(qiáng)對(duì)日期與時(shí)間的處理。
在舊版的 Java 中,日期時(shí)間 API 存在諸多問(wèn)題,其中有:
1、非線程安全 − java.util.Date 是非線程安全的,所有的日期類(lèi)都是可變的,這是Java日期類(lèi)最大的問(wèn)題之一。
2、設(shè)計(jì)很差 − Java的日期/時(shí)間類(lèi)的定義并不一致,在java.util和java.sql的包中都有日期類(lèi),此外用于格式化和解析的類(lèi)在java.text包中定義。java.util.Date同時(shí)包含日期和時(shí)間,而java.sql.Date僅包含日期,將其納入java.sql包并不合理。另外這兩個(gè)類(lèi)都有相同的名字,這本身就是一個(gè)非常糟糕的設(shè)計(jì)。
3、時(shí)區(qū)處理麻煩 − 日期類(lèi)并不提供國(guó)際化,沒(méi)有時(shí)區(qū)支持,因此Java引入了java.util.Calendar和java.util.TimeZone類(lèi),但他們同樣存在上述所有的問(wèn)題。
Java 8 在 java.time 包下提供了很多新的 API。以下為兩個(gè)比較重要的 API:
Local(本地) − 簡(jiǎn)化了日期時(shí)間的處理,沒(méi)有時(shí)區(qū)的問(wèn)題。
Zoned(時(shí)區(qū)) − 通過(guò)制定的時(shí)區(qū)處理日期時(shí)間。
新的java.time包涵蓋了所有處理日期,時(shí)間,日期/時(shí)間,時(shí)區(qū),時(shí)刻(instants),過(guò)程(during)與時(shí)鐘(clock)的操作。
本地化日期時(shí)間 API
LocalDate/LocalTime 和 LocalDateTime 類(lèi)可以在處理時(shí)區(qū)不是必須的情況。代碼如下:
import java.time.LocalDate; import java.time.LocalTime; import java.time.LocalDateTime; import java.time.Month; public class Java8Tester { public static void main(String args[]){ Java8Tester java8tester = new Java8Tester(); java8tester.testLocalDateTime(); } public void testLocalDateTime(){ // 獲取當(dāng)前的日期時(shí)間 LocalDateTime currentTime = LocalDateTime.now(); System.out.println("當(dāng)前時(shí)間: " + currentTime); LocalDate date1 = currentTime.toLocalDate(); System.out.println("date1: " + date1); Month month = currentTime.getMonth(); int day = currentTime.getDayOfMonth(); int seconds = currentTime.getSecond(); System.out.println("月: " + month +", 日: " + day +", 秒: " + seconds); LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012); System.out.println("date2: " + date2); // 12 december 2014 LocalDate date3 = LocalDate.of(2014, Month.DECEMBER, 12); System.out.println("date3: " + date3); // 22 小時(shí) 15 分鐘 LocalTime date4 = LocalTime.of(22, 15); System.out.println("date4: " + date4); // 解析字符串 LocalTime date5 = LocalTime.parse("20:15:30"); System.out.println("date5: " + date5); } }
執(zhí)行以上腳本,輸出結(jié)果為:
$ javac Java8Tester.java
$ java Java8Tester
當(dāng)前時(shí)間: 2016-04-15T16:55:48.668
date1: 2016-04-15
月: APRIL, 日: 15, 秒: 48
date2: 2012-04-10T16:55:48.668
date3: 2014-12-12
date4: 22:15
date5: 20:15:30
使用時(shí)區(qū)的日期時(shí)間API
如果我們需要考慮到時(shí)區(qū),就可以使用時(shí)區(qū)的日期時(shí)間API:
import java.time.ZonedDateTime; import java.time.ZoneId; public class Java8Tester { public static void main(String args[]){ Java8Tester java8tester = new Java8Tester(); java8tester.testZonedDateTime(); } public void testZonedDateTime(){ // 獲取當(dāng)前時(shí)間日期 ZonedDateTime date1 = ZonedDateTime.parse("2015-12-03T10:15:30+05:30[Asia/Shanghai]"); System.out.println("date1: " + date1); ZoneId id = ZoneId.of("Europe/Paris"); System.out.println("ZoneId: " + id); ZoneId currentZone = ZoneId.systemDefault(); System.out.println("當(dāng)期時(shí)區(qū): " + currentZone); } }
執(zhí)行以上腳本,輸出結(jié)果為:
$ javac Java8Tester.java
$ java Java8Tester
date1: 2015-12-03T10:15:30+08:00[Asia/Shanghai]
ZoneId: Europe/Paris
當(dāng)期時(shí)區(qū): Asia/Shanghai
二、日期初識(shí)
示例1: 獲取當(dāng)天日期
Java 8中的 LocalDate 用于表示當(dāng)天日期。和java.util.Date不同,它只有日期,不包含時(shí)間。
public static void main(String[] args) { LocalDate date = LocalDate.now(); System.out.println("當(dāng)前日期=" + date); }
示例2: 構(gòu)造指定日期
調(diào)用工廠方法LocalDate.of()創(chuàng)建任意日期, 該方法需要傳入年、月、日做參數(shù),返回對(duì)應(yīng)的LocalDate實(shí)例。這個(gè)方法的好處是沒(méi)再犯老API的設(shè)計(jì)錯(cuò)誤,比如年度起始于1900,月份是從0開(kāi)始等等
public static void main(String[] args) { LocalDate date = LocalDate.of(2000, 1, 1); System.out.println("千禧年=" + date); }
示例3: 獲取年月日信息
public static void main(String[] args) { LocalDate date = LocalDate.now(); System.out.printf("年=%d, 月=%d, 日=%d", date.getYear(), date.getMonthValue(), date.getDayOfMonth()); }
示例4: 比較兩個(gè)日期是否相等
public static void main(String[] args) { LocalDate now = LocalDate.now(); LocalDate date = LocalDate.of(2018, 9, 24); System.out.println("日期是否相等=" + now.equals(date)); }
三、時(shí)間初識(shí)
示例: 獲取當(dāng)前時(shí)間
Java 8中的 LocalTime 用于表示當(dāng)天時(shí)間。和java.util.Date不同,它只有時(shí)間,不包含日期。
public static void main(String[] args) { LocalTime time = LocalTime.now(); System.out.println("當(dāng)前時(shí)間=" + time); }
四、比較與計(jì)算
示例1: 日期時(shí)間計(jì)算
Java8提供了新的plusXxx()方法用于計(jì)算日期時(shí)間增量值,替代了原來(lái)的add()方法。新的API將返回一個(gè)全新的日期時(shí)間示例,需要使用新的對(duì)象進(jìn)行接收。
public static void main(String[] args) { // 時(shí)間增量 LocalTime time = LocalTime.now(); LocalTime newTime = time.plusHours(2); System.out.println("newTime=" + newTime); // 日期增量 LocalDate date = LocalDate.now(); LocalDate newDate = date.plus(1, ChronoUnit.WEEKS); System.out.println("newDate=" + newDate); }
示例2: 日期時(shí)間比較
Java8提供了isAfter()、isBefore()用于判斷當(dāng)前日期時(shí)間和指定日期時(shí)間的比較
public static void main(String[] args) { LocalDate now = LocalDate.now(); LocalDate date1 = LocalDate.of(2000, 1, 1); if (now.isAfter(date1)) { System.out.println("千禧年已經(jīng)過(guò)去了"); } LocalDate date2 = LocalDate.of(2020, 1, 1); if (now.isBefore(date2)) { System.out.println("2020年還未到來(lái)"); } }
五、時(shí)區(qū)
示例: 創(chuàng)建帶有時(shí)區(qū)的日期時(shí)間
Java 8不僅分離了日期和時(shí)間,也把時(shí)區(qū)分離出來(lái)了?,F(xiàn)在有一系列單獨(dú)的類(lèi)如ZoneId來(lái)處理特定時(shí)區(qū),ZoneDateTime類(lèi)來(lái)表示某時(shí)區(qū)下的時(shí)間。
public static void main(String[] args) { // 上海時(shí)間 ZoneId shanghaiZoneId = ZoneId.of("Asia/Shanghai"); ZonedDateTime shanghaiZonedDateTime = ZonedDateTime.now(shanghaiZoneId); // 東京時(shí)間 ZoneId tokyoZoneId = ZoneId.of("Asia/Tokyo"); ZonedDateTime tokyoZonedDateTime = ZonedDateTime.now(tokyoZoneId); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); System.out.println("上海時(shí)間: " + shanghaiZonedDateTime.format(formatter)); System.out.println("東京時(shí)間: " + tokyoZonedDateTime.format(formatter)); }
六、格式化
示例1: 使用預(yù)定義格式解析與格式化日期
public static void main(String[] args) { // 解析日期 String dateText = "20180924"; LocalDate date = LocalDate.parse(dateText, DateTimeFormatter.BASIC_ISO_DATE); System.out.println("格式化之后的日期=" + date); // 格式化日期 dateText = date.format(DateTimeFormatter.ISO_DATE); System.out.println("dateText=" + dateText); }
示例2: 日期和字符串的相互轉(zhuǎn)換
public static void main(String[] args) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 日期時(shí)間轉(zhuǎn)字符串 LocalDateTime now = LocalDateTime.now(); String nowText = now.format(formatter); System.out.println("nowText=" + nowText); // 字符串轉(zhuǎn)日期時(shí)間 String datetimeText = "1999-12-31 23:59:59"; LocalDateTime datetime = LocalDateTime.parse(datetimeText, formatter); System.out.println(datetime); }
七、相關(guān)類(lèi)說(shuō)明
Instant 時(shí)間戳
Duration 持續(xù)時(shí)間、時(shí)間差
LocalDate 只包含日期,比如:2018-09-24
LocalTime 只包含時(shí)間,比如:10:32:10
LocalDateTime 包含日期和時(shí)間,比如:2018-09-24 10:32:10
Peroid 時(shí)間段
ZoneOffset 時(shí)區(qū)偏移量,比如:+8:00
ZonedDateTime 帶時(shí)區(qū)的日期時(shí)間
Clock 時(shí)鐘,可用于獲取當(dāng)前時(shí)間戳
java.time.format.DateTimeFormatter 時(shí)間格式化類(lèi)
java8時(shí)間使用小結(jié)
//LocalDate代表一個(gè)IOS格式(yyyy-MM-dd)的日期 獲取當(dāng)前的日期: LocalDate localDate = LocalDate.now();//LocalDate: 表示沒(méi)有時(shí)區(qū)的日期, LocalDate是不可變并且線程安全的 System.out.println("localDate: " + localDate);//localDate: 2017-08-24 //LocalDate可以指定特定的日期,調(diào)用of或parse方法返回該實(shí)例: System.out.println(LocalDate.of(2017, 07, 20));//2017-07-20 System.out.println(LocalDate.parse("2017-07-20"));//2017-07-20 //為今天添加一天,也就是獲取明天 System.out.println(LocalDate.now().plusDays(1));//2017-08-25 //為今天添加7天,也就是獲取一個(gè)禮拜之后的今天 System.out.println(LocalDate.now().plusWeeks(1));//2017-08-31 //為今天添加一個(gè)月,也就是獲取一個(gè)月后的今天 System.out.println(LocalDate.now().plusMonths(1));//2017-09-24 //為今天添加一年,也就是獲取一年后的今天 System.out.println(LocalDate.now().plusYears(1));//2018-08-24 //從今天減去一個(gè)月 (跟加同理 可獲取減去1天、 1個(gè)禮拜、 1年之后的時(shí)間) System.out.println(LocalDate.now().minus(1, ChronoUnit.MONTHS));//2017-07-24 System.out.println(LocalDate.now().minusMonths(1));//2017-07-24 //解析日期 2017-07-20,獲取每周中的星期和每月中的日 等 System.out.println("周四: " +LocalDate.parse("2017-07-20").getDayOfWeek());//THURSDAY System.out.println("日: " +LocalDate.parse("2017-07-20").getDayOfMonth());//20 System.out.println("月: " +LocalDate.parse("2017-07-20").getMonthValue());//7 System.out.println("年: " +LocalDate.parse("2017-07-20").getYear());//2017 System.out.println("月: " +LocalDate.parse("2017-07-20").getMonth());//JULY //今年是不是閏年(閏年判斷) System.out.println(LocalDate.now().isLeapYear());//false //判斷是否在日期之前或之后: System.out.println(LocalDate.parse("2017-07-20").isAfter(LocalDate.parse("2017-07-21")));//false System.out.println(LocalDate.parse("2017-07-20").isBefore(LocalDate.parse("2017-07-21")));//true System.out.println(LocalDate.parse("2217-07-20").isBefore(LocalDate.parse("2017-07-21")));//false //獲取這個(gè)月的第一天: System.out.println(LocalDate.parse("2017-07-20").with(TemporalAdjusters.firstDayOfMonth()));//2017-07-01 //獲取下個(gè)月的第一天,等等。。 System.out.println(LocalDate.parse("2017-07-20").with(TemporalAdjusters.firstDayOfNextMonth()));//2017-08-01 System.out.println(LocalDate.parse("2017-07-20").with(TemporalAdjusters.lastDayOfMonth()));//2017-07-31 System.out.println(LocalDate.parse("2017-07-20").with(TemporalAdjusters.firstDayOfNextYear()));//2018-01-01 System.out.println(LocalDate.parse("2017-07-20").with(TemporalAdjusters.firstDayOfYear()));//2017-01-01 //判斷今天是否是我的生日,例如我的生日是 2006-07-20 LocalDate birthday = LocalDate.of(2006, 07, 20); MonthDay birthdayMd = MonthDay.of(birthday.getMonth(),birthday.getDayOfMonth()); MonthDay today=MonthDay.from(LocalDate.now()); System.out.println("今天是否是我的生日: " + today.equals(birthdayMd));//false System.out.println("=======LocalTime表示一個(gè)時(shí)間,而不是日期==========="); //獲取現(xiàn)在的時(shí)間 09:52:19.446 System.out.println("現(xiàn)在的時(shí)間: " +LocalTime.now()); //將一個(gè)字符串時(shí)間解析為L(zhǎng)ocalTime System.out.println( LocalTime.parse("15:02"));//15:02 //使用靜態(tài)方法of創(chuàng)建一個(gè)時(shí)間 System.out.println(LocalTime.of(16, 02));//16:02 //使用解析字符串的方式并添加一小時(shí),輸出16:02 System.out.println(LocalTime.parse("15:02").plus(1, ChronoUnit.HOURS));//16:02 System.out.println(LocalTime.parse("15:02").plus(10, ChronoUnit.MINUTES));//15:12 //獲取時(shí)間的小時(shí)、分鐘 System.out.println(LocalTime.parse("15:02").getHour());//15 System.out.println(LocalTime.parse("15:02").getMinute());//2 //檢查一個(gè)時(shí)間是否在另一個(gè)時(shí)間之前、之后 System.out.println(LocalTime.parse("15:02").isAfter(LocalTime.parse("14:02")));//true System.out.println(LocalTime.parse("15:02").isBefore(LocalTime.parse("14:02")));//false //每天的開(kāi)始與結(jié)束時(shí)間 System.out.println(LocalTime.MAX);//23:59:59.999999999 System.out.println(LocalTime.MIN);//00:00 System.out.println("=======LocalDateTime是用來(lái)表示日期和時(shí)間的,這是一個(gè)最常用的類(lèi)之一==========="); System.out.println("現(xiàn)在: " +LocalDateTime.now());//2017-08-24T10:31:03.600 //LocalDateTime也提供了相關(guān)API來(lái)對(duì)日期和時(shí)間進(jìn)行增減操作 System.out.println("明天的現(xiàn)在: " +LocalDateTime.now().plusDays(1));//2017-08-25T10:33:05.363 //獲取當(dāng)前月份等等 System.out.println(LocalDateTime.now().getMonthValue());//8 System.out.println(LocalDateTime.now().getMonth());//AUGUST System.out.println(LocalDateTime.now().getYear());//2017 //日期格式化 System.out.println("======日期格式化======="); LocalDateTime now = LocalDateTime.now(); DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); System.out.println("默認(rèn)格式化: " + now); System.out.println("自定義格式化: " + now.format(dateTimeFormatter)); LocalDateTime localDateTime = LocalDateTime.parse("2017-07-20 15:27:44", dateTimeFormatter); System.out.println("字符串轉(zhuǎn)LocalDateTime: " + localDateTime.format(dateTimeFormatter)); DateTimeFormatter dateTimeFormatter_s = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String dateString = dateTimeFormatter_s.format(LocalDate.now()); System.out.println("日期轉(zhuǎn)字符串: " + dateString); //日期和周期 Period類(lèi)用于修改給定日期或獲得的兩個(gè)日期之間的區(qū)別。 LocalDate initialDate = LocalDate.parse("2017-07-20"); LocalDate finalDate = initialDate.plus(Period.ofDays(5));//給初始化的日期添加5天 System.out.println("初始化日期: " + initialDate);//2017-07-20 System.out.println("加日期之后: " + finalDate);//2017-07-25 //周期(Period)API中提供給我們可以比較兩個(gè)日期的差別,像下面這樣獲取差距天數(shù):(同理可以獲取兩個(gè)時(shí)間相差的小時(shí)、周、月、年) long between = ChronoUnit.DAYS.between(initialDate, finalDate); System.out.println("差距天數(shù): " + between);//5 //如何將Date類(lèi)轉(zhuǎn)換為Java8中的時(shí)間類(lèi) //Date和Instant互相轉(zhuǎn)換 Date date = Date.from(Instant.now()); Instant instant = date.toInstant(); //Date轉(zhuǎn)換為L(zhǎng)ocalDateTime<br><br>ZoneId zoneId = ZoneId.systemDefault();
LocalDateTime localDateTime = new Date().toInstant().atZone(zoneId).toLocalDateTime();
System.out.println("LocalDateTime = " + localDateTime);
//LocalDateTime轉(zhuǎn)Date Date date_s = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); System.out.println(date_s); //LocalDate轉(zhuǎn)Date Date date_t = Date.from(LocalDate.now().atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()); System.out.println(date_t);
到此這篇關(guān)于Java8 日期、時(shí)間操作代碼的文章就介紹到這了,更多相關(guān)Java8 日期、時(shí)間內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
LRU算法及Apache?LRUMap源碼實(shí)例解析
這篇文章主要給大家介紹了關(guān)于LRU算法及Apache?LRUMap源碼解析的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-11-11使用jekins自動(dòng)構(gòu)建部署java maven項(xiàng)目的方法步驟
這篇文章主要介紹了使用jekins自動(dòng)構(gòu)建部署java maven項(xiàng)目的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01java自定義類(lèi)加載器如何實(shí)現(xiàn)類(lèi)隔離
這篇文章主要介紹了java自定義類(lèi)加載器如何實(shí)現(xiàn)類(lèi)隔離問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11java中char類(lèi)型轉(zhuǎn)換成int類(lèi)型的2種方法
這篇文章主要給大家介紹了關(guān)于java中char類(lèi)型轉(zhuǎn)換成int類(lèi)型的2種方法,因?yàn)閖ava是一門(mén)強(qiáng)類(lèi)型語(yǔ)言,所以在數(shù)據(jù)運(yùn)算中會(huì)存在類(lèi)型轉(zhuǎn)換,需要的朋友可以參考下2023-07-07servlet實(shí)現(xiàn)文件上傳、預(yù)覽、下載、刪除功能
這篇文章主要為大家詳細(xì)介紹了servlet實(shí)現(xiàn)文件上傳、預(yù)覽、下載、刪除功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09Springboot整合spring-boot-starter-data-elasticsearch的過(guò)程
本文詳細(xì)介紹了Springboot整合spring-boot-starter-data-elasticsearch的過(guò)程,包括版本要求、依賴添加、實(shí)體類(lèi)添加、索引的名稱、分片、副本設(shè)置等,同時(shí),還介紹了如何使用ElasticsearchRepository類(lèi)進(jìn)行增刪改查操作2024-10-10