java 8的java.time包(非常值得推薦)

前言:

用過(guò)java1.8之前原生的日期處理api,你就會(huì)知道用起來(lái)非常麻煩,而且要注意的地方有點(diǎn)多(例如月份是由0開(kāi)始,而且api使用有的不統(tǒng)一,線程不安全等等...),所以在java1.8之前的日期api都不值得去使用,雖然說(shuō)現(xiàn)在都有強(qiáng)大的日期處理的第三方庫(kù),但是會(huì)有兼容性問(wèn)題,那么現(xiàn)在jdk8有了新的時(shí)間處理類,為何不去嘗試一下呢

java.time包下有5個(gè)包組成(大部分人用到基礎(chǔ)包和format包就足夠了)

java.time – 包含值對(duì)象的基礎(chǔ)包
java.time.chrono – 提供對(duì)不同的日歷系統(tǒng)的訪問(wèn)
java.time.format – 格式化和解析時(shí)間和日期
java.time.temporal – 包括底層框架和擴(kuò)展特性
java.time.zone – 包含時(shí)區(qū)支持的類

先看看對(duì)這個(gè)包的概述:

java.time 包是在JDK8新引入的,提供了用于日期签舞、時(shí)間裸准、實(shí)例和周期的主要API谋逻。

java.time包定義的類表示了日期-時(shí)間概念的規(guī)則阀圾,包括instants, durations, dates, times, time-zones and periods潦牛。這些都是基于ISO日歷系統(tǒng)泛领,它又是遵循 Gregorian規(guī)則的一喘。

所有類都是不可變的酝豪、線程安全的涛碑。

再看看對(duì)這些類的介紹:

LocalDateTime:只存儲(chǔ)了日期和時(shí)間,如:2017-03-21T14:02:43.455孵淘。(后面的.455表示毫秒值的最后三位,使用.withNano(0)可把毫秒值設(shè)為0)

LocalDate:只存儲(chǔ)了日期蒲障,如:2017-03-21。

LocalTime:只存儲(chǔ)了時(shí)間瘫证,如:14:02:43.455揉阎。(后面的.455表示毫秒值的最后三位,使用.withNano(0)可把毫秒值設(shè)為0)

Year:只表示年份。

Month:只表示月份背捌。

YearMonth:只表示年月余黎。

MonthDay:只表示月日。

DayOfWeek:只存儲(chǔ)星期的一天载萌。

Instant 相當(dāng)于java.util的Date

Clock 它通過(guò)指定一個(gè)時(shí)區(qū)惧财,然后就可以獲取到當(dāng)前的時(shí)刻巡扇,日期與時(shí)間。Clock可以替換System.currentTimeMillis()與TimeZone.getDefault()垮衷。

ZonedDateTime 可以得到特定時(shí)區(qū)的日期/時(shí)間

Duration 是用來(lái)計(jì)算兩個(gè)日期的時(shí)間差

然后再看看它與java.util.Calendar的api比較:

可以看到在java.time當(dāng)中,星期一的值為1,星期日的值為7,而在Calendar當(dāng)中星期日的值為1,而且java.time中一月份的值為1,Calendar一月份的值為0(多么反人類的設(shè)計(jì),多多少少讓人不自在),如果你會(huì)使用Calendar的話,那么你要上手java.time包也是很快的.

還有一些方法前綴的含義,統(tǒng)一了api:

of:靜態(tài)工廠方法(用類名去調(diào)用)厅翔。

parse:靜態(tài)工廠方法,關(guān)注于解析(用類名去調(diào)用)搀突。

now: 靜態(tài)工廠方法刀闷,用當(dāng)前時(shí)間創(chuàng)建實(shí)例(用類名去調(diào)用)

get:獲取某些東西的值。

is:檢查某些東西的是否是true仰迁。

with:返回一個(gè)部分狀態(tài)改變了的時(shí)間日期對(duì)象拷貝(單獨(dú)一個(gè)with方法,參數(shù)為TemporalAdjusters類型)

plus:返回一個(gè)時(shí)間增加了的甸昏、時(shí)間日期對(duì)象拷貝(如果參數(shù)是負(fù)數(shù)也能夠有minus方法的效果)

minus:返回一個(gè)時(shí)間減少了的、時(shí)間日期對(duì)象拷貝

to:把當(dāng)前時(shí)間日期對(duì)象轉(zhuǎn)換成另外一個(gè)徐许,可能會(huì)損失部分狀態(tài).

at:把這個(gè)對(duì)象與另一個(gè)對(duì)象組合起來(lái)施蜜,例如: date.atTime(time)。

format :根據(jù)某一個(gè)DateTimeFormatter格式化為字符串

