工作這么久了,對于Java中時(shí)間日期的操作一直很蛋疼,一會用Date,一會用Calendar一會用LocalDateTime,始終沒有認(rèn)真總結(jié)過它們的聯(lián)系與區(qū)別。迷迷糊糊用了好幾年了,今天終于搞清楚了!

          一,Java8日期時(shí)間API產(chǎn)生的前因后果

          1.1 為什么要重新定義一套日期時(shí)間API

          * 操作不方便:java中最初的Date不能直接對指定字段進(jìn)行加減操作也不支持國際化
          ,后來新增了Calendar,但是Calendar又不支持格式化操作,需要轉(zhuǎn)換成Date再進(jìn)行格式化,總之一直在填坑,使用起來一點(diǎn)都不夠優(yōu)雅。
          * 線程不安全:Date,Caleandar,SimpleDateFormat都是可變的,線程不安全的,所以你需要編寫額外的代碼處理線程安全問題。
          1.2 Java8重新定義

          * 對時(shí)間日期相關(guān)操作進(jìn)行細(xì)分:時(shí)間,日期,日期&時(shí)間,時(shí)間戳,時(shí)間段,日期段,格式化等
          * 所有類都是不可變的,線程安全
          * 兼容舊的日期時(shí)間


          1.3Java8兼容舊版本的Date,同時(shí)也規(guī)范了日期時(shí)間的轉(zhuǎn)換流程。



          一,給人讀的( LocalDateTime & LocalDate & LocalTime)


          java8中將時(shí)間和日期進(jìn)行的區(qū)分,用LocalDateTime表示日期和時(shí)間,LocalDate用來表示日期而LocalTime表示時(shí)間。內(nèi)部實(shí)現(xiàn)也非常好理解,
          LocalDateTime = LocalDate + LocalTime,并且他們的內(nèi)部api也一致,所以筆者就結(jié)合工作中的經(jīng)驗(yàn),介紹他們最常見的用法。

          1.1 獲取當(dāng)前時(shí)間
          LocalDateTime localDateTime = LocalDateTime.now(); // 打印結(jié)果:
          2019-12-02T22:09:20.503
          1.2 獲取指定時(shí)間
          // 獲取 2019年12月02號 23 : 59 : 59 LocalDateTime localDateTime2 =
          LocalDateTime.of(2019, 12, 2, 23, 59, 59); // 打印結(jié)果: 2019-12-02T23:59:59
          1.3 日期/時(shí)間加減操作
          // localDateTime2的基礎(chǔ)上加1天零1s LocalDateTime localDateTime3 =
          localDateTime2.plusDays(1).plusSeconds(1); // 打印結(jié)果:2019-12-04T00:00
          1.4 獲取指定的字段(年月日時(shí)分秒,納秒,不支持毫秒)
          System.out.println("現(xiàn)在是: " + localDateTime.getYear() + " 年中的第 " +
          localDateTime.getDayOfYear() +" 天"); // 打印結(jié)果:現(xiàn)在是: 2019 年中的第 336 天 // 畫外音:
          快過年了呀,感覺這一年又沒啥收獲
          二,給計(jì)算機(jī)讀的(Instant)


          小知識:地球上不同地區(qū)經(jīng)度不同會劃分時(shí)區(qū),以零度經(jīng)線上為準(zhǔn)(格林尼治天文臺舊址,UTC時(shí)區(qū))為準(zhǔn),將地球上各個(gè)部分分為了24個(gè)時(shí)區(qū)。向西走,每過一個(gè)時(shí)區(qū),就要把表撥慢1個(gè)小時(shí);同理每向東走一個(gè)時(shí)區(qū),就要把表撥快1個(gè)小時(shí)。最后,中國處于東8區(qū)。

          2.1 獲取UTC時(shí)間(格林尼治時(shí)間)
          Instant instant = Instant.now(); // 打印結(jié)果: 2019-12-02T14:31:41.661Z
          2.2 獲取北京時(shí)間(東8區(qū))
          // OffsetTime表示有時(shí)差的時(shí)間,除了UTC時(shí)間,都是OffsetTime OffsetDateTime offsetDateTime =
          instant.atOffset(ZoneOffset.ofHours(8)); // 打印結(jié)果: 2019-12-02T22:31:41.661+08:00
          2.3 獲取毫秒數(shù)(1970-01-01T00:00:00Z開始計(jì)算)
          long epochMilli = instant.toEpochMilli() // 打印結(jié)果:1575297101661
          2.4 定義時(shí)間戳
          Instant instant1 = Instant.ofEpochSecond(59); // 打印結(jié)果: 1970-01-01T00:00:59Z
          instant2 = instant1.plusSeconds(99) // 打印結(jié)果:1970-01-01T00:02:38Z
          三, 時(shí)間間隔(Duration)

          3.1 計(jì)算日期間隔(參數(shù)位置影響結(jié)果哦)
          Instant instant1 = Instant.now(); Instant instant2 = instant1.plusSeconds(99);
          Duration duration1 = Duration.between(instant1, instant2); Duration duration2 =
          Duration.between(instant2, instant1); // 打印結(jié)果 duration1:PT1M39S // 打印結(jié)果
          duration2:PT-1M-39S long duration1Seconds = duration1.getSeconds(); long
          duration2Seconds = duration1.getSeconds(); // 打印結(jié)果 duration1Seconds: 90 // 打印結(jié)果
          duration2Seconds: -90
          3.2 操作時(shí)間間隔
          Duration duration3 = duration1.plusDays(1); // 打印結(jié)果:PT24H1M39S
          注意 : 僅支持時(shí)間操作(Instant, LocalTime,LocalDateTime),不支持日期(LocalDate)

          四,日期間隔(Period)
          LocalDate localDate1 = LocalDate.now(); LocalDate localDate2 =
          localDate1.plusDays(1); Period period = Period.between(localDate1, localDate2);
          long days = period.getDays(); // 打印結(jié)果 peroid: P1D // 打印結(jié)果 days: 1
          五,日期/時(shí)間校正器(TemporalAdjuster)

          5.1 獲取指定日期或時(shí)間
          LocalDateTime localDateTime1 = LocalDateTime.now(); LocalDateTime
          localDateTime2 = localDateTime.withDayOfMonth(20); // 打印結(jié)果
          localDateTime1:2019-12-02T22:57:47.674 // 打印結(jié)果
          localDateTime2:2019-12-20T22:57:47.674
          5.2 獲取下一個(gè)固定日期(下一個(gè)星期天)
          LocalDateTime localDateTime3 =
          localDateTime.with(TemporalAdjusters.next(DayOfWeek.SUNDAY)); // 打印結(jié)果
          localDateTime33:2019-12-08T23:00:43.101
          5.3 自定義矯正器
          // 獲取下一個(gè)工作日 LocalDateTime localDateTime4 = localDateTime.with((tempDateTime)
          -> { LocalDateTime localDateTime5 = (LocalDateTime) tempDateTime; DayOfWeek
          dayOfWeek = localDateTime5.getDayOfWeek(); if
          (dayOfWeek.equals(DayOfWeek.FRIDAY)) { return localDateTime5.plusDays(3); }
          else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) { return
          localDateTime5.plusDays(2); } else { return localDateTime5.plusDays(1); } });
          // 打印結(jié)果 localDateTime4:2019-12-03T23:00:43.101
          六,日期時(shí)間格式化
          DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd
          HH:mm:ss"); LocalDateTime localDateTime = LocalDateTime.now(); String dateStr
          =dateTimeFormatter.format(localDateTime); // 打印結(jié)果: 2019-12-02 23:08:55
          LocalDateTime localDateTime2 = LocalDateTime.parse(dateStr, dateTimeFormatter);
          // 打印結(jié)果: 2019-12-02T23:08:55 LocalDate localDate = LocalDate.parse(dateStr,
          dateTimeFormatter); // 打印結(jié)果: 2019-12-02
          七,基于Instant進(jìn)行轉(zhuǎn)換


          java8api對于時(shí)間戳,日期時(shí)間以及老版本的Date對象之間的轉(zhuǎn)換也進(jìn)行了兼容和適配,所有的轉(zhuǎn)換操作都可以基于Instant對象進(jìn)行。由于LocalDate,LocalTime和LocalDateTime三個(gè)類的操作完全一樣,所以下文仍使用LocalDateTime演示。

          7.1 時(shí)間戳轉(zhuǎn)LocalDate,LocalDate,LocalDateTime
          long timestamp = Instant.now().toEpochMilli(); LocalDateTime localDateTime =
          Instant.ofEpochMilli(timestamp).atOffset(ZoneOffset.ofHours(8)).toLocalDateTime();
          // 打印結(jié)果:2019-12-02T23:20:25.791
          7.2 LocalDate,LocalDate,LocalDateTime轉(zhuǎn)時(shí)間戳
          LocalDateTime localDateTime = LocalDateTime.now(); long timestamp =
          localDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli(); //
          打印結(jié)果:1575300368099
          7.3 兼容舊版本Date
          LocalDateTime localDateTime3 = LocalDateTime.now();Date date =
          Date.from(localDateTime.atZone(ZoneOffset.ofHours(8)).toInstant());LocalDateTime
          localDateTime4? =
          localDateTime3.atZone(ZoneOffset.ofHours(8)).toLocalDateTime(); // 打印結(jié)果
          date:Mon Dec 02 23:32:53 CST 2019 // 打印結(jié)果 lcoalDateTime4:2019-12-02T23:32:53.188
          八, Q&A


          上一篇問題:在java中通常使用synchronized來實(shí)現(xiàn)方法同步,AQS中通過CAS保證了修改同步狀態(tài)的一致性問題,那么對比synchronized,cas有什么優(yōu)勢不同與優(yōu)勢呢?你還知道其他無鎖并發(fā)的策略嗎?

          8.1 Answer

          Java中的無鎖并發(fā)策略可以分為三種:

          * 基于樂觀鎖的CAS操作
          * Copy On
          Write:寫時(shí)復(fù)制是指:在并發(fā)訪問的情景下,當(dāng)需要修改JAVA中Containers的元素時(shí),不直接修改該容器,而是先復(fù)制一份副本,在副本上進(jìn)行修改。修改完成之后,將指向原來容器的引用指向新的容器(副本容器)
          * ThreadLocal:線程本地存儲,就是為每一個(gè)線程創(chuàng)建一個(gè)變量,只有本線程可以在該變量中查看和修改值。
          8.2 Question

          *
          這是一道送分題:正如上文提到的,Java8之前的日期時(shí)間以及格式化類是線程不安全的,你知道怎么編寫測試代碼嗎?

          *
          如果優(yōu)雅得獲取昨天0點(diǎn)整的毫秒值?

          學(xué)習(xí)Java過程中可能遇到問題和困惑,關(guān)注我vx公眾號 “cruder”
          ,后臺留言,筆者幫你一起解決?。ㄐ枰獙W(xué)習(xí)資料的請關(guān)注后后臺留言,主要都是java相關(guān),java基礎(chǔ),并發(fā),mysql,redis,es,mq等都都有!)

          友情鏈接
          ioDraw流程圖
          API參考文檔
          OK工具箱
          云服務(wù)器優(yōu)惠
          阿里云優(yōu)惠券
          騰訊云優(yōu)惠券
          京東云優(yōu)惠券
          站點(diǎn)信息
          問題反饋
          郵箱:[email protected]
          QQ群:637538335
          關(guān)注微信

                一级毛片a一级毛片免费看黄道婆 | 国产99久久精品 | 欧美性爱天天 | 青青草原在线视频网站 | 天天色电影 |