建議各位親使用LocalDateTime而不使用Date哦

来源:https://www.cnblogs.com/cxydmx/archive/2019/11/05/11802362.html
-Advertisement-
Play Games

在項目開發過程中經常遇到時間處理,但是你真的用對了嗎,理解阿裡巴巴開發手冊中禁用static修飾SimpleDateFormat嗎 通過閱讀本篇文章你將瞭解到: 為什麼需要LocalDate、LocalTime、LocalDateTime【java8新提供的類】 java8新的時間API的使用方式, ...


在項目開發過程中經常遇到時間處理,但是你真的用對了嗎,理解阿裡巴巴開發手冊中禁用static修飾SimpleDateFormat嗎

通過閱讀本篇文章你將瞭解到:

  • 為什麼需要LocalDateLocalTimeLocalDateTime【java8新提供的類】
  • java8新的時間API的使用方式,包括創建、格式化、解析、計算、修改

為什麼需要LocalDate、LocalTime、LocalDateTime

  • Date如果不格式化,列印出的日期可讀性差

    Tue Sep 10 09:34:04 CST 2019
    
  • 使用SimpleDateFormat對時間進行格式化,但SimpleDateFormat是線程不安全的 SimpleDateFormatformat方法最終調用代碼:

    private StringBuffer format(Date date, StringBuffer toAppendTo,
                                  FieldDelegate delegate) {
            // Convert input date to time field list
            calendar.setTime(date);
            boolean useDateFormatSymbols = useDateFormatSymbols();
            for (int i = 0; i < compiledPattern.length; ) {
                int tag = compiledPattern[i] >>> 8;
                int count = compiledPattern[i++] & 0xff;
                if (count == 255) {
                    count = compiledPattern[i++] << 16;
                    count |= compiledPattern[i++];
                }
                switch (tag) {
                case TAG_QUOTE_ASCII_CHAR:
                    toAppendTo.append((char)count);
                    break;
                case TAG_QUOTE_CHARS:
                    toAppendTo.append(compiledPattern, i, count);
                    i += count;
                    break;
                default:
                    subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
                    break;
                }
            }
            return toAppendTo;
        }
    

    calendar是共用變數,並且這個共用變數沒有做線程安全控制。當多個線程同時使用相同的SimpleDateFormat對象【如用static修飾的SimpleDateFormat】調用format方法時,多個線程會同時調用calendar.setTime方法,可能一個線程剛設置好time值另外的一個線程馬上把設置的time值給修改了導致返回的格式化時間可能是錯誤的。在多併發情況下使用SimpleDateFormat需格外註意 SimpleDateFormat除了format是線程不安全以外,parse方法也是線程不安全的。parse方法實際調用alb.establish(calendar).getTime()方法來解析,alb.establish(calendar)方法里主要完成了

      1. 重置日期對象cal的屬性值
      1. 使用calb中中屬性設置cal
      1. 返回設置好的cal對象

但是這三步不是原子操作

多線程併發如何保證線程安全 - 避免線程之間共用一個SimpleDateFormat對象,每個線程使用時都創建一次SimpleDateFormat對象 => 創建和銷毀對象的開銷大 - 對使用formatparse方法的地方進行加鎖 => 線程阻塞性能差 - 使用ThreadLocal保證每個線程最多只創建一次SimpleDateFormat對象 => 較好的方法

  • Date對時間處理比較麻煩,比如想獲取某年、某月、某星期,以及n天以後的時間,如果用Date來處理的話真是太難了,你可能會說Date類不是有getYeargetMonth這些方法嗎,獲取年月日很Easy,但都被棄用了啊

Come On 一起使用java8全新的日期和時間API

LocalDate

只會獲取年月日

  • 創建LocalDate

    //獲取當前年月日
    LocalDate localDate = LocalDate.now();
    //構造指定的年月日
    LocalDate localDate1 = LocalDate.of(2019, 9, 10);
    
  • 獲取年、月、日、星期幾

    int year = localDate.getYear();
    int year1 = localDate.get(ChronoField.YEAR);
    Month month = localDate.getMonth();
    int month1 = localDate.get(ChronoField.MONTH_OF_YEAR);
    int day = localDate.getDayOfMonth();
    int day1 = localDate.get(ChronoField.DAY_OF_MONTH);
    DayOfWeek dayOfWeek = localDate.getDayOfWeek();
    int dayOfWeek1 = localDate.get(ChronoField.DAY_OF_WEEK);
    
