网易首页 > 网易号 > 正文 申请入驻

Date 类已被废弃了,强烈建议不要再使用 java.util.Date 了!

0
分享至

钓友宝 (微信小程序):一款专门为 钓友 开发的 免费的 分享钓点地图与实时天气的软件,地图中标记了所有野钓、钓场、公共水域等的精确位置,支持导航、 预测钓鱼位置的鱼情 等功能。

一、有什么问题吗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 日。” 多久有用一次?

关键原因如下:

原文如下:为什么要避免使用Date类?

“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,所以必须要一起改否则就会报错。这里就不细说修改流程了,主要说一下我们在改造的时候遇到的一些问题。

1. 耐心比对数据库日期字段和DO的映射

1)确定字段类型

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

如果字段代表日期和时间,则可能需要使用 LocalDateTime。

如果字段仅代表日期,则可能需要使用 LocalDate。

如果字段仅代表时间,则可能需要使用 LocalTime。

如果字段需要保存时间戳(带时区的),则可能需要使用 Instant 或 ZonedDateTime。

2)更新数据对象类

更新数据对象类中的字段,把 Date 类型改为适当的 java.time 类型。

2. 将DateUtil中的方法改造

1)替换原来的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(); // 如果你需要和特定的时区交互,可以使用ZonedDateTime ZonedDateTime nowZonedDateTime = ZonedDateTime.now(); // 如果你需要转换回java.util.Date,你可以这样做(假设你的代码其他部分还需要使用Date) Date nowFromDateInstant = Date.from(nowInstant); // 如果需要与java.sql.Timestamp交互 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

原来的方式

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); }

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); }

c. 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]; }

原来的方式

