Java中時(shí)間API的基本使用教程
1. 時(shí)區(qū)概念
國際經(jīng)度會議(又稱國際子午線會議)上,規(guī)定將全球劃分為24個(gè)時(shí)區(qū)(東、西各12個(gè)時(shí)區(qū))。規(guī)定英國的格林尼治天文臺舊址為中時(shí)區(qū)(零時(shí)區(qū))、東1-12區(qū),西1-12區(qū)。每個(gè)時(shí)區(qū)橫跨經(jīng)度15度,時(shí)間正好是1小時(shí)。最后的東、西第12區(qū)各跨經(jīng)度7.5度,以東、西經(jīng)180度為界。每個(gè)時(shí)區(qū)的中央經(jīng)線上的時(shí)間就是這個(gè)時(shí)區(qū)內(nèi)統(tǒng)一采用的時(shí)間,稱為區(qū)時(shí),相鄰兩個(gè)時(shí)區(qū)的時(shí)間相差1小時(shí)。英國(格林尼治天文臺舊址)為本初子午線,即零度經(jīng)線。
時(shí)區(qū)的表格劃分
為什么全世界不使用統(tǒng)一的時(shí)間
于各個(gè)地區(qū)所在地球位置不同,所處地球的經(jīng)度不同,故其日出日落的時(shí)間也不相同。在地球上劃定不同的時(shí)區(qū),是為了使時(shí)間和自然現(xiàn)象(白天黑夜)有固定的對應(yīng)。如果全世界用統(tǒng)一的時(shí)間,那么中國的8:00是早上,而美國的8:00卻是晚上了。這樣容易擾亂人自身生理的節(jié)律和對日常生活的安排也及其不方便。人是不能改變白天黑夜的,只好改變衡量白天黑夜的辦法了。
2. 幾種常見的時(shí)間
1、GMT
GMT(格林威治標(biāo)準(zhǔn)時(shí)間):也就是0時(shí)區(qū)的時(shí)間,理論上來說,格林尼治標(biāo)準(zhǔn)時(shí)間的正午是指當(dāng)太陽橫穿格林尼治子午線時(shí)(也就是在格林尼治上空最高點(diǎn)時(shí))的時(shí)間。由于地球在它的橢圓軌道里的運(yùn)動速度不均勻,這個(gè)時(shí)刻可能和實(shí)際的太陽時(shí)相差16分鐘。地球每天的自轉(zhuǎn)是有些不規(guī)則的,而且正在緩慢減速。所以,格林尼治時(shí)間已經(jīng)不再被作為標(biāo)準(zhǔn)時(shí)間使用。現(xiàn)在的標(biāo)準(zhǔn)時(shí)間——協(xié)調(diào)世界時(shí)(UTC)——由原子鐘提供。
2、UTC
UTC(世界協(xié)調(diào)時(shí)間),協(xié)調(diào)世界時(shí)是以原子時(shí)秒長為基礎(chǔ),國際原子時(shí)的準(zhǔn)確度為每日數(shù)納秒,而世界時(shí)的準(zhǔn)確度為每日數(shù)毫秒,現(xiàn)在我們使用的互聯(lián)網(wǎng)就采用該計(jì)時(shí)標(biāo)準(zhǔn)。UTC是GMT微調(diào)過的時(shí)間,我們可以認(rèn)為兩者是一致的。
3、CET
歐洲中部時(shí)間(CET)比世界標(biāo)準(zhǔn)時(shí)間(UTC)早一個(gè)小時(shí),部分歐洲國家和北非國家使用,這個(gè)標(biāo)準(zhǔn)是地理加政治的產(chǎn)物;
4、CST
北京時(shí)間
CET=UTC(GMT) + 1小時(shí)
CST=UTC(GMT) + 8小時(shí)
3. 時(shí)間戳
時(shí)間戳是指格林威治時(shí)間1970年01月01日00時(shí)00分00秒(北京時(shí)間1970年01月01日08時(shí)00分00秒)起至現(xiàn)在的總秒數(shù)(Java中獲得的秒數(shù)是以毫秒為單位的)。
例如現(xiàn)在北京時(shí)間2015-12-31 17:00:00的時(shí)間戳是1451552400,就是指從北京時(shí)間1970-01-01 08:00:00到2015-12-31 17:00:00已經(jīng)過去了1451552400秒。
使用時(shí)間戳有如下好處:
- 時(shí)間戳沒有時(shí)區(qū)概念,比如如果用'2015-12-31 17:00:00'這么一個(gè)字符串表示時(shí)間的話,北京時(shí)間和美國時(shí)間是不一樣的,但是用時(shí)間戳1451552400來表示的話,那就是一定是唯一的時(shí)間,不會有歧義;
- 時(shí)間戳在編程語言中一般是長整形數(shù)據(jù)類型,無論何種編程語言都能認(rèn)識時(shí)間戳,如果用字符串表示時(shí)間,還需要轉(zhuǎn)換。
4. Java中的時(shí)間API
在Java8以前操作時(shí)間的常見API有:
- java.util.Date:表示Java中的日期,但是能夠操作到時(shí)間級別,如今這個(gè)類中的很多方法都已經(jīng)被廢棄,不建議使用;
- java.sql.Date:表示數(shù)據(jù)庫時(shí)間,只能操作到日期,不能讀取和修改時(shí)間;
- java.sql.Time:表示數(shù)據(jù)庫時(shí)間;
- java.sql.Timestamp:時(shí)間戳;
- Calendar:工具類,提供時(shí)間的加減等復(fù)雜操作,支持時(shí)區(qū);
- TimeZone:表示時(shí)區(qū);
- SimpleDateFormat:日期格式化類,非常常用。
Date主要負(fù)責(zé)存儲一個(gè)絕對時(shí)間,并對兩邊提供操作接口。Calendar負(fù)責(zé)對Date中特定信息,比如這個(gè)時(shí)間是該年的第幾個(gè)星期,此外,還可以通過set,add,roll接口來進(jìn)行日期時(shí)間的增減。SimpleDateFormat主要作為一些格式化的輸入輸出。
4.1 Date的簡單列子
Date類比較簡單,支持兩種構(gòu)造函數(shù)。不建議用這個(gè)類進(jìn)行復(fù)雜的操作。如果使用的是Java8,建議使用LocalDate。Date類也提供了和Java 8 API相互轉(zhuǎn)換的接口。
Date date1 = new Date(); Thread.sleep(1000); long nowTime = System.currentTimeMillis(); Date date2 = new Date(nowTime); //Date類和Java 8 API相互轉(zhuǎn)換的接口 Instant instant = date2.toInstant(); Date date3 = Date.from(instant); System.out.println("nowTime:"+nowTime); System.out.println(date1); System.out.println(date2); System.out.println(date3); System.out.println(date2.getTime());
4.2 SimpleDateFormat使用列子
SimpleDateFormat接收一個(gè)String pattern和Local參數(shù)來構(gòu)造對象。其中pattern是預(yù)定義的:
G 年代標(biāo)志符
y 年
M 月
d 日
h 時(shí) 在上午或下午 (1~12)
H 時(shí) 在一天中 (0~23)
m 分
s 秒
S 毫秒
E 星期
D 一年中的第幾天
F 一月中第幾個(gè)星期幾
w 一年中第幾個(gè)星期
W 一月中第幾個(gè)星期
a 上午 / 下午 標(biāo)記符
k 時(shí) 在一天中 (1~24)
K 時(shí) 在上午或下午 (0~11)
z 時(shí)區(qū)
//默認(rèn)的方言 SimpleDateFormat sf = new SimpleDateFormat("G yyyy-MM-dd a z"); SimpleDateFormat sf1 = new SimpleDateFormat("G yyyy-MM-dd a z", Locale.US); SimpleDateFormat sf2 = new SimpleDateFormat("G yyyy-MM-dd a z", Locale.KOREA); String format1 = sf.format(date1); String format2 = sf1.format(date1); String format3 = sf2.format(date1); System.out.println("format1:"+format1); System.out.println("format2:"+format2); System.out.println("format3:"+format3); //解析Date Date date = sf.parse(format1);
4.3 Calendar的使用
Calendar還有許多其他API,比如獲得當(dāng)前月天數(shù),當(dāng)前年天數(shù)等等,需要時(shí)可以查詢使用。
Calendar calendar = Calendar.getInstance(); int year = calendar.get(Calendar.YEAR); // 獲取月,這里需要需要月份的范圍為0~11,因此獲取月份的時(shí)候需要+1才是當(dāng)前月份值 int month = calendar.get(Calendar.MONTH) + 1; // 獲取日 int day = calendar.get(Calendar.DAY_OF_MONTH); // 獲取時(shí) int hour = calendar.get(Calendar.HOUR); // 獲取分 int minute = calendar.get(Calendar.MINUTE); // 獲取秒 int second = calendar.get(Calendar.SECOND); System.out.println("現(xiàn)在是" + year + "年" + month + "月" + day + "日" + hour + "時(shí)" + minute + "分" + second + "秒"); //獲取一個(gè)月后的今天 calendar.add(Calendar.MONTH,1);
4.4 存在的問題
- java的日期/時(shí)間類的定義并不一致,在java.util和java.sql的包中都有日期類,此外用于格式化和解析的類在java.text包中定義。
- java.util.Date同時(shí)包含日期和時(shí)間,而java.sql.Date僅包含日期,將其納入java.sql包并不合理。另外這兩個(gè)類都有相同的名字,這本身就是一個(gè)非常糟糕的設(shè)計(jì)。
- 對于時(shí)間、時(shí)間戳、格式化以及解析,并沒有一些明確定義的類。對于格式化和解析的需求,我們有java.text.DateFormat抽象類,但通常情況下,SimpleDateFormat類被用于此類需求。
- 所有的日期類都是可變的,因此他們都不是線程安全的,這是Java日期類最大的問題之一。
- 日期類并不提供國際化,沒有時(shí)區(qū)支持,因此Java引入了java.util.Calendar和java.util.TimeZone類,但他們同樣存在上述所有的問題。
5. Java8中新添加的時(shí)間API
- java.time包:這是新的Java日期/時(shí)間API的基礎(chǔ)包,所有的主要基礎(chǔ)類都是這個(gè)包的一部分,如:LocalDate, LocalTime, LocalDateTime, Instant, Period, Duration等等。所有這些類都是不可變的和線程安全的,在絕大多數(shù)情況下,這些類能夠有效地處理一些公共的需求。
- java.time.chrono包:這個(gè)包為非ISO的日歷系統(tǒng)定義了一些泛化的API,我們可以擴(kuò)展AbstractChronology類來創(chuàng)建自己的日歷系統(tǒng)。
- java.time.format包:這個(gè)包包含能夠格式化和解析日期時(shí)間對象的類,在絕大多數(shù)情況下,我們不應(yīng)該直接使用它們,因?yàn)閖ava.time包中相應(yīng)的類已經(jīng)提供了格式化和解析的方法。
- java.time.temporal包:這個(gè)包包含一些時(shí)態(tài)對象,我們可以用其找出關(guān)于日期/時(shí)間對象的某個(gè)特定日期或時(shí)間,比如說,可以找到某月的第一天或最后一天。你可以非常容易地認(rèn)出這些方法,因?yàn)樗鼈兌季哂小皐ithXXX”的格式。
- java.time.zone包:這個(gè)包包含支持不同時(shí)區(qū)以及相關(guān)規(guī)則的類。
5.1 LocalDate
//Current Date LocalDate today = LocalDate.now(); System.out.println("Current Date="+today); //Creating LocalDate by providing input arguments LocalDate firstDay_2014 = LocalDate.of(2014, Month.JANUARY, 1); System.out.println("Specific Date="+firstDay_2014); //Try creating date by providing invalid inputs //LocalDate feb29_2014 = LocalDate.of(2014, Month.FEBRUARY, 29); //Exception in thread "main" java.time.DateTimeException: //Invalid date 'February 29' as '2014' is not a leap year //Current date in "Asia/Kolkata", you can get it from ZoneId javadoc LocalDate todayKolkata = LocalDate.now(ZoneId.of("Asia/Kolkata")); System.out.println("Current Date in IST="+todayKolkata); //Getting date from the base date i.e 01/01/1970 LocalDate dateFromBase = LocalDate.ofEpochDay(365); System.out.println("365th day from base date= "+dateFromBase); //2014年的第100天 LocalDate hundredDay2014 = LocalDate.ofYearDay(2014, 100); System.out.println("100th day of 2014="+hundredDay2014);
5.2 LocalTime使用
//Current Time LocalTime time = LocalTime.now(); System.out.println("Current Time="+time); //Creating LocalTime by providing input arguments LocalTime specificTime = LocalTime.of(12,20,25,40); System.out.println("Specific Time of Day="+specificTime); //Try creating time by providing invalid inputs //LocalTime invalidTime = LocalTime.of(25,20); //Exception in thread "main" java.time.DateTimeException: //Invalid value for HourOfDay (valid values 0 - 23): 25 //Current date in "Asia/Kolkata", you can get it from ZoneId javadoc LocalTime timeKolkata = LocalTime.now(ZoneId.of("Asia/Kolkata")); System.out.println("Current Time in IST="+timeKolkata); //java.time.zone.ZoneRulesException: Unknown time-zone ID: IST //LocalTime todayIST = LocalTime.now(ZoneId.of("IST")); //Getting date from the base date i.e 01/01/1970 LocalTime specificSecondTime = LocalTime.ofSecondOfDay(10000); System.out.println("10000th second time= "+specificSecondTime);
5.3 LocalDateTime
//Current Date LocalDateTime today = LocalDateTime.now(); System.out.println("Current DateTime="+today); //Current Date using LocalDate and LocalTime today = LocalDateTime.of(LocalDate.now(), LocalTime.now()); System.out.println("Current DateTime="+today); //Creating LocalDateTime by providing input arguments LocalDateTime specificDate = LocalDateTime.of(2014, Month.JANUARY, 1, 10, 10, 30); System.out.println("Specific Date="+specificDate); //Try creating date by providing invalid inputs //LocalDateTime feb29_2014 = LocalDateTime.of(2014, Month.FEBRUARY, 28, 25,1,1); //Exception in thread "main" java.time.DateTimeException: //Invalid value for HourOfDay (valid values 0 - 23): 25 //Current date in "Asia/Kolkata", you can get it from ZoneId javadoc LocalDateTime todayKolkata = LocalDateTime.now(ZoneId.of("Asia/Kolkata")); System.out.println("Current Date in IST="+todayKolkata); //java.time.zone.ZoneRulesException: Unknown time-zone ID: IST //LocalDateTime todayIST = LocalDateTime.now(ZoneId.of("IST")); //Getting date from the base date i.e 01/01/1970 LocalDateTime dateFromBase = LocalDateTime.ofEpochSecond(10000, 0, ZoneOffset.UTC); System.out.println("10000th second time from 01/01/1970= "+dateFromBase);
5.4 Instant
Instant可以理解為時(shí)間戳。
//Current timestamp Instant timestamp = Instant.now(); System.out.println("Current Timestamp = "+timestamp); //Instant from timestamp Instant specificTime = Instant.ofEpochMilli(timestamp.toEpochMilli()); System.out.println("Specific Time = "+specificTime); //Duration example Duration thirtyDay = Duration.ofDays(30); System.out.println(thirtyDay);
5.5 格式化
需要格式化日期時(shí),我們直接調(diào)用相關(guān)類的format方法即可,如下:
//DateTimeFormatter支持的模式和SimpleDateFormat支持的一致 today.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")); 5.6 對舊時(shí)間API的支持 Date date= new Date();Instant instant = date.toInstant();LocalDateTime pst = LocalDateTime.ofInstant(instant, ZoneId.of(ZoneId.SHORT_IDS.get("PST")));Calendar calendar = Calendar.getInstance();Instant instant1 = calendar.toInstant();LocalDateTime pst1 = LocalDateTime.ofInstant(instant, ZoneId.of(ZoneId.SHORT_IDS.get("PST")));
6. 在東八區(qū)的機(jī)器上獲得美國時(shí)間
美國屬于西5區(qū),比北京時(shí)間晚13個(gè)小時(shí)。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對腳本之家的支持。
相關(guān)文章
SpringBoot集成Tomcat服務(wù)架構(gòu)配置
這篇文章主要為大家介紹了SpringBoot集成Tomcat服務(wù)架構(gòu)配置,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02SpringBoot創(chuàng)建定時(shí)任務(wù)的示例詳解
在Spring Boot中創(chuàng)建定時(shí)任務(wù),通常使用@Scheduled注解,這是Spring框架提供的一個(gè)功能,允許你按照固定的頻率(如每天、每小時(shí)、每分鐘等)執(zhí)行某個(gè)方法,本文給大家介紹了SpringBoot創(chuàng)建定時(shí)任務(wù)的示例,需要的朋友可以參考下2024-04-04如何在SpringBoot項(xiàng)目里進(jìn)行統(tǒng)一異常處理
這篇文章主要介紹了如何在SpringBoot項(xiàng)目里進(jìn)行統(tǒng)一異常處理,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值。需要的小伙伴可以參考一下2022-07-07Layui前后臺交互數(shù)據(jù)獲取java實(shí)例
下面小編就為大家分享一篇Layui前后臺交互數(shù)據(jù)獲取java實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01java實(shí)現(xiàn)隊(duì)列queue數(shù)據(jù)結(jié)構(gòu)詳解
大家好,本篇文章主要講的是java實(shí)現(xiàn)隊(duì)列queue數(shù)據(jù)結(jié)構(gòu)詳解,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下2022-02-02