新時(shí)間API類都實(shí)現(xiàn)了一系列方法用以完成通用的任務(wù)雌隅,如:加翻默、減、格式化恰起、解析修械、從日期/時(shí)間中提取單獨(dú)部分,等等

time包里面的類實(shí)例如果用了上面的方法而被修改了,那么會(huì)返回一個(gè)新的實(shí)例過(guò)來(lái),而不像Calendar那樣可以在同一個(gè)實(shí)例進(jìn)行不同的修改,體現(xiàn)了不可變


java.time.temporal.ChronoField枚舉類

此枚舉類是作為get方法的參數(shù)獲取時(shí)間的值
它里面的屬性含義有的跟Calendar的成員變量含義差不多,想要了解一下可以看我的關(guān)于Calendar類詳解的文章 ,如果要看很詳細(xì)的講解可以去查看ChronoField類的官方api文檔

演示一下判斷當(dāng)前時(shí)間是屬于上午還是下午:

        LocalDateTime now = LocalDateTime.now();
        switch (now.get(ChronoField.AMPM_OF_DAY)) {
        case 0:
            System.out.println("上午");
        case 1:
            System.out.println("下午");
        }
        //打印 下午

java.time.temporal.TemporalAdjusters類

此類配合java.time基礎(chǔ)包中類的with方法:

LocalDate now = LocalDate.now();

        //當(dāng)前月份的第一天的日期,2017-03-01
        System.out.println(now.with(TemporalAdjusters.firstDayOfMonth())); 
        
        //下一個(gè)月的第一天的日期,2017-04-01
        System.out.println(now.with(TemporalAdjusters.firstDayOfNextMonth())); 
        
        //當(dāng)前月份的最后一天,2017-03-31 --再也不用計(jì)算是28检盼,29肯污,30還是31
        System.out.println(now.with(TemporalAdjusters.lastDayOfMonth())); 

java.time.format.DateTimeFormatter

此類的功能與SimpleDateFormat類的功能類似,此類也是線程安全的,在寫成時(shí)間處理工具類時(shí),可作為靜態(tài)成員變量,而不用每次都new一個(gè)SimpleDateFormat實(shí)例,此類是用來(lái)創(chuàng)建日期顯示的模板,然后對(duì)于日期的格式化和解析還是使用LocalDateTime等類的parse靜態(tài)方法和format方法,其模板屬性格式是和SimpleDateFormat一樣的,請(qǐng)看:

G 年代標(biāo)志符
y 年
M 月
d 日
h 時(shí) (12小時(shí)制)
H 時(shí) (24小時(shí)制)
m 分
s 秒
S 毫秒
E 星期幾
D 一年中的第幾天
F 一月中第幾個(gè)星期(以每個(gè)月1號(hào)為第一周,8號(hào)為第二周為標(biāo)準(zhǔn)計(jì)算)
w 一年中第幾個(gè)星期
W 一月中第幾個(gè)星期(不同于F的計(jì)算標(biāo)準(zhǔn),是以星期為標(biāo)準(zhǔn)計(jì)算星期數(shù),例如1號(hào)是星期三,是當(dāng)月的第一周,那么5號(hào)為星期日就已經(jīng)是當(dāng)月的第二周了)
a 上午 / 下午 標(biāo)記符
k 時(shí) (24小時(shí)制,其值與H的不同點(diǎn)在于,當(dāng)數(shù)值小于10時(shí),前面不會(huì)有0)
K 時(shí) (12小時(shí)值,其值與h的不同點(diǎn)在于,當(dāng)數(shù)值小于10時(shí),前面不會(huì)有0)
z 時(shí)區(qū)

對(duì)于此類使用先來(lái)個(gè)簡(jiǎn)單的新舊api對(duì)比演示:

1 .Date轉(zhuǎn)String

        //使用Date和SimpleDateFormat
        SimpleDateFormat simpleDateFormat = 
                        new SimpleDateFormat("G yyyy年MM月dd號(hào) E a hh時(shí)mm分ss秒");
        
        String format = simpleDateFormat.format(new Date());
        
        System.out.println(format); 
        //打印: 公元 2017年03月21號(hào) 星期二 下午 06時(shí)38分20秒
        
        //使用jdk1.8 LocalDateTime和DateTimeFormatter
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter pattern = 
                   DateTimeFormatter.ofPattern("G yyyy年MM月dd號(hào) E a hh時(shí)mm分ss秒");
        String format = now.format(pattern);
        System.out.println(format);
      //打印: 公元 2017年03月21號(hào) 星期二 下午 06時(shí)38分20秒

