Java Date & Time API 有什么问题?[已结束]

What's wrong with Java Date & Time API? [closed]

提问人:Anton Gogolev 提问时间:12/28/2009 最后编辑:Piper BarrettAnton Gogolev 更新时间:2/4/2021 访问量:34828

问:


想改进这个问题吗?更新问题,以便可以通过编辑这篇文章来用事实和引文来回答。

5年前关闭。

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

谁能对此有所了解?

Java 日期时间

评论

0赞 Basil Bourque 1/15/2018
Смотритетакже: Java Dates - What is the correct class to use?

答:

15赞 Eran Medan 12/28/2009 #1

我为你感到难过......作为一名前 .NET 程序员,我问了同样的问题,.NET 中的时间 API(时间跨度、运算符重载)非常方便。

首先,若要创建特定日期,请使用已弃用的 API,或者:

Calendar c = Calendar.getInstance();
c.set(2000, 31, 12)

为了减去一天,你做了坏事,比如

Date firstDate = ...
Calendar c = Calendar.getInstance();
c.setTime(fistDate);
c.add(Calendar.DATE,-1);
Date dayAgo = c.getTime();

或更糟

Date d = new Date();
Date d2 = new Date(d.getTime() - 1000*60*60*24);

要了解两个日期之间经过了多少时间(以天/周/月为单位)...情况变得更糟

但是,apache () 的 DateUtils 提供了一些方便的方法,我发现自己最近只使用它们org.apache.commons.lang.time.DateUtils

正如 Brabster 所写,Joda Time 也是一个很好的外部库,但 apache 似乎比其他任何东西都更“常见”......

评论

0赞 Anton Gogolev 12/28/2009
请告诉我们如何做到这一点(“找出两个日期之间经过了多少时间”)!
0赞 Eran Medan 12/28/2009
我希望我知道一个简单的方法......包括闰年、跳跃月和 vlolatile 日......
1赞 trashgod 12/28/2009
参见 org.apache.commons.lang.time: commons.apache.org/lang//api/org/apache/commons/lang/time/...
0赞 Basil Bourque 7/10/2020
@AntonGogolev 在 java.time 中,使用 PeriodDuration 类分别以年-月-日和小时-分钟-秒的等级计算和表示经过的时间。
31赞 waxwing 12/28/2009 #2
  • 日期实例是可变的,这几乎总是不方便的。
  • 他们有双重性质。它们表示时间戳和日历日期。事实证明,在对日期进行计算时,这是有问题的。
  • 在许多情况下,日历数据的数字表示是违反直觉的。例如:从零开始,从 1900 年开始(即 2009 年表示为 109)。getMonth()getYear()
  • 它们缺少您期望从类中获得的许多功能。Date
3赞 brabster 12/28/2009 #3

老实说,我发现 Java 的 Date API 是可用的。我所看到和听到的大多数问题都与冗长、需要涉及多个类来做任何有用的事情 (, , /) 以及缺乏像 .CalendarDateDateFormatSimpleDateFormatgetDayOfWeek()

Joda Time 是 Java 中一个备受推崇的替代 API,在 Why Joda Time 一节中,它给出了更多论据,说明为什么它是一个可能值得关注的可行替代方案。

49赞 meriton 12/28/2009 #4

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

2.5 Java社区的需求将通过提议 规范?

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

一个经典错误(4639407)被阻止 从在 Calendar 对象。代码序列 可以写成可以创建一个 日期在某些年份,但在其他年份没有, 具有预防某些 用户输入正确的 出生日期。这是由 Calendar 类只允许 夏令时增益 1 小时 在夏天,历史上它是 加上 2 小时左右的时间 第二次世界大战。虽然这个错误是 现在已修复,如果在 未来一个国家选择引入一个 夏令时增益 夏天三个小时,然后 日历类将再次被打破。

当前的 Java SE API 也受到了影响 在多线程环境中。 已知不可变类是 本质上是线程安全的状态 无法更改。但是,Date 和 日历是可变的,这需要 程序员要考虑克隆和 显式线程。此外, 缺乏螺纹安全 DateTimeFormat 并不广为人知, 并一直是许多难以 跟踪线程问题。

以及 Java SE 为 datetime 提供的类, 它没有用于建模其他的类 概念。非时区日期或 时间、持续时间、期间和 间隔没有类表示 在 Java SE 中。因此,开发人员 经常使用 int 来表示 持续时间,使用 JavaDoc 指定单位。

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

这个 JSR 将解决 完整的日期和时间模型, 包括日期和时间(带有和 无时区)、持续时间和 时间段、间隔、格式 和解析。

160赞 AlBlue 12/28/2009 #5

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

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

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

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

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

评论

0赞 Enerccio 6/4/2021
可变性并不是一个真正的问题
0赞 PaulaG 2/14/2022
可变性问题可能取决于您的语言和编程风格。对于函数式编程来说,这当然是一个问题