日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java8 ,LocalDate,LocalDateTime处理日期和时间工具类,

發布時間:2023/12/8 java 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java8 ,LocalDate,LocalDateTime处理日期和时间工具类, 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java8 ,LocalDate,LocalDateTime處理日期和時間工具類

    • 日期格式化
    • 1、獲取今天的日期
    • 2、在Java 8 中獲取年、月、日信息
    • 3、在Java 8 中處理特定日期
    • 4、在Java 8 中判斷兩個日期是否相等
    • 5、在 Java 8 中檢查像生日這種周期性事件
    • 6、在 Java 8 中獲取當前時間
    • 7、在現有的時間上增加小時
    • 8、計算一周后的日期
    • 9、計算一年前或一年后的日期
    • 10、使用 Java 8 的 Clock 時鐘類
    • 11、如何用 Java 判斷日期是早于還是晚于另一個日期
    • 12、在 Java 8 中處理時區
    • 13、如何表示信用卡到期這類固定日期,答案就在 YearMonth
    • 14、如何在 Java 8 中檢查閏年
    • 15、計算兩個日期之間的天數和月數
    • 16、包含時差信息的日期和時間
    • 17、在 Java 8 中獲取當前的時間戳
    • 18、在 Java 8 中如何使用預定義的格式化工具去解析或格式化日期
    • 19、如何在 Java 中使用自定義格式化工具解析日期
    • 20、在 Java 8 中如何把日期轉換成字符串
    • 21Java 8 日期時間API
    • 22.LocalDateTime與字符串互轉/Date互轉/LocalDate互轉/指定日期/時間比較
      • 與字符串互轉
      • 與Date互轉
      • 與LocalDate互轉
      • 調整時間
      • 時間比較
      • 間隔計算
      • 判斷是否是今天或昨天
    • 23.獲取當天的開始和結束時間
    • 24.本周開始、結束時間
    • 25.本月第一天、最后一天
    • 26.LocalDateTime指定時間,生成指定時間段的隨機時間
  • 日期處理
    • 1.1 用Calendar設置時間的坑
    • 1.2 Java日期格式化YYYY的坑
    • 1.3 Java日期格式化hh的坑。
    • 1.4 Calendar獲取的月份比實際數字少1即(0-11)
    • 1.5 Java日期格式化DD的坑
    • 1.6 SimleDateFormat的format初始化問題
    • 1.7 日期本地化問題
    • 1.8 SimpleDateFormat 解析的時間精度問題
    • 1.9 SimpleDateFormat 的線性安全問題
    • 1.10Java日期的夏令時問題



titile 1 to 21 from:

zhisheng



日期格式化

import java.text.SimpleDateFormat; import java.time.format.DateTimeFormatter;public static final String DATE_TIME_FORMATTER_PATTERN = "yyyy-MM-dd HH:mm:ss"; public static final String DATE_FORMATTER_PATTERN = "yyyy-MM-dd"; public static final String TIME_FORMATTER_PATTERN = "HH:mm:ss"; public static final SimpleDateFormat S_DATE_TIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static final SimpleDateFormat S_DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd"); public static final SimpleDateFormat S_TIME_FORMATTER = new SimpleDateFormat("HH:mm:ss"); public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");

1、獲取今天的日期

Java 8 中的 LocalDate 用于表示當天日期。和 java.util.Date 不同,它只有日期,不包含時間。當你僅需要表示日期時就用這個類。

LocalDate now = LocalDate.now(); System.out.println(now);

結果是:

2018-9-10

上面的代碼創建了當天的日期,不含時間信息。打印出的日期格式非常友好,不像老的 Date 類打印出一堆沒有格式化的信息。

2、在Java 8 中獲取年、月、日信息

LocalDate 類提供了獲取年、月、日的快捷方法,其實例還包含很多其它的日期屬性。通過調用這些方法就可以很方便的得到需要的日期信息,不用像以前一樣需要依賴 java.util.Calendar 類了。

LocalDate now = LocalDate.now(); int year = now.getYear(); int monthValue = now.getMonthValue(); int dayOfMonth = now.getDayOfMonth(); System.out.printf("year = %d, month = %d, day = %d", year, monthValue, dayOfMonth);

