Java 日期和时间 API 有啥问题? [关闭]

Posted

技术标签:

【中文标题】Java 日期和时间 API 有啥问题? [关闭]【英文标题】:What's wrong with Java Date & Time API? [closed]Java 日期和时间 API 有什么问题? [关闭] 【发布时间】:2010-12-30 11:29:22 【问题描述】:

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

有人能解释一下吗?

【问题讨论】:

另见:Java Dates - What's the correct class to use? 【参考方案1】:

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

阅读 JavaDoc 可能会让人认为开发人员确实有一些好主意。它继续讨论UTC和GMT之间的区别,尽管两者之间的区别基本上是闰秒(发生在prettyrarely)。

但是,设计决策确实浪费了任何作为设计良好的 API 的想法。以下是一些最常见的错误:

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

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

【讨论】:

可变性并不是一个真正的问题【参考方案2】:

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

2.5 Java 社区的哪些需求将通过提案解决 规范?

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

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

当前的 Java SE API 也受到影响 在多线程环境中。 众所周知,不可变的类是 本质上是线程安全的作为它们的状态 不能变。但是,日期和 日历是可变的,这需要 程序员考虑克隆和 显式线程化。除此之外 缺乏线程安全 DateTimeFormat 并不广为人知, 并已成为许多难以 追踪线程问题。

还有问题 Java SE 的日期时间类, 它没有用于建模其他的类 概念。非时区日期或 时间、持续时间、期间和 区间没有类表示 在 Java SE 中。结果,开发商 经常使用 int 来表示 持续时间,使用 javadoc 指定单位。

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

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

【讨论】:

【参考方案3】: 日期实例是mutable,这几乎总是不方便。 它们具有双重性质。它们代表时间戳和日历日期。事实证明,在对日期进行计算时,这是有问题的。 在许多情况下,日历数据的数字表示是违反直觉的。例如:getMonth() 从零开始,getYear() 从 1900 开始(即 2009 年表示为 109)。 它们缺少许多您期望 Date 类提供的功能。

【讨论】:

【参考方案4】:

我对你有感觉...作为一名前 .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 (org.apache.commons.lang.time.DateUtils) 的 DateUtils 提供了一些方便的方法,我发现自己最近只使用它们

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

【讨论】:

拜托,请告诉我们怎么做(“找出两个日期之间经过了多少时间”)! 我希望我知道一个简单的方法......包括闰年、跳跃的月份和动荡的日子...... 另见,org.apache.commons.lang.time:commons.apache.org/lang//api/org/apache/commons/lang/time/… @AntonGogolev 在 java.time 中,使用 PeriodDuration 类以年-月-日和小时-分钟的比例计算和表示经过的时间- 秒。【参考方案5】:

说实话,我发现 Java 的 Date API 是有用的。我看到和听到的大多数问题都与冗长有关,需要涉及多个类来做任何有用的事情(CalendarDateDateFormat/SimpleDateFormat)以及缺乏简单的访问器,如getDayOfWeek().

Joda Time 是 Java 中备受推崇的替代 API,在Why Joda Time 部分中,它提供了一些关于为什么它是可能感兴趣的可行替代方案的更多论据。

【讨论】:

以上是关于Java 日期和时间 API 有啥问题? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

iPhone和/或Android手机有啥好的OCR API吗? [关闭]

Java的智能日期/时间解析器[关闭]

像 Twilio 那样按日期对 REST api 进行版本控制有啥好处?

REST API 身份验证有啥不同? [关闭]

带有日期参数的天气 API [关闭]

有啥方法可以将推送式网络通知发送到移动设备? [关闭]