LocalTime

只會獲取幾點幾分幾秒

  • 創建LocalTime

     LocalTime localTime = LocalTime.of(13, 51, 10);
     LocalTime localTime1 = LocalTime.now();
    
  • 獲取時分秒

    //獲取小時
    int hour = localTime.getHour();
    int hour1 = localTime.get(ChronoField.HOUR_OF_DAY);
    //獲取分
    int minute = localTime.getMinute();
    int minute1 = localTime.get(ChronoField.MINUTE_OF_HOUR);
    //獲取秒
    int second = localTime.getSecond();
    int second1 = localTime.get(ChronoField.SECOND_OF_MINUTE);
    
LocalDateTime

獲取年月日時分秒,等於LocalDate+LocalTime

  • 創建LocalDateTime

    LocalDateTime localDateTime = LocalDateTime.now();
    LocalDateTime localDateTime1 = LocalDateTime.of(2019, Month.SEPTEMBER, 10, 14, 46, 56);
    LocalDateTime localDateTime2 = LocalDateTime.of(localDate, localTime);
    LocalDateTime localDateTime3 = localDate.atTime(localTime);
    LocalDateTime localDateTime4 = localTime.atDate(localDate);
    
  • 獲取LocalDate

     LocalDate localDate2 = localDateTime.toLocalDate();
    
  • 獲取LocalTime

    LocalTime localTime2 = localDateTime.toLocalTime();
    
Instant

獲取秒數

  • 創建Instant對象

    Instant instant = Instant.now();
    
  • 獲取秒數

    long currentSecond = instant.getEpochSecond();
    
  • 獲取毫秒數

    long currentMilli = instant.toEpochMilli();
    

個人覺得如果只是為了獲取秒數或者毫秒數,使用System.currentTimeMillis()來得更為方便

修改LocalDate、LocalTime、LocalDateTime、Instant

LocalDateLocalTimeLocalDateTimeInstant不可變對象,修改這些對象對象會返回一個副本

  • 增加、減少年數、月數、天數等 以LocalDateTime為例
    LocalDateTime localDateTime = LocalDateTime.of(2019, Month.SEPTEMBER, 10,
                  14, 46, 56);
    //增加一年
    localDateTime = localDateTime.plusYears(1);
    localDateTime = localDateTime.plus(1, ChronoUnit.YEARS);
    //減少一個月
    localDateTime = localDateTime.minusMonths(1);
    localDateTime = localDateTime.minus(1, ChronoUnit.MONTHS);  
    
  • 通過with修改某些值
    //修改年為2019
    localDateTime = localDateTime.withYear(2020);
    //修改為2022
    localDateTime = localDateTime.with(ChronoField.YEAR, 2022);
    

還可以修改月、日

時間計算

比如有些時候想知道這個月的最後一天是幾號、下個周末是幾號,通過提供的時間和日期API可以很快得到答案

LocalDate localDate = LocalDate.now();
LocalDate localDate1 = localDate.with(firstDayOfYear());

比如通過firstDayOfYear()返回了當前日期的第一天日期,還有很多方法這裡不在舉例說明

格式化時間
LocalDate localDate = LocalDate.of(2019, 9, 10);
String s1 = localDate.format(DateTimeFormatter.BASIC_ISO_DATE);
String s2 = localDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
//自定義格式化
DateTimeFormatter dateTimeFormatter =   DateTimeFormatter.ofPattern("dd/MM/yyyy");
String s3 = localDate.format(dateTimeFormatter);

DateTimeFormatter預設提供了多種格式化方式,如果預設提供的不能滿足要求,可以通過DateTimeFormatterofPattern方法創建自定義格式化方式

解析時間
LocalDate localDate1 = LocalDate.parse("20190910", DateTimeFormatter.BASIC_ISO_DATE);
LocalDate localDate2 = LocalDate.parse("2019-09-10", DateTimeFormatter.ISO_LOCAL_DATE);

