首页 > 其他分享 >强烈建议你不要再使用Date类了!!!

强烈建议你不要再使用Date类了!!!

时间:2024-04-05 21:31:00浏览次数:9  
标签:不要 date 强烈建议 static LocalDateTime Date return Calendar

文章目录

一、有什么问题吗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.Datejava.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];
}

d. 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 {
        // 获取一天的结束时间,即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,它最会干这事了。最后把这些修改后的方法替换一下就行了。

四、小结一下

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

标签:不要,date,强烈建议,static,LocalDateTime,Date,return,Calendar
From: https://blog.csdn.net/qq_43842093/article/details/137386163

相关文章

  • Java代码实现带时区时间字符串转为LocalDateTime对象
    不带时区时间字符串可以使用Java8中的DateTimeFormatter类来将字符串转换为LocalDateTime对象。下面是一个示例代码:importjava.time.LocalDateTime;importjava.time.format.DateTimeFormatter;publicclassDateTimeConversionExample{publicstaticvoidmain(Stri......
  • linux 中 yum makecache 、yum update、yum upgrade的作用
     001、yummakecache的作用是将服务器上的软件包信息缓存到本地,以提高搜索和安装软件的速度。 002、yumupdate:该命令用于更新系统中已安装的软件包到最新版本,但不会安装新的软件包或删除已安装的软件包。 003、yumupgrade:该命令也用于更新系统中已安装的软件包到最新......
  • playwright for net 对日期选择控件(My97DatePicker)的设置
     playwrightf对日期选择控件的设置,直接使用js脚本publicpartialclassMainForm:Form{IPlaywrightplaywright;IPagepage;publicMainForm(){InitializeComponent();}privateasyncvoidMainForm_Loa......
  • MySQL UPDATE JOIN 根据一张表或多表来更新另一张表的数据
    当使用MySQL时,经常需要根据一张表或多张表的数据来更新另一张表的数据。这种情况下,我们可以使用UPDATE语句结合JOIN操作来实现这一需求。本文将介绍MySQL中使用UPDATEJOIN的技术。什么是UPDATEJOINUPDATEJOIN是MySQL中一种结合UPDATE语句和JOIN操作的技术,用于根据一张表或多......
  • Java代码实现带时区时间字符串转为LocalDateTime对象
    不带时区时间字符串可以使用Java8中的DateTimeFormatter类来将字符串转换为LocalDateTime对象。下面是一个示例代码:importjava.time.LocalDateTime;importjava.time.format.DateTimeFormatter;publicclassDateTimeConversionExample{publicstaticvoidmain(Stri......
  • 06 MySQL数据操作DML---插入insert、删除delete、更新update、查询select
    DML是指数据操作语言,用来对数据库中表的数据记录进行更新插入insert向表中指定字段插入数据insertinto表名(字段名1,字段名2,字段名3,...)values(字段名1值,字段名2值,字段名3值,...)INSERTintomy_student(id,`name`,age)values(2,'Jack',12);字段列表不一定非要......
  • Vue日期选择器里面进行disabledDate(time)进行调用
    题主首先参照别人的写法,写在里面,但是发现disabledDate一直是灰色调用不成功,后来进行别的参考pickerOptions:{disabledDate(time){returntime.getTime()<Date.now()-8.64e7;//如果没有后面的-8.64e7就是不可以选择今天的},}, ......
  • 不要混淆了贴图与纹理
    在3D建模中,贴图(TextureMapping)和纹理(Texture)虽然经常被混为一谈,但它们其实是两个截然不同的概念。以下是贴图和纹理的主要区别:贴图(TextureMapping)贴图是一个过程,即将2D图像(纹理)映射到3D模型的表面。这个过程需要UV映射(UVMapping),也就是将3D模型的表面坐标转换为2D......
  • Item21:当你返回一个对象时,不要试图返回一个引用
    芝士wa2024.4.2Item21链接“无论何时只要你看到一个引用声明,你应该立刻问自己它是什么东西的另一个名字,因为它必定是某物的另一个名字”如果函数返回一个引用,它必须返回某个已存在的对象的引用。一个函数创建一个新对象只有两种方法:在栈上或者在堆上。栈上的生成物是局部......
  • 分享几个非常不错嵌入式开源项目,一定不要错过
    大家好,我是知微!经常有小伙伴后台私信我:有没有好的开源项目推荐怎么样才能提升自己的编程能力那么这篇文章就推荐几个还不错的开源项目,感兴趣的小伙伴可以学习一下!日志库EasyLoggerhttps://github.com/armink/EasyLogger开发一个项目,如果没有日志的记录,当遇到问题需要分......