公司空降一个 CTO:禁止在项目中利用 Date 类,发现立刻走人!!! [复制链接]
发表于 2024-5-19 16:54:31 | 显示全部楼层 |阅读模式
作者:sum墨
泉源:https://www.cnblogs.com/wlovet/p/18058514
为什么现在连Date类都不建议利用了?
一、有什么问题吗java.util.Date?

java.util.Date(Date从现在开始)是一个糟糕的类型,这解释了为什么它的大部门内容在 Java 1.1 中被弃用(但不幸的是仍在利用)。
设计缺陷包罗:

  • 它的名称具有误导性:它并不代表一个日期,而是代表时间的一个瞬间。所以它应该被称为Instant——正如它的java.time等价物一样。
  • 它是非最终的:这鼓励了对继承的不良利用,例如java.sql.Date(这意味着代表一个日期,并且由于具有雷同的短名称而也令人狐疑)
  • 它是可变的:日期/时间类型是自然值,可以通过不可变类型有效地建模。可变的事实Date(例如通过setTime方法)意味着勤奋的开发人员最终会在各处创建防御性副本。
  • 它在许多地方(包罗)隐式利用体系本地时区,toString()这让许多开发人员感到狐疑。有关此内容的更多信息,请参阅“什么是即时”部门
  • 它的月份编号是从 0 开始的,是从 C 语言复制的。这导致了很多很多相差一的错误。
  • 它的年份编号是基于 1900 年的,也是从 C 语言复制的。当然,当 Java 出现时,我们已经意识到这不利于可读性?
  • 它的方法命名不明确:getDate()返回月份中的某一天,并getDay()返回星期几。给这些更具形貌性的名字有多难?
  • 对于是否支持闰秒含糊其辞:“秒由 0 到 61 之间的整数表示;值 60 和 61 仅在闰秒时出现,纵然如此,也仅在实际正确跟踪闰秒的 Java 实现中出现。” 我强烈怀疑大多数开发人员(包罗我本身)都做了很多假设,认为 for 的范围getSeconds()实际上在 0-59 范围内(含)。
  • 它的宽容没有明显的来由:“在所有情况下,为这些目的而对方法给出的论据不必落在指定的范围内; 例如,日期可以指定为 1 月 32 日,并被解释为 2 月 1 日。” 多久有效一次?
关键缘故原由如下:

原文如下:https://codeblog.jonskeet.uk/2017/04/23/all-about-java-util-date/
二、为啥要改?

我们要改的缘故原由很简朴,我们的代码缺陷扫描规则认为这是一个必须修改的缺陷,否则不给发布,不改不行,服了。

办理思路:避免利用java.util.Date与java.sql.Date类和其提供的API,思量利用java.time.Instant类或java.time.LocalDateTime类及其提供的API替换。
三、怎么改?

只能说这种底子的类改起来牵一发动浑身,必要从DO实体类看起,然后就是各种Converter,末了是DTO。由于我们还是微服务架构,业务服务依赖于底子服务的API,所以必须要一起改否则就会报错。
这里就不细说修改流程了,主要说一下我们在改造的时候遇到的一些问题。
推荐一个开源免费的 Spring Boot 实战项目:
https://github.com/javastacks/spring-boot-best-practice
1. 耐心比对数据库日期字段和DO的映射

(1)确定字段类型

起首你必要确定数据对象中的 Date 字段代表的是日期、时间还是时间戳。

  • 如果字段代表日期和时间,则大概必要利用 LocalDateTime。
  • 如果字段仅代表日期,则大概必要利用 LocalDate。
  • 如果字段仅代表时间,则大概必要利用 LocalTime。
  • 如果字段必要保存时间戳(带时区的),则大概必要利用 Instant 或 ZonedDateTime。
(2)更新数据对象类

更新数据对象类中的字段,把 Date 类型改为适当的 java.time 类型。
2. 将DateUtil中的方法改造

(1)替换原来的new Date()和Calendar.getInstance().getTime()

原来的方式:
  1. Date nowDate = new Date();
  2. Date nowCalendarDate = Calendar.getInstance().getTime();
复制代码
利用 java.time 改造后:
  1. // 使用Instant代表一个时间点,这与Date类似
  2. Instant nowInstant = Instant.now();
  3. // 如果需要用到具体的日期和时间(例如年、月、日、时、分、秒)
  4. LocalDateTime nowLocalDateTime = LocalDateTime.now();
  5. // 如果你需要和特定的时区交互,可以使用ZonedDateTime
  6. ZonedDateTime nowZonedDateTime = ZonedDateTime.now();
  7. // 如果你需要转换回java.util.Date,你可以这样做(假设你的代码其他部分还需要使用Date)
  8. Date nowFromDateInstant = Date.from(nowInstant);
  9. // 如果需要与java.sql.Timestamp交互
  10. java.sql.Timestamp nowFromInstant = java.sql.Timestamp.from(nowInstant);
复制代码
一些留意点:

  • Instant 表示的是一个时间点,它是时区无关的,相当于旧的 Date 类。它通常用于表示时间戳。
  • LocalDateTime 表示没有时区信息的日期和时间,它不能直接转换为时间戳,除非你将其与时区联合利用(例如通过 ZonedDateTime)。
  • ZonedDateTime 包含时区信息的日期和时间,它更类似于 Calendar,因为 Calendar 也包含时区信息。
  • 当你必要将 java.time 对象转换回 java.util.Date 对象时,可以利用 Date.from(Instant) 方法。这在你的代码必要与旧的API或库交互时非常有效。
(2)一些底子的方法改造

a. dateFormat

原来的方式
  1. public static String dateFormat(Date date, String dateFormat) {
  2.     SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
  3.     return formatter.format(date);
  4. }