結果是:

year = 2018, month = 6, day = 20

3、在Java 8 中處理特定日期

在第一個例子里,我們通過靜態工廠方法 now() 非常容易地創建了當天日期,你還可以調用另一個有用的工廠方法LocalDate.of() 創建任意日期, 該方法需要傳入年、月、日做參數,返回對應的 LocalDate 實例。這個方法的好處是沒再犯老 API 的設計錯誤,比如年度起始于 1900,月份是從 0 開始等等。日期所見即所得,就像下面這個例子表示了 6 月 20 日,沒有任何隱藏機關。

LocalDate date = LocalDate.of(2018, 06, 20); System.out.println(date);

4、在Java 8 中判斷兩個日期是否相等

LocalDate 重載了 equal 方法:

LocalDate now = LocalDate.now(); LocalDate date = LocalDate.of(2018, 06, 20); if (date.equals(now)) {System.out.println("同一天"); }

如果比較的日期是字符型的,需要先解析成日期對象再作判斷。

5、在 Java 8 中檢查像生日這種周期性事件

Java 中另一個日期時間的處理就是檢查類似每月賬單、結婚紀念日、EMI日或保險繳費日這些周期性事件。如果你在電子商務網站工作,那么一定會有一個模塊用來在圣誕節、感恩節這種節日時向客戶發送問候郵件。Java 中如何檢查這些節日或其它周期性事件呢?答案就是 MonthDay 類。這個類組合了月份和日,去掉了年,這意味著你可以用它判斷每年都會發生事件。和這個類相似的還有一個 YearMonth 類。這些類也都是不可變并且線程安全的值類型。下面我們通過 MonthDay 來檢查周期性事件:

LocalDate now = LocalDate.now(); LocalDate dateOfBirth = LocalDate.of(2018, 06, 20); MonthDay birthday = MonthDay.of(dateOfBirth.getMonth(), dateOfBirth.getDayOfMonth()); MonthDay currentMonthDay = MonthDay.from(now); if (currentMonthDay.equals(birthday)) {System.out.println("Happy Birthday"); } else {System.out.println("Sorry, today is not your birthday"); }

結果:(注意:獲取當前時間可能與你看的時候不對,所以這個結果可能和你看的時候運行結果不一樣)

只要當天的日期和生日匹配,無論是哪一年都會打印出祝賀信息。

6、在 Java 8 中獲取當前時間

與 Java 8 獲取日期的例子很像,獲取時間使用的是 LocalTime 類,一個只有時間沒有日期的 LocalDate 近親。可以調用靜態工廠方法 now() 來獲取當前時間。默認的格式是 hh:mm:ss:nnn。

LocalTime localTime = LocalTime.now(); System.out.println(localTime);

結果:

13:35:56.155

7、在現有的時間上增加小時

通過增加小時、分、秒來計算將來的時間很常見。Java 8 除了不變類型和線程安全的好處之外,還提供了更好的plusHours() 方法替換 add(),并且是兼容的。注意,這些方法返回一個全新的 LocalTime 實例,由于其不可變性,返回后一定要用變量賦值。

LocalTime localTime = LocalTime.now(); System.out.println(localTime); LocalTime localTime1 = localTime.plusHours(2);//增加2小時 System.out.println(localTime1);

8、計算一周后的日期

LocalDate 日期不包含時間信息,它的 plus()方法用來增加天、周、月,ChronoUnit 類聲明了這些時間單位。由于 LocalDate 也是不變類型,返回后一定要用變量賦值。

LocalDate now = LocalDate.now(); LocalDate plusDate = now.plus(1, ChronoUnit.WEEKS); System.out.println(now); System.out.println(plusDate);

結果:

2018-06-20 2018-06-27

可以看到新日期離當天日期是 7 天,也就是一周。你可以用同樣的方法增加 1 個月、1 年、1 小時、1 分鐘甚至一個世紀,更多選項可以查看 Java 8 API 中的 ChronoUnit 類

9、計算一年前或一年后的日期

利用 minus() 方法計算一年前的日期。

