Java Date & Time API 有什么问题?[已关闭]

2022-08-31 09:09:23

我经常遇到关于Java和其他日期时间相关类的负面反馈。作为一名.NET开发人员,我无法完全(没有使用它们)理解它们到底出了什么问题。Date

任何人都可以对此有所了解吗?


答案 1

啊,Java类。也许是最好的例子之一,说明如何在任何地方不用任何语言做某事。我从哪里开始?Date

阅读JavaDoc可能会导致人们认为开发人员实际上已经得到了一些好主意。它继续详细讨论UTCGMT之间的差异,尽管两者之间的差异基本上是闰秒(这种情况很少发生)。

但是,设计决策确实浪费了任何关于设计良好的API的想法。以下是一些最喜欢的错误:

  • 尽管它是在千年的最后十年设计的,但自1900年以来,它将年份评为两位数。由于这个平庸的决定,在Java世界中有数百万种解决方法可以完成1900+(或1900-)。
  • 月份的索引为零,以满足具有月份数组并且不与十三元素数组一起生活的惊人不寻常的情况,其中第一个包含.因此,我们有0..11(今天是109年的第11个月)。月份上有类似数量的 ++ 和 -- 以转换为字符串。null
  • 它们是可变的。因此,每当您想要返回日期(例如,作为实例结构)时,您都需要返回该日期的克隆,而不是日期对象本身(否则,人们可能会改变您的结构)。
  • 旨在“修复”此问题的 ,实际上犯了同样的错误。它们仍然是可变的。Calendar
  • Date表示 一个 ,但为了尊重 SQL land 中的那些,还有另一个子类 ,它表示一天(尽管没有与之关联的时区)。DateTimejava.sql.Date
  • 没有与 文件关联的 s,因此范围(例如“一整天”)通常表示为午夜到午夜(通常在某个任意时区中)TimeZoneDate

最后,值得注意的是,闰秒通常会根据一个好的系统时钟进行自我纠正,该系统时钟会在一小时内用ntp更新(参见上面的链接)。在引入两个闰秒(至少每六个月,实际上每隔几年)的情况下,系统仍然启动并运行的可能性很小,特别是考虑到您必须不时重新部署新版本代码的事实。即使使用再生类的动态语言或类似WAR引擎之类的东西也会污染类空间并最终耗尽permgen。


答案 2

JSR 310 在 Java 8 中用 java.time 取代了旧的日期时间类,在原始 JSR 中证明了自己的合理性,如下所示:

2.5 所提出的规范将满足 Java 社区的哪些需求?

目前,Java SE有两个单独的日期和时间API - java.util.Date和java.util.Calendar。这两个API一直被描述为Java开发人员在博客和论坛上难以使用。值得注意的是,两者都使用零索引数月,这是许多错误的原因。多年来,Calendar也遭受了许多错误和性能问题的困扰,这主要是由于在内部以两种不同的方式存储其状态。

一个经典的 bug(4639407)阻止在 Calendar 对象中创建某些日期。可以编写一系列代码,这些代码可以在某些年份创建日期,但在其他年份中则不能创建日期,从而阻止某些用户输入正确的出生日期。这是由于日历类只允许夏令时增加一个小时,而从历史上看,它是在第二次世界大战前后加上2个小时。虽然这个错误现在已经修复,但如果在未来的某个时候,一个国家选择在夏季引入夏令时加三个小时的加三个小时,那么日历类将再次被打破。

当前的Java SE API在多线程环境中也受到影响。已知不可变类本质上是线程安全的,因为它们的状态不能更改。但是,“日期”和“日历”都是可变的,这要求程序员明确考虑克隆和线程。此外,DateTimeFormat中缺乏线程安全性并不广为人知,并且是许多难以跟踪的线程问题的原因。

除了 Java SE 在日期时间方面的类存在问题之外,它也没有用于对其他概念进行建模的类。非时区日期或时间、持续时间、期间和间隔在 Java SE 中没有类表示形式。因此,开发人员经常使用int来表示持续时间,javadoc指定单位。

缺乏全面的日期和时间模型也导致许多常见操作比它们应该的更棘手。例如,计算两个日期之间的天数是目前一个特别困难的问题。

此 JSR 将解决完整的日期和时间模型的问题,包括日期和时间(有和没有时区)、持续时间和时间段、间隔、格式和解析。