SimpleDateFormat相比,DateTimeFormatter是線程安全的

小結

LocalDateTimeDate有的我都有,Date沒有的我也有,日期選擇請Pick Me


SpringBoot中應用LocalDateTime
  • 將LocalDateTime欄位以時間戳的方式返回給前端 添加日期轉化類
    public class LocalDateTimeConverter extends JsonSerializer<LocalDateTime> {
        @Override
        public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeNumber(value.toInstant(ZoneOffset.of("+8")).toEpochMilli());
        }
    }
    
    併在LocalDateTime欄位上添加@JsonSerialize(using = LocalDateTimeConverter.class)註解,如下:
    @JsonSerialize(using = LocalDateTimeConverter.class)
    protected LocalDateTime gmtModified;
    
  • 將LocalDateTime欄位以指定格式化日期的方式返回給前端 在LocalDateTime欄位上添加@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")註解即可,如下:
    @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
    protected LocalDateTime gmtModified;
    
  • 對前端傳入的日期進行格式化 在LocalDateTime欄位上添加@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")註解即可,如下:
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    protected LocalDateTime gmtModified;
    



關註微信公眾號【程式員的夢想】,專註於Java,SpringBoot,SpringCloud,微服務,Docker以及前後端分離等全棧技術。

在這裡插入圖片描述


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ▶ Log4j2 性能 "https://logging.apache.org/log4j/2.x/performance.html" ▶ Spring Boot 依賴與配置 Maven 依賴 XML 配置 resources/log4j2.xml 混合 sync/async 彩色日誌 分類輸出到不 ...
  • 之前同事問了一道需要點腦洞的演算法題,我覺得蠻有意思的,思路可能會給大家帶來一些啟發,特意在此記錄一下 題目 現有一個元素僅為 0,1 的 n 階矩陣,求連續相鄰(水平或垂直,不能有環)元素值為 1 的序列和的最大值 假設有如下矩陣 則此矩陣連續相鄰元素為 1 的序列和分別為 4, 3,(如圖示),可 ...
  • 2019-11-05-23:03:28 List集合: java.util.List 介面繼承自 Collection 介面,是單列集合的一個重要分支,習慣性地會將實現了List 介面的對象稱為List集合 特點: 1. 它是一個元素存取有序的集合。例如,存元素的順序是11、22、33。那麼集合中, ...
  • 1. 列表 1.1 列表的介紹 列表是python的基礎數據類型之⼀,其他編程語⾔也有類似的數據類型。比如JS中的數組, java中的數組等等。它是以[ ]括起來,每個元素⽤','隔開⽽且可以存放各種數據類型: lst = [1, '哈哈', "吼吼", [1,8,0,"百度"], ("我","叫" ...
  • 1. python介紹 1.1 python是什麼樣的語言 編程語⾔主要從以下⼏個⻆度為進⾏分類,編譯型和解釋型、靜態語⾔和動態語⾔、強類型定義語⾔和弱類型定義語⾔,我們先看編譯型語⾔和解釋型語⾔.稍後再說強類型和弱類型 編譯和解釋的區別是什麼? 編譯器是把源程式的每⼀條語句都編譯成機器語⾔,並保存 ...
  • 開發環境: Windows操作系統 開發工具:MyEclipse/Eclipse + JDK+ Tomcat + MySQL 資料庫 項目簡介: 系統前段頁面採用jsp + JavaScript + css的組合技術開發,其中JavaScript使用了jQuery和bootstrap框架,這兩個前段 ...
  • 1.緩存雪崩和緩存穿透問題 1.1緩存雪崩 簡介:緩存同一時間大面積的失效,所以,後面的請求都會落到資料庫上,造成資料庫短時間內承受大量請求而崩掉。 解決辦法:  事前:儘量保證整個 redis 集群的高可用性,發現機器宕機儘快補上。選擇合適的記憶體淘汰策略。  事中:本地 ehcache 緩存 ...
  • 一、基礎類介紹 1、工作簿類Workbook簡介: import xlwt class Workbook(object0): ''' 工作簿類,使用xlwt創建excel文件時,首先要實例化此類的對象 ''' def __init__(self, encoding='ascii', style_co ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...