LocalDate now = LocalDate.now(); LocalDate minusDate = now.minus(1, ChronoUnit.YEARS); LocalDate plusDate1 = now.plus(1, ChronoUnit.YEARS); System.out.println(minusDate); System.out.println(plusDate1);

10、使用 Java 8 的 Clock 時鐘類

Java 8 增加了一個 Clock 時鐘類用于獲取當時的時間戳,或當前時區下的日期時間信息。以前用到System.currentTimeInMillis() 和 TimeZone.getDefault() 的地方都可用 Clock 替換。

Clock clock = Clock.systemUTC(); Clock clock1 = Clock.systemDefaultZone(); System.out.println(clock); System.out.println(clock1);

結果:

SystemClock[Z] SystemClock[Asia/Shanghai]

11、如何用 Java 判斷日期是早于還是晚于另一個日期

LocalDate 類有兩類方法 isBefore() 和 isAfter() 用于比較日期。調用 isBefore() 方法時,如果給定日期小于當前日期則返回 true。

LocalDate tomorrow = LocalDate.of(2018,6,20); if(tomorrow.isAfter(now)){System.out.println("Tomorrow comes after today"); } LocalDate yesterday = now.minus(1, ChronoUnit.DAYS); if(yesterday.isBefore(now)){System.out.println("Yesterday is day before today"); }

12、在 Java 8 中處理時區

Java 8 不僅分離了日期和時間,也把時區分離出來了。現在有一系列單獨的類如 ZoneId 來處理特定時區,ZoneDateTime 類來表示某時區下的時間。這在 Java 8 以前都是 GregorianCalendar 類來做的。

ZoneId america = ZoneId.of("America/New_York"); LocalDateTime localtDateAndTime = LocalDateTime.now(); ZonedDateTime dateAndTimeInNewYork = ZonedDateTime.of(localtDateAndTime, america ); System.out.println(dateAndTimeInNewYork);

13、如何表示信用卡到期這類固定日期,答案就在 YearMonth

YearMonth 是另一個組合類,用于表示信用卡到期日、FD 到期日、期貨期權到期日等。還可以用這個類得到 當月共有多少天,YearMonth 實例的 lengthOfMonth() 方法可以返回當月的天數,在判斷 2 月有 28 天還是 29 天時非常有用。

YearMonth currentYearMonth = YearMonth.now(); System.out.printf("Days in month year %s: %d%n", currentYearMonth, currentYearMonth.lengthOfMonth()); YearMonth creditCardExpiry = YearMonth.of(2018, Month.FEBRUARY); System.out.printf("Your credit card expires on %s %n", creditCardExpiry);

結果:

Days in month year 2018-06: 30 Your credit card expires on 2018-02

14、如何在 Java 8 中檢查閏年

LocalDate 類有一個很實用的方法 isLeapYear() 判斷該實例是否是一個閏年。

15、計算兩個日期之間的天數和月數

有一個常見日期操作是計算兩個日期之間的天數、周數或月數。在 Java 8 中可以用 java.time.Period 類來做計算。下面這個例子中,我們計算了當天和將來某一天之間的月數。

LocalDate date = LocalDate.of(2019, Month.MARCH, 20); Period period = Period.between(now, date); System.out.println("離下個時間還有" + period.getMonths() + " 個月");

16、包含時差信息的日期和時間

在 Java 8 中,ZoneOffset 類用來表示時區,舉例來說印度與 GMT 或 UTC 標準時區相差 +05:30,可以通過ZoneOffset.of() 靜態方法來獲取對應的時區。一旦得到了時差就可以通過傳入 LocalDateTime 和 ZoneOffset 來創建一個 OffSetDateTime 對象。

LocalDateTime datetime = LocalDateTime.of(2014, Month.JANUARY, 14,19,30); ZoneOffset offset = ZoneOffset.of("+05:30"); OffsetDateTime date = OffsetDateTime.of(datetime, offset); System.out.println("Date and Time with timezone offset in Java : " + date);

17、在 Java 8 中獲取當前的時間戳

Instant 類有一個靜態工廠方法 now() 會返回當前的時間戳,如下所示:

Instant timestamp = Instant.now(); System.out.println(timestamp);

結果:

2018-06-20T06:35:24.881Z

時間戳信息里同時包含了日期和時間,這和 java.util.Date 很像。實際上 Instant 類確實等同于 Java 8 之前的 Date類,你可以使用 Date 類和 Instant 類各自的轉換方法互相轉換,例如:Date.from(Instant) 將 Instant 轉換成java.util.Date,Date.toInstant() 則是將 Date 類轉換成 Instant 類。

18、在 Java 8 中如何使用預定義的格式化工具去解析或格式化日期

在 Java 8 以前的世界里,日期和時間的格式化非常詭異,唯一的幫助類 SimpleDateFormat 也是非線程安全的,而且用作局部變量解析和格式化日期時顯得很笨重。幸好線程局部變量能使它在多線程環境中變得可用,不過這都是過去時了。Java 8 引入了全新的日期時間格式工具,線程安全而且使用方便。它自帶了一些常用的內置格式化工具。

19、如何在 Java 中使用自定義格式化工具解析日期

盡管內置格式化工具很好用,有時還是需要定義特定的日期格式。可以調用 DateTimeFormatter 的 ofPattern() 靜態方法并傳入任意格式返回其實例,格式中的字符和以前代表的一樣,M 代表月,m 代表分。如果格式不規范會拋出 DateTimeParseException 異常,不過如果只是把 M 寫成 m 這種邏輯錯誤是不會拋異常的。

20、在 Java 8 中如何把日期轉換成字符串

這是迄今為止 Java 日期轉字符串最為簡單的方式了。下面的例子將返回一個代表日期的格式化字符串。和前面類似,還是需要創建 DateTimeFormatter 實例并傳入格式,但這回調用的是 format() 方法,而非 parse() 方法。這個方法會把傳入的日期轉化成指定格式的字符串。

LocalDateTime arrivalDate = LocalDateTime.now(); try {DateTimeFormatter format = DateTimeFormatter.ofPattern("MMMdd yyyy hh:mm a");String landing = arrivalDate.format(format);System.out.printf("Arriving at : %s %n", landing); }catch (DateTimeException ex) {System.out.printf("%s can't be formatted!%n", arrivalDate);ex.printStackTrace(); }

