当前位置:首页 > 科技  > 软件

为何应抛弃Date:探索更优的日期处理方案

来源: 责编: 时间:2024-04-08 09:03:08 295观看
导读java.util.Date(Date从现在开始)是一个糟糕的类型,这解释了为什么它的大部分内容在 Java 1.1 中被弃用(但不幸的是仍在使用)。设计缺陷包括:它的名称具有误导性: 它并不代表一个日期,而是代表时间的一个瞬间。所以它应该被称

java.util.Date(Date从现在开始)是一个糟糕的类型,这解释了为什么它的大部分内容在 Java 1.1 中被弃用(但不幸的是仍在使用)。vhT28资讯网——每日最新资讯28at.com

设计缺陷包括:vhT28资讯网——每日最新资讯28at.com

  • 它的名称具有误导性: 它并不代表一个日期,而是代表时间的一个瞬间。所以它应该被称为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 日。” 多久有用一次?

关键原因如下:vhT28资讯网——每日最新资讯28at.com

图片图片vhT28资讯网——每日最新资讯28at.com

解决思路:避免使用java.util.Date与java.sql.Date类和其提供的API,考虑使用java.time.Instant类或java.time.LocalDateTime类及其提供的API替代。vhT28资讯网——每日最新资讯28at.com

怎么改?

只能说这种基础的类改起来牵一发动全身,需要从DO实体类看起,然后就是各种Converter,最后是DTO。vhT28资讯网——每日最新资讯28at.com

由于我们还是微服务架构,业务服务依赖于基础服务的API,所以必须要一起改否则就会报错。这里就不细说修改流程了,主要说一下我们在改造的时候遇到的一些问题。vhT28资讯网——每日最新资讯28at.com

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

1)确定字段类型

首先你需要确定数据对象中的 Date 字段代表的是日期、时间还是时间戳。vhT28资讯网——每日最新资讯28at.com

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

更新数据对象类中的字段,把 Date 类型改为适当的 java.time 类型。vhT28资讯网——每日最新资讯28at.com

2. 将DateUtil中的方法改造

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

原来的方式:vhT28资讯网——每日最新资讯28at.com

Date nowDate = new Date();Date nowCalendarDate = Calendar.getInstance().getTime();

使用 java.time 改造后:vhT28资讯网——每日最新资讯28at.com

// 使用Instant代表一个时间点,这与Date类似Instant nowInstant = Instant.now();// 如果需要用到具体的日期和时间(例如年、月、日、时、分、秒)LocalDateTime nowLocalDateTime = LocalDateTime.now();// 如果你需要和特定的时区交互,可以使用ZonedDateTimeZonedDateTime nowZonedDateTime = ZonedDateTime.now();// 如果你需要转换回java.util.Date,你可以这样做(假设你的代码其他部分还需要使用Date)Date nowFromDateInstant = Date.from(nowInstant);// 如果需要与java.sql.Timestamp交互java.sql.Timestamp nowFromInstant = java.sql.Timestamp.from(nowInstant);

一些注意点:vhT28资讯网——每日最新资讯28at.com

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

a. dateFormatvhT28资讯网——每日最新资讯28at.com

原来的方式vhT28资讯网——每日最新资讯28at.com

public static String dateFormat(Date date, String dateFormat) {    SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);    return formatter.format(date);}

使用java.time改造后vhT28资讯网——每日最新资讯28at.com

public static String dateFormat(LocalDateTime date, String dateFormat) {    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat);    return date.format(formatter);}

b. addSecond、addMinute、addHour、addDay、addMonth、addYearvhT28资讯网——每日最新资讯28at.com

原来的方式vhT28资讯网——每日最新资讯28at.com

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改造后vhT28资讯网——每日最新资讯28at.com

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. dateToWeekvhT28资讯网——每日最新资讯28at.com

原来的方式vhT28资讯网——每日最新资讯28at.com

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改造后vhT28资讯网——每日最新资讯28at.com

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和getEndOfDayvhT28资讯网——每日最新资讯28at.com

原来的方式vhT28资讯网——每日最新资讯28at.com

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改造后vhT28资讯网——每日最新资讯28at.com

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. betweenStartAndEndvhT28资讯网——每日最新资讯28at.com

原来的方式vhT28资讯网——每日最新资讯28at.com

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改造后vhT28资讯网——每日最新资讯28at.com

public static Boolean betweenStartAndEnd(Instant nowTime, Instant beginTime, Instant endTime) {    return nowTime.isAfter(beginTime) && nowTime.isBefore(endTime);}

我这里就只列了一些,如果有缺失的可以自己补充,不会写的话直接问问ChatGPT,它最会干这事了。最后把这些修改后的方法替换一下就行了。vhT28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-81878-0.html为何应抛弃Date:探索更优的日期处理方案

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 从JDK8到JDK14:阿里巴巴面试题探索Java的演进之路!

下一篇: 从MVC到DDD:探寻软件架构的本质变迁

标签:
  • 热门焦点
  • 7月安卓手机性能榜:红魔8S Pro再夺榜首

    7月份的手机市场风平浪静,除了红魔和努比亚带来了两款搭载骁龙8Gen2领先版处理器的新机之外,别的也想不到有什么新品了,这也正常,通常6月7月都是手机厂商修整的时间,进入8月份之
  • 2023年Q2用户偏好榜:12+256G版本成新主流

    3月份的性能榜、性价比榜和好评榜之后,就要轮到2023年的第二季度偏好榜了,上半年的新机潮已经过去,最明显的肯定就是大内存和存储的机型了,另外部分中端机也取消了屏幕塑料支架
  • 三言两语说透设计模式的艺术-简单工厂模式

    一、写在前面工厂模式是最常见的一种创建型设计模式,通常说的工厂模式指的是工厂方法模式,是使用频率最高的工厂模式。简单工厂模式又称为静态工厂方法模式,不属于GoF 23种设计
  • 破圈是B站头上的紧箍咒

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之每年的暑期档都少不了瞄准追剧女孩们的古偶剧集,2021年有优酷的《山河令》,2022年有爱奇艺的《苍兰诀》,今年却轮到小破站抓住了追
  • 苹果、三星、惠普等暂停向印度出口笔记本和平板电脑

    集微网消息,据彭博社报道,在8月3日印度突然禁止在没有许可证的情况下向印度进口电脑/平板及显示器等产品后,苹果、三星电子和惠普等大公司暂停向印度
  • 2299元起!iQOO Pad明晚首销:性能最强天玑平板

    5月23日,iQOO如期举行了新品发布会,除了首发安卓最强旗舰处理器的iQOO Neo8系列新机外,还在发布会上推出了旗下首款平板电脑——iQOO Pad,其最大的卖点
  • 回归OPPO两年,一加赢了销量,输了品牌

    成为OPPO旗下主打性能的先锋品牌后,一加屡创佳绩。今年618期间,一加手机全渠道销量同比增长362%,凭借一加 11、一加 Ace 2、一加 Ace 2V三款爆品,一加
  • SN570 NVMe SSD固态硬盘 价格与性能兼具

    SN570 NVMe SSD固态硬盘是西部数据发布的最新一代WD Blue系列的固态硬盘,不仅闪存技术更为精进,性能也得到了进一步的跃升。WD Blue SN570 NVMe SSD的包装外
  • 上海举办人工智能大会活动,建设人工智能新高地

    人工智能大会在上海浦江两岸隆重拉开帷幕,人工智能新技术、新产品、新应用、新理念集中亮相。8月30日晚,作为大会的特色活动之一的上海人工智能发展盛典人工
Top