复制代码
利用java.time改造后
  1. public static String dateFormat(LocalDateTime date, String dateFormat) {
  2.     DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat);
  3.     return date.format(formatter);
  4. }
复制代码
b. addSecond、addMinute、addHour、addDay、addMonth、addYear

原来的方式
  1. public static Date addSecond(Date date, int second) {
  2.     Calendar calendar = Calendar.getInstance();
  3.     calendar.setTime(date);
  4.     calendar.add(13, second);
  5.     return calendar.getTime();
  6. }
  7. public static Date addMinute(Date date, int minute) {
  8.     Calendar calendar = Calendar.getInstance();
  9.     calendar.setTime(date);
  10.     calendar.add(12, minute);
  11.     return calendar.getTime();
  12. }
  13. public static Date addHour(Date date, int hour) {
  14.     Calendar calendar = Calendar.getInstance();
  15.     calendar.setTime(date);
  16.     calendar.add(10, hour);
  17.     return calendar.getTime();
  18. }
  19. public static Date addDay(Date date, int day) {
  20.     Calendar calendar = Calendar.getInstance();
  21.     calendar.setTime(date);
  22.     calendar.add(5, day);
  23.     return calendar.getTime();
  24. }
  25. public static Date addMonth(Date date, int month) {
  26.     Calendar calendar = Calendar.getInstance();
  27.     calendar.setTime(date);
  28.     calendar.add(2, month);
  29.     return calendar.getTime();
  30. }
  31. public static Date addYear(Date date, int year) {
  32.     Calendar calendar = Calendar.getInstance();
  33.     calendar.setTime(date);
  34.     calendar.add(1, year);
  35.     return calendar.getTime();
  36. }
复制代码
利用java.time改造后
  1. public static LocalDateTime addSecond(LocalDateTime date, int second) {
  2.     return date.plusSeconds(second);
  3. }
  4. public static LocalDateTime addMinute(LocalDateTime date, int minute) {
  5.     return date.plusMinutes(minute);
  6. }
  7. public static LocalDateTime addHour(LocalDateTime date, int hour) {
  8.     return date.plusHours(hour);
  9. }
  10. public static LocalDateTime addDay(LocalDateTime date, int day) {
  11.     return date.plusDays(day);
  12. }
  13. public static LocalDateTime addMonth(LocalDateTime date, int month) {
  14.     return date.plusMonths(month);
  15. }
  16. public static LocalDateTime addYear(LocalDateTime date, int year) {
  17.     return date.plusYears(year);
  18. }
复制代码
c. dateToWeek

原来的方式
  1. public static final String[] WEEK_DAY_OF_CHINESE = new String[]{"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
  2. public static String dateToWeek(Date date) {
  3.     Calendar cal = Calendar.getInstance();
  4.     cal.setTime(date);
  5.     return WEEK_DAY_OF_CHINESE[cal.get(7) - 1];
  6. }
复制代码
利用java.time改造后
  1. public static final String[] WEEK_DAY_OF_CHINESE = new String[]{"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
  2. public static String dateToWeek(LocalDate date) {
  3.     DayOfWeek dayOfWeek = date.getDayOfWeek();
  4.     return WEEK_DAY_OF_CHINESE[dayOfWeek.getValue() % 7];
  5. }
复制代码
d. getStartOfDay和getEndOfDay

原来的方式
  1. public static Date getStartTimeOfDay(Date date) {
  2.     if (date == null) {
  3.         return null;
  4.     } else {
  5.         LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
  6.         LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
  7.         return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
  8.     }
  9. }
  10. public static Date getEndTimeOfDay(Date date) {
  11.     if (date == null) {
  12.         return null;
  13.     } else {
  14.         LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
  15.         LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
  16.         return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
  17.     }
  18. }
复制代码
利用java.time改造后
  1. public static LocalDateTime getStartTimeOfDay(LocalDateTime date) {
  2.     if (date == null) {
  3.         return null;
  4.     } else {
  5.         // 获取一天的开始时间,即00:00
  6.         return date.toLocalDate().atStartOfDay();
  7.     }
  8. }
  9. public static LocalDateTime getEndTimeOfDay(LocalDateTime date) {
  10.     if (date == null) {
  11.         return null;
  12.     } else {
  13.         // 获取一天的结束时间,即23:59:59.999999999
  14.         return date.toLocalDate().atTime(LocalTime.MAX);
  15.     }
  16. }
复制代码
e. betweenStartAndEnd

原来的方式
  1. public static Boolean betweenStartAndEnd(Date nowTime, Date beginTime, Date endTime) {
  2.     Calendar date = Calendar.getInstance();
  3.     date.setTime(nowTime);
  4.     Calendar begin = Calendar.getInstance();
  5.     begin.setTime(beginTime);
  6.     Calendar end = Calendar.getInstance();
  7.     end.setTime(endTime);
  8.     return date.after(begin) && date.before(end);
  9. }
复制代码
利用java.time改造后
  1. public static Boolean betweenStartAndEnd(Instant nowTime, Instant beginTime, Instant endTime) {
  2.     return nowTime.isAfter(beginTime) && nowTime.isBefore(endTime);
  3. }
复制代码
我这里就只列了一些,如果有缺失的可以本身增补,不会写的话直接问问ChatGPT,它最会干这事了。末了把这些修改后的方法替换一下就行了。
四、小结一下

这个改造难度不高,但是复杂度非常高,一个地方没改好,轻则接口报错,重则启动失败,非常耗费精神,真不想改。
更多文章推荐:
1.Spring Boot 3.x 教程,太全了!
2.2,000+ 道 Java口试题及答案整理(2024最新版)
3.免费获取 IDEA 激活码的 7 种方式(2024最新版)
觉得不错,别忘了随手点赞+转发哦!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表