Java中時(shí)間處理API全解析(從JDK7到JDK8)
前言
在 Java 開發(fā)領(lǐng)域,時(shí)間處理是一項(xiàng)極為常見且關(guān)鍵的需求。無論是記錄用戶的操作時(shí)間,還是實(shí)現(xiàn)定時(shí)任務(wù)等功能,都離不開對時(shí)間 API 的靈活運(yùn)用。本文圍繞 JDK7 與 JDK8 中的時(shí)間處理類,結(jié)合學(xué)習(xí)內(nèi)容,詳細(xì)梳理Date、SimpleDateFormat、Calendar以及 JDK8 全新時(shí)間類的使用與演進(jìn),助力開發(fā)者掌握 Java 時(shí)間處理的核心要點(diǎn)。
一、JDK7 時(shí)間處理基石 ——Date 類
(一)Date 類基本功能
Date類位于java.util包下,是 JDK7 中用于表示特定瞬間的時(shí)間類,其精度可達(dá)到毫秒級別。它的出現(xiàn),為 Java 處理時(shí)間提供了基礎(chǔ)能力。
創(chuàng)建Date對象的方式較為簡單,通過無參構(gòu)造方法可以直接獲取當(dāng)前系統(tǒng)時(shí)間:
import java.util.Date; public class DateDemo { public static void main(String[] args) { Date now = new Date(); System.out.println("當(dāng)前系統(tǒng)時(shí)間:" + now); } }
上述代碼的輸出結(jié)果類似Thu Jul 23 10:00:00 CST 2025,能夠直觀地呈現(xiàn)當(dāng)下的時(shí)間信息。
(二)Date 類的局限性
盡管Date類能夠獲取和表示時(shí)間,但在實(shí)際開發(fā)過程中,它的短板逐漸顯現(xiàn)出來:
可讀性差:直接輸出的時(shí)間格式對于普通用戶而言不夠友好,難以快速理解其中包含的具體年月日時(shí)分秒信息。
操作不便捷:如果想要獲取年、月、日等單獨(dú)的時(shí)間字段,需要結(jié)合其他類(如Calendar),無法直接從Date對象中簡潔地提取,這無疑增加了時(shí)間處理的復(fù)雜度。
二、格式化時(shí)間好幫手 ——SimpleDateFormat 類
(一)格式化與解析原理
SimpleDateFormat是java.text包下的一個(gè)類,它專門用于對Date類進(jìn)行格式化(將Date對象轉(zhuǎn)換為指定格式的字符串)和解析(將符合格式的字符串轉(zhuǎn)換回Date對象)操作。通過自定義的模式字符串,SimpleDateFormat能夠靈活地控制時(shí)間的展示樣式。
(二)常用模式符號
掌握以下這些模式符號,就能根據(jù)需求定制出所需的時(shí)間格式:
- y:表示年(例如yyyy表示四位年,yy表示兩位年)
- M:表示月(MM會補(bǔ)兩位,1 月會顯示為01)
- d:表示日(dd會補(bǔ)兩位)
- H:表示時(shí)(采用 24 小時(shí)制,HH會補(bǔ)兩位)
- m:表示分(mm會補(bǔ)兩位)
- s:表示秒(ss會補(bǔ)兩位)
(三)格式化操作示例
將Date對象轉(zhuǎn)換為 “yyyy - MM - dd HH:mm:ss” 格式的字符串:
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class SimpleDateFormatParseDemo { public static void main(String[] args) { String timeStr = "2025-07-23 10:20:00"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { Date date = sdf.parse(timeStr); System.out.println("解析后的 Date 對象:" + date); } catch (ParseException e) { e.printStackTrace(); } } }
運(yùn)行上述代碼后,時(shí)間會按照設(shè)定的格式輸出,例如2025-07-23 10:15:30,大大提升了時(shí)間的可讀性。
(四)解析操作示例
將符合格式的字符串轉(zhuǎn)換回Date對象:
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class SimpleDateFormatParseDemo { public static void main(String[] args) { String timeStr = "2025-07-23 10:20:00"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { Date date = sdf.parse(timeStr); System.out.println("解析后的 Date 對象:" + date); } catch (ParseException e) { e.printStackTrace(); } } }
需要注意的是,在進(jìn)行解析操作時(shí),字符串的格式必須和模式嚴(yán)格匹配,否則會拋出ParseException異常,因此要做好異常處理工作。
三、更靈活的時(shí)間操作工具 ——Calendar 類
(一)Calendar 類特點(diǎn)
Calendar是java.util包下的一個(gè)抽象類,與Date類相比,它提供了更為豐富的時(shí)間操作方法,能夠方便地獲取、設(shè)置時(shí)間字段(如年、月、日、時(shí)等),還支持對時(shí)間進(jìn)行加減運(yùn)算。
(二)獲取 Calendar 實(shí)例
由于Calendar是抽象類,不能直接通過new關(guān)鍵字來創(chuàng)建實(shí)例,而是需要通過getInstance方法來獲取:
import java.util.Calendar; public class CalendarDemo { public static void main(String[] args) { Calendar calendar = Calendar.getInstance(); } }
該方法返回的是GregorianCalendar實(shí)例(即公歷),能夠適配大部分的使用場景。
(三)常用方法及示例
獲取時(shí)間字段:
int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH) + 1; // 月份從 0 開始,需要加 1 int day = calendar.get(Calendar.DAY_OF_MONTH); int hour = calendar.get(Calendar.HOUR_OF_DAY); // 采用24小時(shí)制 int minute = calendar.get(Calendar.MINUTE); int second = calendar.get(Calendar.SECOND); System.out.println("當(dāng)前時(shí)間:" + year + "年" + month + "月" + day + "日 " + hour + ":" + minute + ":" + second);
設(shè)置時(shí)間:
calendar.set(Calendar.YEAR, 2026); calendar.set(Calendar.MONTH, Calendar.JANUARY); // 直接使用常量,更具語義性 calendar.set(Calendar.DAY_OF_MONTH, 1); // 也可以一次性設(shè)置多個(gè)字段 calendar.set(2026, Calendar.FEBRUARY, 14, 18, 30, 0);
時(shí)間加減:
calendar.add(Calendar.DAY_OF_MONTH, 7); // 將當(dāng)前時(shí)間加 7 天 calendar.add(Calendar.HOUR, -3); // 將當(dāng)前時(shí)間減 3 小時(shí)
這些操作使得時(shí)間調(diào)整變得靈活高效,能夠輕松實(shí)現(xiàn)諸如計(jì)算 “一周后的時(shí)間”“三小時(shí)前的時(shí)間” 等需求。
(四)與 Date 類相互轉(zhuǎn)換
Date轉(zhuǎn)Calendar:calendar.setTime(date);
Calendar轉(zhuǎn)Date:Date date = calendar.getTime();
通過這種轉(zhuǎn)換方式,能夠在兩種時(shí)間表示形式之間進(jìn)行切換,以適配不同 API 的需求。
四、JDK8 時(shí)間類 —— 新時(shí)代的時(shí)間處理方案
JDK8 引入了全新的時(shí)間 API(位于java.time包下),解決了 JDK7 時(shí)間類存在的諸多痛點(diǎn),如線程不安全、設(shè)計(jì)復(fù)雜等問題,以下是其中的核心類介紹:
(一)LocalDate、LocalTime、LocalDateTime
LocalDate:專注于處理日期(年、月、日),示例如下:
import java.time.LocalDate; public class LocalDateDemo { public static void main(String[] args) { LocalDate nowDate = LocalDate.now(); System.out.println("當(dāng)前日期:" + nowDate); LocalDate 指定日期 = LocalDate.of(2025, 7, 23); int year = 指定日期.getYear(); int month = 指定日期.getMonthValue(); int day = 指定日期.getDayOfMonth(); LocalDate 加 5 天 = 指定日期.plusDays(5); LocalDate 減 3 月 = 指定日期.minusMonths(3); } }
LocalTime:用于處理時(shí)間(時(shí)、分、秒、納秒),其用法與LocalDate類似,能夠獲取、設(shè)置、加減時(shí)間字段。
LocalDateTime:融合了日期和時(shí)間的信息,功能更為全面,例如:
import java.time.LocalDateTime; public class LocalDateTimeDemo { public static void main(String[] args) { LocalDateTime nowDateTime = LocalDateTime.now(); LocalDateTime 指定時(shí)間 = LocalDateTime.of(2025, 7, 23, 10, 30, 0); // 支持豐富的時(shí)間調(diào)整,如調(diào)整到下一個(gè)周一、設(shè)置秒數(shù)等 LocalDateTime 下周一 = nowDateTime.with(TemporalAdjusters.next(DayOfWeek.MONDAY)); } }
(二)ZoneId 與 ZonedDateTime—— 時(shí)區(qū)處理
ZoneId:用于表示時(shí)區(qū),例如ZoneId.of("Asia/Shanghai")可以獲取上海時(shí)區(qū)。
ZonedDateTime:表示帶時(shí)區(qū)的時(shí)間,它結(jié)合了LocalDateTime和ZoneId,能夠解決跨時(shí)區(qū)時(shí)間處理的問題:
import java.time.ZoneId; import java.time.ZonedDateTime; public class ZonedDateTimeDemo { public static void main(String[] args) { ZonedDateTime 上海時(shí)間 = ZonedDateTime.now(ZoneId.of("Asia/Shanghai")); ZonedDateTime 紐約時(shí)間 = ZonedDateTime.now(ZoneId.of("America/New_York")); // 時(shí)區(qū)轉(zhuǎn)換 ZonedDateTime 上海轉(zhuǎn)紐約 = 上海時(shí)間.withZoneSameInstant(ZoneId.of("America/New_York")); } }
(三)DateTimeFormatter—— 線程安全的格式化工具
DateTimeFormatter是 JDK8 中用于格式化和解析時(shí)間的類,它是線程安全的,可以替代SimpleDateFormat。示例如下:
import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class DateTimeFormatterDemo { public static void main(String[] args) { LocalDateTime now = LocalDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String formatStr = now.format(formatter); System.out.println("格式化后:" + formatStr); LocalDateTime parseTime = LocalDateTime.parse("2025-07-23 10:45:00", formatter); } }
五、JDK7 與 JDK8 時(shí)間類對比與選擇
(一)對比
線程安全:JDK7 中的SimpleDateFormat是線程不安全的,而 JDK8 的時(shí)間類都是線程安全的。
易用性:JDK8 時(shí)間類的方法更加直觀、語義更清晰,例如LocalDate.plusDays比Calendar.add更容易理解。
設(shè)計(jì)合理性:JDK8 時(shí)間類的職責(zé)單一(LocalDate負(fù)責(zé)處理日期、LocalTime負(fù)責(zé)處理時(shí)間),而 JDK7 的時(shí)間類功能較為混雜。
(二)選擇建議
新開發(fā)項(xiàng)目:優(yōu)先使用 JDK8 的時(shí)間類,以享受其簡潔、安全的 API。
維護(hù)老項(xiàng)目:如果使用的是 JDK7 的時(shí)間類,要注意線程安全問題(例如對SimpleDateFormat進(jìn)行加鎖或使用ThreadLocal);也可以逐步將其遷移到 JDK8 的時(shí)間類,以提升代碼質(zhì)量。
六、總結(jié)
從 JDK7 的Date、SimpleDateFormat、Calendar,到 JDK8 的全新時(shí)間 API,Java 的時(shí)間處理能力在不斷演進(jìn)。在學(xué)習(xí)過程中,要理解不同類的適用場景,掌握核心方法,在實(shí)際開發(fā)中根據(jù)需求靈活選擇合適的時(shí)間類。JDK8 的時(shí)間類代表了未來的發(fā)展趨勢,值得深入學(xué)習(xí)和運(yùn)用,從而讓時(shí)間處理變得更加高效、簡潔。隨著對 Java 時(shí)間 API 的掌握愈發(fā)熟練,在處理日期時(shí)間相關(guān)需求時(shí),也能更加得心應(yīng)手,為構(gòu)建健壯、易維護(hù)的 Java 程序奠定堅(jiān)實(shí)的基礎(chǔ)。
到此這篇關(guān)于Java中時(shí)間處理API全解析(從JDK7到JDK8)的文章就介紹到這了,更多相關(guān)Java時(shí)間處理API內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實(shí)戰(zhàn)花店商城系統(tǒng)的實(shí)現(xiàn)流程
只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+Springboot+Maven+mybatis+Vue+Mysql實(shí)現(xiàn)一個(gè)花店商城系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平2022-01-01SpringBoot整合WxJava開啟消息推送的實(shí)現(xiàn)
本文主要介紹了SpringBoot整合WxJava開啟消息推送,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-03-03java poi sax方式處理大數(shù)據(jù)量excel文件
這篇文章主要介紹了java poi sax方式處理大數(shù)據(jù)量excel文件,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01Java8 將一個(gè)List<T>轉(zhuǎn)為Map<String,T>的操作
這篇文章主要介紹了Java8 將一個(gè)List<T>轉(zhuǎn)為Map<String, T>的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02Spring Boot整合FTPClient線程池的實(shí)現(xiàn)示例
這篇文章主要介紹了Spring Boot整合FTPClient線程池的實(shí)現(xiàn)示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12SpringBoot配置返回?cái)?shù)據(jù)不存在null的問題小結(jié)
文章介紹了在Spring Boot項(xiàng)目中使用Jackson序列化器處理JSON數(shù)據(jù)時(shí)遇到的問題,特別是如何配置Jackson以返回不包含null值的JSON響應(yīng),并探討了Jackson的三種主要JSON處理方法,感興趣的朋友一起看看吧2025-02-02SpringBoot項(xiàng)目中枚舉類型字段與前端和數(shù)據(jù)庫的交互方法
最近做的這個(gè)項(xiàng)目中,用到了大量的枚舉類,下面這篇文章主要給大家介紹了關(guān)于SpringBoot項(xiàng)目中枚舉類型字段與前端和數(shù)據(jù)庫的交互方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07