21Java 8 日期時間API

  • 提供了 javax.time.ZoneId 獲取時區。
  • 提供了 LocalDate 和 LocalTime 類。
  • Java 8 的所有日期和時間 API 都是不可變類并且線程安全,而現有的 Date 和 Calendar API 中的 java.util.Date 和SimpleDateFormat 是非線程安全的。
  • 主包是 java.time, 包含了表示日期、時間、時間間隔的一些類。里面有兩個子包 java.time.format 用于格式化, java.time.temporal 用于更底層的操作。
  • 時區代表了地球上某個區域內普遍使用的標準時間。每個時區都有一個代號,格式通常由區域/城市構成(Asia/Tokyo),在加上與格林威治或 UTC 的時差。例如:東京的時差是 +09:00。
  • OffsetDateTime 類實際上組合了 LocalDateTime 類和 ZoneOffset 類。用來表示包含和格林威治或 UTC 時差的完整日期(年、月、日)和時間(時、分、秒、納秒)信息。
  • DateTimeFormatter 類用來格式化和解析時間。與 SimpleDateFormat 不同,這個類不可變并且線程安全,需要時可以給靜態常量賦值。 DateTimeFormatter 類提供了大量的內置格式化工具,同時也允許你自定義。在轉換方面也提供了 parse() 將字符串解析成日期,如果解析出錯會拋出 DateTimeParseException。DateTimeFormatter 類同時還有format() 用來格式化日期,如果出錯會拋出 DateTimeException異常。
  • 22.LocalDateTime與字符串互轉/Date互轉/LocalDate互轉/指定日期/時間比較

    與字符串互轉

    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");LocalDateTime time = LocalDateTime.now();String localTime = df.format(time);LocalDateTime ldt = LocalDateTime.parse("2018-06-01 10:12:05",df);System.out.println("LocalDateTime轉成String類型的時間:"+localTime);System.out.println("String類型的時間轉成LocalDateTime:"+ldt);

    與Date互轉

    java.util.Date date = new java.util.Date();Instant instant = date.toInstant();ZoneId zone = ZoneId.systemDefault();LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone); LocalDateTime localDateTime = LocalDateTime.now();ZoneId zone = ZoneId.systemDefault();Instant instant = localDateTime.atZone(zone).toInstant();java.util.Date date = Date.from(instant);

    與LocalDate互轉

    LocalDateTime now = LocalDateTime.now();LocalDate localDate = now.toLocalDate(); LocalDate localDate = LocalDate.now();ZoneId zone = ZoneId.systemDefault();Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();java.util.Date date = Date.from(instant);

    調整時間

    LocalDateTime now = LocalDateTime.now();//明天LocalDateTime plusDays = now.plusDays(1);//昨天LocalDateTime plusDays2 = now.plusDays(-1);//還有時分等同理

    時間比較

    LocalDateTime now = LocalDateTime.now();Long epochMilli = now.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();

    間隔計算

    使用Duration進行 day,hour,minute,second等的計算

    使用Period進行Year,Month的計算

    Duration duration = Duration.between(localDateTime,localDateTime4); duration.toDays(); duration.toHours(); duration.toMinutes(); Period period2 = Period.between(localDateTime.toLocalDate(),localDateTime4.toLocalDate()); period2.getYears(); period2.getMonths(); period2.toTotalMonths();

    判斷是否是今天或昨天

    String time = "2018-08-09 11:20:45";DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");LocalDateTime localTime = LocalDateTime.parse(time, dtf);LocalDateTime startTime = LocalDate.now().atTime(0, 0, 0);LocalDateTime endTime = LocalDate.now().atTime(23, 59, 59);LocalDateTime startYesterday = LocalDate.now().plusDays(-1).atTime(0, 0, 0);LocalDateTime endYesterday = LocalDate.now().plusDays(-1).atTime(23, 59, 59);//如果小于昨天的開始日期if (localTime.isBefore(startYesterday)) {System.out.println("時間是過去");}//時間是昨天if (localTime.isAfter(startYesterday) && localTime.isBefore(endYesterday)) {System.out.println("時間是昨天");}//如果大于今天的開始日期,小于今天的結束日期if (localTime.isAfter(startTime) && localTime.isBefore(endTime)) {System.out.println("時間是今天");}//如果大于今天的結束日期if (localTime.isAfter(endTime)) {System.out.println("時間是未來");}}

    23.獲取當天的開始和結束時間

    private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");public static void main(String[] args) {//獲取當前時間LocalDateTime nowTime = LocalDateTime.now();//獲取當前日期LocalDate nowDate = LocalDate.now();//設置零點LocalDateTime beginTime = LocalDateTime.of(nowDate,LocalTime.MIN);//將時間進行格式化String time1= beginTime.format(dtf);//設置當天的結束時間LocalDateTime endTime = LocalDateTime.of(nowDate,LocalTime.MAX);//將時間進行格式化String time2 =dtf.format(endTime);System.out.println("今天開始的時間beginTime:"+time1);System.out.println("今天結束的時間endTime:"+time2); }輸出的結果是:今天開始的時間beginTime:2019-05-26 00:00:00今天結束的時間endTime: 2019-05-26 23:59:59

    24.本周開始、結束時間

    //本周開始時間 TemporalAdjuster FIRST_OF_WEEK =TemporalAdjusters.ofDateAdjuster(localDate -> localDate.minusDays(localDate.getDayOfWeek().getValue()- DayOfWeek.MONDAY.getValue())); String weekStart = df.format(inputDate.with(FIRST_OF_WEEK)); //本周結束時間 TemporalAdjuster LAST_OF_WEEK =TemporalAdjusters.ofDateAdjuster(localDate -> localDate.plusDays(DayOfWeek.SUNDAY.getValue() - localDate.getDayOfWeek().getValue())); String weekEnd = df.format(inputDate.with(LAST_OF_WEEK));

    25.本月第一天、最后一天

    //TODO 本月的第一天 String monthStart = df.format(LocalDate.of(inputDate.getYear(),inputDate.getMonth(),1)); //TODO 本月的最后一天 String monthEnd = df.format(inputDate.with(TemporalAdjusters.lastDayOfMonth()));

    26.LocalDateTime指定時間,生成指定時間段的隨機時間

    /*** 取范圍日期的隨機日期時間,不含邊界* @param startDay* @param endDay* @return*/public static LocalDateTime randomLocalDateTime(int startDay, int endDay) {int plusMinus = 1;if (startDay < 0 && endDay > 0) {plusMinus = Math.random() > 0.5 ? 1 : -1;if (plusMinus > 0) {startDay = 0;} else {endDay = Math.abs(startDay);startDay = 0;}} else if (startDay < 0 && endDay < 0) {plusMinus = -1;//兩個數交換startDay = startDay + endDay;endDay = startDay - endDay;startDay = startDay - endDay;//取絕對值startDay = Math.abs(startDay);endDay = Math.abs(endDay);}//指定時間LocalDate day = LocalDate.now().plusDays(plusMinus * RandomUtils.nextInt(startDay, endDay));int hour = RandomUtils.nextInt(1, 24);int minute = RandomUtils.nextInt(0, 60);int second = RandomUtils.nextInt(0, 60);LocalTime time = LocalTime.of(hour, minute, second);return LocalDateTime.of(day, time);}

    調用方法:

    //生成指定時間段的隨機LocalDateTime時間 randomLocalDateTime(-3, 3).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

    或:

    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");LocalDateTime ldt = randomLocalDateTime(-7, 1); String odMapStartTime = ldt.format(dtf); String odMapEndTime = ldt.plusMinutes(r.nextInt(5)).format(dtf);

    日期處理

    1.1 用Calendar設置時間的坑

    反例

    Calendar c = Calendar.getInstance(); c.set(Calendar.HOUR, 10); System.out.println(c.getTime());

    運行結果

    Thu Mar 26 22:28:05 GMT+08:00 2020

    解析
    我們設置了10小時,但運行結果是22點,而不是10點。因為Calendar.HOUR默認是按12小時制處理的,需要使用Calendar.HOUR_OF_DAY,因為它才是按24小時處理的。
    正例

    Calendar c = Calendar.getInstance(); c.set(Calendar.HOUR_OF_DAY, 10);

    1.2 Java日期格式化YYYY的坑

    反例

    Calendar calendar = Calendar.getInstance(); calendar.set(2019, Calendar.DECEMBER, 31);Date testDate = calendar.getTime();SimpleDateFormat dtf = new SimpleDateFormat("YYYY-MM-dd"); System.out.println("2019-12-31 轉 YYYY-MM-dd 格式后 " + dtf.format(testDate));

    運行結果

    2019-12-31 轉 YYYY-MM-dd 格式后 2020-12-31

    解析
    為什么明明是2019年12月31號,就轉了一下格式,就變成了2020年12月31號了?因為YYYY是基于周來計算年的,它指向當天所在周屬于的年份,一周從周日開始算起,周六結束,只要本周跨年,那么這一周就算下一年的了。正確姿勢是使用yyyy格式。

    正例

    Calendar calendar = Calendar.getInstance(); calendar.set(2019, Calendar.DECEMBER, 31);Date testDate = calendar.getTime();SimpleDateFormat dtf = new SimpleDateFormat("yyyy-MM-dd"); System.out.println("2019-12-31 轉 yyyy-MM-dd 格式后 " + dtf.format(testDate));

    1.3 Java日期格式化hh的坑。

    反例

    String str = "2020-03-18 12:00"; SimpleDateFormat dtf = new SimpleDateFormat("yyyy-MM-dd hh:mm"); Date newDate = dtf.parse(str); System.out.println(newDate);

    運行結果

    Wed Mar 18 00:00:00 GMT+08:00 2020

    解析
    設置的時間是12點,為什么運行結果是0點呢?因為hh是12制的日期格式,當時間為12點,會處理為0點。正確姿勢是使用HH,它才是24小時制。
    正例

    String str = "2020-03-18 12:00"; SimpleDateFormat dtf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); Date newDate = dtf.parse(str); System.out.println(newDate);

    1.4 Calendar獲取的月份比實際數字少1即(0-11)

    反例

    //獲取當前月,當前是3月 Calendar calendar = Calendar.getInstance(); System.out.println("當前"+calendar.get(Calendar.MONTH)+"月份");

    運行結果

    當前2月份

    解析

    The first month of the year in the Gregorian and Julian calendars is <code>JANUARY</code> which is 0;

    也就是1月對應的是下標 0,依次類推。因此獲取正確月份需要加 1.
    復制代碼正例

    //獲取當前月,當前是3月 Calendar calendar = Calendar.getInstance(); System.out.println("當前"+(calendar.get(Calendar.MONTH)+1)+"月份");

    1.5 Java日期格式化DD的坑

    反例

    Calendar calendar = Calendar.getInstance(); calendar.set(2019, Calendar.DECEMBER, 31);Date testDate = calendar.getTime();SimpleDateFormat dtf = new SimpleDateFormat("yyyy-MM-DD"); System.out.println("2019-12-31 轉 yyyy-MM-DD 格式后 " + dtf.format(testDate));

    運行結果

    2019-12-31 轉 yyyy-MM-DD 格式后 2019-12-365

    解析
    DD和dd表示的不一樣,DD表示的是一年中的第幾天,而dd表示的是一月中的第幾天,所以應該用的是dd。
    正例

    Calendar calendar = Calendar.getInstance(); calendar.set(2019, Calendar.DECEMBER, 31);Date testDate = calendar.getTime();SimpleDateFormat dtf = new SimpleDateFormat("yyyy-MM-dd"); System.out.println("2019-12-31 轉 yyyy-MM-dd 格式后 " + dtf.format(testDate));

    1.6 SimleDateFormat的format初始化問題

    反例

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); System.out.println(sdf.format(20200323));

    運行結果

    1970-01-01

    解析
    用format格式化日期是,要輸入的是一個Date類型的日期,而不是一個整型或者字符串。
    正例

    Calendar calendar = Calendar.getInstance(); calendar.set(2020, Calendar.MARCH, 23); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); System.out.println(sdf.format(calendar.getTime()));

    1.7 日期本地化問題

    反例

    String dateStr = "Wed Mar 18 10:00:00 2020"; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy"); LocalDateTime dateTime = LocalDateTime.parse(dateStr, formatter); System.out.println(dateTime);

    運行結果

    Exception in thread "main" java.time.format.DateTimeParseException: Text 'Wed Mar 18 10:00:00 2020' could not be parsed at index 0at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)at java.time.LocalDateTime.parse(LocalDateTime.java:492)at com.example.demo.SynchronizedTest.main(SynchronizedTest.java:19)

    解析
    DateTimeFormatter 這個類默認進行本地化設置,如果默認是中文,解析英文字符串就會報異常。可以傳入一個本地化參數(Locale.US)解決這個問題
    正例

    String dateStr = "Wed Mar 18 10:00:00 2020"; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy",Locale.US); LocalDateTime dateTime = LocalDateTime.parse(dateStr, formatter); System.out.println(dateTime);

    1.8 SimpleDateFormat 解析的時間精度問題

    反例

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String time = "2020-03"; System.out.println(sdf.parse(time));

    運行結果

    Exception in thread "main" java.text.ParseException: Unparseable date: "2020-03"at java.text.DateFormat.parse(DateFormat.java:366)at com.example.demo.SynchronizedTest.main(SynchronizedTest.java:19)

    解析
    SimpleDateFormat 可以解析長于/等于它定義的時間精度,但是不能解析小于它定義的時間精度。
    正例

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM"); String time = "2020-03"; System.out.println(sdf.parse(time));

    1.9 SimpleDateFormat 的線性安全問題

    反例

    public class SimpleDateFormatTest {private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");public static void main(String[] args) {ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 100, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(1000));while (true) {threadPoolExecutor.execute(() -> {String dateString = sdf.format(new Date());try {Date parseDate = sdf.parse(dateString);String dateString2 = sdf.format(parseDate);System.out.println(dateString.equals(dateString2));} catch (ParseException e) {e.printStackTrace();}});}}

    運行結果

    Exception in thread "pool-1-thread-49" java.lang.NumberFormatException: For input string: "5151."at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)at java.lang.Long.parseLong(Long.java:589)at java.lang.Long.parseLong(Long.java:631)at java.text.DigitList.getLong(DigitList.java:195)at java.text.DecimalFormat.parse(DecimalFormat.java:2051)at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162)at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)at java.text.DateFormat.parse(DateFormat.java:364)at com.example.demo.SimpleDateFormatTest.lambda$main$0(SimpleDateFormatTest.java:19)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748) Exception in thread "pool-1-thread-47" java.lang.NumberFormatException: For input string: "5151."at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)at java.lang.Long.parseLong(Long.java:589)at java.lang.Long.parseLong(Long.java:631)at java.text.DigitList.getLong(DigitList.java:195)at java.text.DecimalFormat.parse(DecimalFormat.java:2051)at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162)at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)at java.text.DateFormat.parse(DateFormat.java:364)at com.example.demo.SimpleDateFormatTest.lambda$main$0(SimpleDateFormatTest.java:19)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)

    解析
    全局變量的SimpleDateFormat,在并發情況下,存在安全性問題。

    • SimpleDateFormat繼承了 DateFormat
    • DateFormat類中維護了一個全局的Calendar變量
    • sdf.parse(dateStr)和sdf.format(date),都是由Calendar引用來儲存的。
    • 如果SimpleDateFormat是static全局共享的,Calendar引用也會被共享。
    • 又因為Calendar內部并沒有線程安全機制,所以全局共享的SimpleDateFormat不是線性安全的。

    解決SimpleDateFormat線性不安全問題,有三種方式:

    • 將SimpleDateFormat定義為局部變量
    • 使用ThreadLocal。
    • 方法加同步鎖synchronized。

    正例

    public class SimpleDateFormatTest {private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>();public static DateFormat getDateFormat() {DateFormat df = threadLocal.get();if(df == null){df = new SimpleDateFormat(DATE_FORMAT);threadLocal.set(df);}return df;}public static String formatDate(Date date) throws ParseException {return getDateFormat().format(date);}public static Date parse(String strDate) throws ParseException {return getDateFormat().parse(strDate);}public static void main(String[] args) {ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 100, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(1000));while (true) {threadPoolExecutor.execute(() -> {try {String dateString = formatDate(new Date());Date parseDate = parse(dateString);String dateString2 = formatDate(parseDate);System.out.println(dateString.equals(dateString2));} catch (ParseException e) {e.printStackTrace();}});}} }

    1.10Java日期的夏令時問題

    反例:

    TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println(sdf.parse("1986-05-04 00:30:00"));

    運行結果

    Sun May 04 01:30:00 CDT 1986

    解析
    先了解一下夏令時

    • 夏令時,表示為了節約能源,人為規定時間的意思。
    • 一般在天亮早的夏季人為將時間調快一小時,可以使人早起早睡,減少照明量,以充分利用光照資源,從而節約照明用電。
    • 各個采納夏時制的國家具體規定不同。目前全世界有近110個國家每年要實行夏令時。
    • 1986年4月,中國中央有關部門發出“在全國范圍內實行夏時制的通知”,具體作法是:每年從四月中旬第一個星期日的凌晨2時整(北京時間),將時鐘撥快一小時。(1992年起,夏令時暫停實行。)
    • 夏時令這幾個時間可以注意一下哈,1986-05-04, 1987-04-12, 1988-04-10, 1989-04-16, 1990-04-15, 1991-04-14.

    結合demo代碼,中國在1986-05-04當天還在使用夏令時,時間被撥快了1個小時。所以0點30分打印成了1點30分。如果要打印正確的時間,可以考慮修改時區為東8區。
    正例

    TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println(sdf.parse("1986-05-04 00:30:00"));

    總結

    以上是生活随笔為你收集整理的Java8 ,LocalDate,LocalDateTime处理日期和时间工具类,的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。