<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          為什么現(xiàn)在Java連Date類都不建議使用了?

          共 12097字,需瀏覽 25分鐘

           ·

          2024-04-20 12:20


          來源:juejin.cn/post/7343161506699313162

          有什么問題嗎java.util.Date

          java.util.DateDate從現(xiàn)在開始)是一個糟糕的類型,這解釋了為什么它的大部分內(nèi)容在 Java 1.1 中被棄用(但不幸的是仍在使用)。

          設計缺陷包括:
          • 它的名稱具有誤導性:它并不代表 a Date,而是代表時間的一個瞬間。所以它應該被稱為Instant——正如它的java.time等價物一樣。
          • 它是非最終的:這鼓勵了對繼承的不良使用,例如java.sql.Date(這意味著代表一個日期,并且由于具有相同的短名稱而也令人困惑)
          • 它是可變的:日期/時間類型是自然值,可以通過不可變類型有效地建模。可變的事實Date(例如通過setTime方法)意味著勤奮的開發(fā)人員最終會在各處創(chuàng)建防御性副本。
          • 它在許多地方(包括)隱式使用系統(tǒng)本地時區(qū),toString()這讓許多開發(fā)人員感到困惑。有關(guān)此內(nèi)容的更多信息,請參閱“什么是即時”部分
          • 它的月份編號是從 0 開始的,是從 C 語言復制的。這導致了很多很多相差一的錯誤。
          • 它的年份編號是基于 1900 年的,也是從 C 語言復制的。當然,當 Java 出現(xiàn)時,我們已經(jīng)意識到這不利于可讀性?
          • 它的方法命名不明確:getDate()返回月份中的某一天,并getDay()返回星期幾。給這些更具描述性的名字有多難?
          • 對于是否支持閏秒含糊其辭:“秒由 0 到 61 之間的整數(shù)表示;值 60 和 61 僅在閏秒時出現(xiàn),即使如此,也僅在實際正確跟蹤閏秒的 Java 實現(xiàn)中出現(xiàn)。” 我強烈懷疑大多數(shù)開發(fā)人員(包括我自己)都做了很多假設,認為 for 的范圍getSeconds()實際上在 0-59 范圍內(nèi)(含)。
          • 它的寬容沒有明顯的理由:“在所有情況下,為這些目的而對方法給出的論據(jù)不必落在指定的范圍內(nèi); 例如,日期可以指定為 1 月 32 日,并被解釋為 2 月 1 日。” 多久有用一次?
          更多細節(jié)內(nèi)容參考:https://t.zsxq.com/18HLAb2hI

          為啥要改?

          我們要改的原因很簡單,我們的代碼缺陷掃描規(guī)則認為這是一個必須修改的缺陷,否則不給發(fā)布,不改不行,服了。

          解決思路:避免使用java.util.Datejava.sql.Date類和其提供的API,考慮使用java.time.Instant類或java.time.LocalDateTime類及其提供的API替代。

          怎么改?

          只能說這種基礎(chǔ)的類改起來牽一發(fā)動全身,需要從DO實體類看起,然后就是各種Converter,最后是DTO。由于我們還是微服務架構(gòu),業(yè)務服務依賴于基礎(chǔ)服務的API,所以必須要一起改否則就會報錯。這里就不細說修改流程了,主要說一下我們在改造的時候遇到的一些問題。
          耐心比對數(shù)據(jù)庫日期字段和DO的映射。

          確定字段類型

          首先你需要確定數(shù)據(jù)對象中的 Date 字段代表的是日期、時間還是時間戳。
          • 如果字段代表日期和時間,則可能需要使用 LocalDateTime
          • 如果字段僅代表日期,則可能需要使用 LocalDate
          • 如果字段僅代表時間,則可能需要使用 LocalTime
          • 如果字段需要保存時間戳(帶時區(qū)的),則可能需要使用 Instant 或 ZonedDateTime

          更新數(shù)據(jù)對象類

          更新數(shù)據(jù)對象類中的字段,把 Date 類型改為適當?shù)?java.time 類型。

          將DateUtil中的方法改造

          替換不建議使用的 API

          替換原來的new Date()和Calendar.getInstance().getTime()
          原來的方式:
          
             
          Date nowDate = new Date();
          Date nowCalendarDate = Calendar.getInstance().getTime();
          使用 java.time 改造后:
          
             
          // 使用Instant代表一個時間點,這與Date類似
          Instant nowInstant = Instant.now();

          // 如果需要用到具體的日期和時間(例如年、月、日、時、分、秒)
          LocalDateTime nowLocalDateTime = LocalDateTime.now();

          // 如果你需要和特定的時區(qū)交互,可以使用ZonedDateTime
          ZonedDateTime nowZonedDateTime = ZonedDateTime.now();

          // 如果你需要轉(zhuǎn)換回java.util.Date,你可以這樣做(假設你的代碼其他部分還需要使用Date)
          Date nowFromDateInstant = Date.from(nowInstant);

          // 如果需要與java.sql.Timestamp交互
          java.sql.Timestamp nowFromInstant = java.sql.Timestamp.from(nowInstant);
          一些注意點:
          1. Instant 表示的是一個時間點,它是時區(qū)無關(guān)的,相當于舊的 Date 類。它通常用于表示時間戳。
          2. LocalDateTime 表示沒有時區(qū)信息的日期和時間,它不能直接轉(zhuǎn)換為時間戳,除非你將其與時區(qū)結(jié)合使用(例如通過 ZonedDateTime)。
          3. ZonedDateTime 包含時區(qū)信息的日期和時間,它更類似于 Calendar,因為 Calendar 也包含時區(qū)信息。
          4. 當你需要將 java.time 對象轉(zhuǎn)換回 java.util.Date 對象時,可以使用 Date.from(Instant) 方法。這在你的代碼需要與舊的API或庫交互時非常有用。

          dateFormat

          原來的方式
          
             
          public static String dateFormat(Date date, String dateFormat) {
              SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
              return formatter.format(date);
          }
          使用java.time改造后
          
             
          public static String dateFormat(LocalDateTime date, String dateFormat) {
              DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat);
              return date.format(formatter);
          }

          add相關(guān)方法

          b. addSecond、addMinute、addHour、addDay、addMonth、addYear
          原來的方式
          
             
          public static Date addSecond(Date date, int second) {
              Calendar calendar = Calendar.getInstance();
              calendar.setTime(date);
              calendar.add(13, second);
              return calendar.getTime();
          }

          public static Date addMinute(Date date, int minute) {
              Calendar calendar = Calendar.getInstance();
              calendar.setTime(date);
              calendar.add(12, minute);
              return calendar.getTime();
          }

          public static Date addHour(Date date, int hour) {
              Calendar calendar = Calendar.getInstance();
              calendar.setTime(date);
              calendar.add(10, hour);
              return calendar.getTime();
          }

          public static Date addDay(Date date, int day) {
              Calendar calendar = Calendar.getInstance();
              calendar.setTime(date);
              calendar.add(5, day);
              return calendar.getTime();
          }

          public static Date addMonth(Date date, int month) {
              Calendar calendar = Calendar.getInstance();
              calendar.setTime(date);
              calendar.add(2, month);
              return calendar.getTime();
          }

          public static Date addYear(Date date, int year) {
              Calendar calendar = Calendar.getInstance();
              calendar.setTime(date);
              calendar.add(1, year);
              return calendar.getTime();
          }
          使用java.time改造后
          
             
          public static LocalDateTime addSecond(LocalDateTime date, int second) {
              return date.plusSeconds(second);
          }

          public static LocalDateTime addMinute(LocalDateTime date, int minute) {
              return date.plusMinutes(minute);
          }

          public static LocalDateTime addHour(LocalDateTime date, int hour) {
              return date.plusHours(hour);
          }

          public static LocalDateTime addDay(LocalDateTime date, int day) {
              return date.plusDays(day);
          }

          public static LocalDateTime addMonth(LocalDateTime date, int month) {
              return date.plusMonths(month);
          }

          public static LocalDateTime addYear(LocalDateTime date, int year) {
              return date.plusYears(year);
          }

          dateToWeek

          原來的方式
          
             
          public static final String[] WEEK_DAY_OF_CHINESE = new String[]{"周日""周一""周二""周三""周四""周五""周六"};
          public static String dateToWeek(Date date) {
              Calendar cal = Calendar.getInstance();
              cal.setTime(date);
              return WEEK_DAY_OF_CHINESE[cal.get(7) - 1];
          }
          使用java.time改造后
          
             
          public static final String[] WEEK_DAY_OF_CHINESE = new String[]{"周日""周一""周二""周三""周四""周五""周六"};

          public static String dateToWeek(LocalDate date) {
              DayOfWeek dayOfWeek = date.getDayOfWeek();
              return WEEK_DAY_OF_CHINESE[dayOfWeek.getValue() % 7];
          }

          getStartOfDay和getEndOfDay

          原來的方式
          
             
          public static Date getStartTimeOfDay(Date date) {
              if (date == null) {
                  return null;
              } else {
                  LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
                  LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
                  return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
              }
          }

          public static Date getEndTimeOfDay(Date date) {
              if (date == null) {
                  return null;
              } else {
                  LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
                  LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
                  return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
              }
          }
          使用java.time改造后
          
             
          public static LocalDateTime getStartTimeOfDay(LocalDateTime date) {
              if (date == null) {
                  return null;
              } else {
                  // 獲取一天的開始時間,即00:00
                  return date.toLocalDate().atStartOfDay();
              }
          }

          public static LocalDateTime getEndTimeOfDay(LocalDateTime date) {
              if (date == null) {
                  return null;
              } else {
                  // 獲取一天的結(jié)束時間,即23:59:59.999999999
                  return date.toLocalDate().atTime(LocalTime.MAX);
              }
          }

          betweenStartAndEnd

          原來的方式
          
             
          public static Boolean betweenStartAndEnd(Date nowTime, Date beginTime, Date endTime) {
              Calendar date = Calendar.getInstance();
              date.setTime(nowTime);
              Calendar begin = Calendar.getInstance();
              begin.setTime(beginTime);
              Calendar end = Calendar.getInstance();
              end.setTime(endTime);
              return date.after(begin) && date.before(end);
          }
          使用java.time改造后
          
             
          public static Boolean betweenStartAndEnd(Instant nowTime, Instant beginTime, Instant endTime) {
              return nowTime.isAfter(beginTime) && nowTime.isBefore(endTime);
          }
          我這里就只列了一些,如果有缺失的可以自己補充,不會寫的話直接問問 ChatGPT,它最會干這事了。最后把這些修改后的方法替換一下就行了。

          總結(jié)

          這個改造難度不高,但是復雜度非常高,一個地方?jīng)]改好,輕則接口報錯,重則啟動失敗,非常耗費精力,真不想改。
             


          瀏覽 154
          10點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          10點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  韩国成人免费无码免费视频 | 伊人婷婷成人网 | 日逼一级片 | 欧美日韩国产性爱 | 九一香蕉视频在线观看 |