2 .String轉(zhuǎn)Date

         //使用Date和SimpleDateFormat
        SimpleDateFormat simpleDateFormat = 
                  new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        
        Date date = simpleDateFormat.parse("2017-12-03 10:15:30");
        
        System.out.println(simpleDateFormat.format(date));
        //打印 2017-12-03 10:15:30
        //使用jdk1.8 LocalDateTime和DateTimeFormatter
        DateTimeFormatter pattern = 
                    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        //嚴(yán)格按照ISO yyyy-MM-dd驗(yàn)證,03寫成3都不行
        LocalDateTime dt = LocalDateTime.parse("2017-12-03 10:15:30",pattern); 
        
        System.out.println(dt.format(pattern));

下面演示一次java.time基礎(chǔ)包中的類的使用:

1. java.time.LocalDateTime

此類顯示的是年月日時(shí)分秒(默認(rèn)的格式為:2017-01-01T01:01:01.555)

LocalDateTime now = LocalDateTime.now();
        System.out.println(now.toString());
        System.out.println(now.getYear());
        System.out.println(now.getMonthValue());
        System.out.println(now.getDayOfMonth());
        System.out.println(now.getHour()); //24小時(shí)制
        System.out.println(now.getMinute());
        System.out.println(now.getSecond());
        System.out.println(now.getNano()); //毫秒值的后三位作為前三位后面補(bǔ)6個(gè)零
      
打印的結(jié)果為:  
2017-03-21T20:26:18.317
2017
3
21
20
26
18
317000000
//能夠自定義時(shí)間
        LocalDateTime time = LocalDateTime.of(2017, 1, 1, 1, 1,1);
        System.out.println(time); //2017-01-01T01:01:01
        
        //使用plus方法增加年份
        LocalDateTime time = LocalDateTime.of(2017, 1, 1, 1, 1,1);

        //改變時(shí)間后會(huì)返回一個(gè)新的實(shí)例nextYearTime
        LocalDateTime nextYearTime = time.plusYears(1); 

        System.out.println(nextYearTime); //2018-01-01T01:01:01
        
        //使用minus方法減年份
        LocalDateTime time = LocalDateTime.of(2017, 1, 1, 1, 1,1);
        LocalDateTime lastYearTime = time.minusYears(1);
        System.out.println(lastYearTime); //2016-01-01T01:01:01
        
        //使用with方法設(shè)置月份
        LocalDateTime time = LocalDateTime.of(2017, 1, 1, 1, 1,1);
        LocalDateTime changeTime = time.withMonth(12);
        System.out.println(changeTime); //2017-12-01T01:01:01
        
        //判斷當(dāng)前年份是否閏年
        System.out.println("isLeapYear :" + time.isLeapYear());
        
        //判斷當(dāng)前日期屬于星期幾
        LocalDateTime time = LocalDateTime.now();
        DayOfWeek dayOfWeek = time.getDayOfWeek();
        System.out.println(dayOfWeek); //WEDNESDAY

2. java.time.LocalDate

此類顯示的是年月日(默認(rèn)的格式為:2017-01-01)
用法與LocalDateTime類大致一樣

3. java.time.LocalTime

此類顯示的是時(shí)分秒和毫秒值的后三位(21:26:35.693)
用法與LocalDateTime類大致一樣

3. java.time.Instant

此類功能和java.util.Date類類似

Instant now = Instant.now();
        System.out.println(now.toEpochMilli());//獲取當(dāng)前時(shí)間的毫秒值
        System.out.println(now.isAfter(now)); //當(dāng)前時(shí)間是否在參數(shù)中的時(shí)間之后
        System.out.println(now.isBefore(now));//當(dāng)前時(shí)間是否在參數(shù)中的時(shí)間之前

        //當(dāng)前時(shí)間與參數(shù)中的時(shí)間進(jìn)行對(duì)比,在參數(shù)的時(shí)間之前,相同,之后的值分別是(-1,0,1)
        System.out.println(now.compareTo(now));
        

        //用一個(gè)時(shí)間戳去創(chuàng)建一個(gè)Instance實(shí)例,用法和new Date(時(shí)間戳)創(chuàng)建一個(gè)Date實(shí)例是一樣的
        Instant ofEpochMilli = Instant.ofEpochMilli(System.currentTimeMillis()); 

       System.out.println(now.getEpochSecond());//獲取當(dāng)前時(shí)間的秒

4.java.time.Instant和java.time.LocalDateTime互轉(zhuǎn)

4.1 Instance轉(zhuǎn)LocalDateTime
Instant instant = Instant.ofEpochMilli(System.currentTimeMillis());
        
        ZoneId systemDefault = ZoneId.systemDefault();
        
        LocalDateTime now = LocalDateTime.ofInstant(instant, systemDefault);
        
        System.out.println(now); //2017-03-22T13:44:34.979