public static Date getStartTimeOfDay(Date date) {     if (date == null) {         returnnull;     } 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) {         returnnull;     } 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) {         returnnull;     } else {         // 获取一天的开始时间,即00:00         return date.toLocalDate().atStartOfDay();     } } public static LocalDateTime getEndTimeOfDay(LocalDateTime date) {     if (date == null) {         returnnull;     } else {         // 获取一天的结束时间,即23:59:59.999999999         return date.toLocalDate().atTime(LocalTime.MAX);     } }

e. 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,它最会干这事了。最后把这些修改后的方法替换一下就行了。

四、小结一下

这个改造难度不高,但是复杂度非常高,一个地方没改好,轻则接口报错,重则启动失败,非常耗费精力,真不想改。

JDK8以上版本建议直接使用LocalDate和LocalDateTime。


Java精选面试题 (微信小程序):5000+道面试题和选择题,包含Java基础、MQ、Redis、SpringBoot、Elasticsearch、Docker、K8s、Flink、Spark、架构设计、大厂真题等,在线随时刷题!
来源:https://www.cnblogs.com/wlovet/p/18058514

公众号“Java精选”所发表内容注明来源的,版权归原出处所有(无法查证版权的或者未注明出处的均来自网络,系转载,转载的目的在于传递更多信息,版权属于原作者。如有侵权,请联系,笔者会第一时间删除处理!

最近有很多人问,有没有读者或者摸鱼交流群!加入方式很简单,公众号Java精选,回复“加群”,即可入群!

文章有帮助的话,点在看,转发吧!

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
12秒98夺第1!吴艳妮预赛闪耀比心庆祝,跨栏女神对决,林雨薇第2

12秒98夺第1!吴艳妮预赛闪耀比心庆祝,跨栏女神对决,林雨薇第2

李喜林篮球绝杀
2025-11-19 10:28:03
弟弟结婚不让去,我关机旅行,开机后看到我妈打来300个未接来电

弟弟结婚不让去,我关机旅行,开机后看到我妈打来300个未接来电

木槿纪实
2025-11-19 09:29:29
阿里开始严查午休

阿里开始严查午休

蚂蚁大喇叭
2025-11-17 09:56:58
解决Siri这座“屎山”,是苹果新掌门的头号任务

解决Siri这座“屎山”,是苹果新掌门的头号任务

字母榜
2025-11-17 16:09:01
震惊!新型穷人症状曝光,网友称已“病入膏肓”!

震惊!新型穷人症状曝光,网友称已“病入膏肓”!

特约前排观众
2025-11-19 00:15:03
71岁成龙去世?最新消息!

71岁成龙去世?最新消息!

乡野小珥
2025-11-18 13:40:40
侯耀华北京别墅亲自做饭,灶台杂乱满墙油污,78岁穿范哲思很时尚

侯耀华北京别墅亲自做饭,灶台杂乱满墙油污,78岁穿范哲思很时尚

趣味八卦
2025-11-19 07:29:01
高市万万没想到,派“弃子”来华后,中国立场变了,又叫停2件事

高市万万没想到,派“弃子”来华后,中国立场变了,又叫停2件事

潮鹿逐梦
2025-11-17 21:59:35
薄一波晚年反省,当年不该支持此人上台,他给国家带来大麻烦

薄一波晚年反省,当年不该支持此人上台,他给国家带来大麻烦

扬平说史
2025-11-06 20:22:42
一百年里只见过4次!2025年男子在上海发现1只,一天约200人围观

一百年里只见过4次!2025年男子在上海发现1只,一天约200人围观

万象硬核本尊
2025-11-17 19:37:13
妻子逼我拿30万给小舅子买车,我62岁妈妈冷静开口:过不下去就离

妻子逼我拿30万给小舅子买车,我62岁妈妈冷静开口:过不下去就离

李子木说
2025-10-29 17:39:15
0-0险平!中国队无缘冠军,最大水货揪出,熊猫杯最终排名如下

0-0险平!中国队无缘冠军,最大水货揪出,熊猫杯最终排名如下

大秦壁虎白话体育
2025-11-18 21:53:48
勇士113-121魔术遭4坏消息!替补无稳定得分,内外线防守都被爆!

勇士113-121魔术遭4坏消息!替补无稳定得分,内外线防守都被爆!

细话篮球
2025-11-19 11:28:16
喻恩泰好友反击了!爆料史林子多次偷情出轨,并曝出露骨聊天截图

喻恩泰好友反击了!爆料史林子多次偷情出轨,并曝出露骨聊天截图

萌神木木
2025-11-18 19:36:17
不断挑拨离间!孙颖莎忍无可忍,终于道出与王曼昱“真实关系”

不断挑拨离间!孙颖莎忍无可忍,终于道出与王曼昱“真实关系”

东方不败然多多
2025-11-18 13:43:01
取消赴日旅游的中国游客:机酒已全额退款,未来出行仍在观望

取消赴日旅游的中国游客:机酒已全额退款,未来出行仍在观望

南方都市报
2025-11-18 23:22:18
中国拒绝捐款,特朗普缺席COP30,我们没有义务当冤大头

中国拒绝捐款,特朗普缺席COP30,我们没有义务当冤大头

历史求知所
2025-11-18 10:15:03
中国003型航母都要量产了,为啥东海舰队还是没分到航母?

中国003型航母都要量产了,为啥东海舰队还是没分到航母?

军武次位面
2025-11-18 17:03:53
联合国回应高市早苗言论

联合国回应高市早苗言论

每日经济新闻
2025-11-18 14:17:06
关于供应链转移这事,有业内网友说出了这些细节

关于供应链转移这事,有业内网友说出了这些细节

清晖有墨
2025-11-18 13:29:54
2025-11-19 11:40:49
Java精选
Java精选
一场永远也演不完的戏
1758文章数 3859关注度
往期回顾 全部

科技要闻

一夜封神,Gemini 3让谷歌找回“碾压感”

头条要闻

女子参加模特大赛夺"广东冠军" 因突破大众审美引争议

头条要闻

女子参加模特大赛夺"广东冠军" 因突破大众审美引争议

体育要闻

结束最后一次对决,陈梦和朱雨玲笑着相拥

娱乐要闻

又反转!曝喻恩泰出轨美女律师

财经要闻

黄金税改两周,水贝低价神话终结?

汽车要闻

脱胎换骨的优秀底盘Get 新款享界S9动态驾驶体验

态度原创

手机
房产
艺术
时尚
公开课

手机要闻

富士康已搭建苹果折叠屏专属生产线:屏幕无折痕

房产要闻

29.4亿!海南“地王”片区,要卖超级宅地!

艺术要闻

启功:我是画家,但书名超过了画名

拍照不用露脸也很美!4个心机pose学起来,朋友圈狂收赞

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版