4.2 LocalDateTime轉(zhuǎn)Instance
LocalDateTime now = LocalDateTime.now();

        ZoneId systemDefault = ZoneId.systemDefault();
        
        Instant instant = now.atZone(systemDefault).toInstant();
        
        System.out.println(instant.toEpochMilli()); //1490163685578

4. java.time.Duration

此類用來(lái)計(jì)算兩同類型日期的時(shí)間差,看演示:

LocalDateTime start = LocalDateTime.of(2017, 1, 1, 1, 1);
LocalDateTime end = LocalDateTime.of(2017, 2, 1, 1, 1);

        Duration result = Duration.between(start, end);
        System.out.println(result.toDays()); //31
        System.out.println(result.toHours()); //744
        System.out.println(result.toMinutes()); //44640
        System.out.println(result.toMillis()); //2678400000
        System.out.println(result.toNanos()); //2678400000000000

其中between方法計(jì)算兩日期時(shí)間差,兩參數(shù)都是Temporal接口類型的日期,來(lái)看看Temporal的實(shí)現(xiàn)類:

HijrahDate, Instant, JapaneseDate, LocalDate, LocalDateTime, LocalTime, MinguoDate, OffsetDateTime, OffsetTime, ThaiBuddhistDate, Year, YearMonth, ZonedDateTime


java.util.Date或java.util.Calendar到新庫(kù)類的轉(zhuǎn)換

轉(zhuǎn)換可通過(guò)下面的方法進(jìn)行吨枉。
Date.toInstant()
Date.from(Instant)
Calendar.toInstant()


JDBC

最新JDBC映射將把數(shù)據(jù)庫(kù)的日期類型和Java 8的新類型關(guān)聯(lián)起來(lái):

date -> LocalDate
time -> LocalTime
timestamp -> LocalDateTime
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末仇箱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子东羹,更是在濱河造成了極大的恐慌剂桥,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件属提,死亡現(xiàn)場(chǎng)離奇詭異权逗,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)冤议,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門斟薇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人恕酸,你說(shuō)我怎么就攤上這事堪滨。” “怎么了蕊温?”我有些...
    開(kāi)封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵袱箱,是天一觀的道長(zhǎng)遏乔。 經(jīng)常有香客問(wèn)我,道長(zhǎng)发笔,這世上最難降的妖魔是什么盟萨? 我笑而不...
    開(kāi)封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮了讨,結(jié)果婚禮上捻激,老公的妹妹穿的比我還像新娘。我一直安慰自己前计,他們只是感情好胞谭,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著男杈,像睡著了一般丈屹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上势就,一...
    開(kāi)封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音脉漏,去河邊找鬼苞冯。 笑死,一個(gè)胖子當(dāng)著我的面吹牛侧巨,可吹牛的內(nèi)容都是我干的舅锄。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼司忱,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼皇忿!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起坦仍,我...
    開(kāi)封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鳍烁,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后繁扎,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體幔荒,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年梳玫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了爹梁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡提澎,死狀恐怖姚垃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情盼忌,我是刑警寧澤积糯,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布掂墓,位于F島的核電站,受9級(jí)特大地震影響絮宁,放射性物質(zhì)發(fā)生泄漏梆暮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一绍昂、第九天 我趴在偏房一處隱蔽的房頂上張望啦粹。 院中可真熱鬧,春花似錦窘游、人聲如沸唠椭。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)贪嫂。三九已至,卻和暖如春艾蓝,著一層夾襖步出監(jiān)牢的瞬間力崇,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工赢织, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留亮靴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓于置,卻偏偏與公主長(zhǎng)得像茧吊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子八毯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 最近項(xiàng)目中用到自定義日歷組件搓侄,找來(lái)找去,最后發(fā)現(xiàn)GitHub的material-calendarview這個(gè)項(xiàng)目最...
    colin2017閱讀 1,501評(píng)論 0 0
  • /Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home...
    光劍書架上的書閱讀 3,856評(píng)論 2 8
  • Java 語(yǔ)言支持的類型分為兩類:基本類型和引用類型话速。整型(byte 1, short 2, int 4, lon...
    xiaogmail閱讀 1,345評(píng)論 0 10
  • Java 8 - New Date/Time API 1 Java 8-概述2 Java 8 - Lambda表達(dá)...
    全能程序猿閱讀 829評(píng)論 0 1
  • 其實(shí)不喜歡喝酒讶踪,但是同事聚會(huì),難免會(huì)喝一點(diǎn)泊交。四年在一起俊柔,一兩個(gè)月都會(huì)聚一次。 現(xiàn)在腦袋發(fā)熱活合,不確定能說(shuō)什么雏婶,只是想...
    楠苜閱讀 285評(píng)論 2 2