Java Date& amp;有什么问题?时间API?

时间:2009-12-28 13:23:13

标签: java datetime

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

有人可以对此有所了解吗?

5 个答案:

答案 0 :(得分:132)

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

阅读JavaDoc可能会让人觉得开发人员实际上有一些好主意。它继续讨论UTCGMT之间的差异,尽管两者之间的差异基本上是闰秒(发生pretty rarely)。< / p>

但是,设计决策实际上浪费了任何想法都是精心设计的API。以下是一些最喜欢的错误:

  • 尽管是在千禧年的最后十年设计的,但自1900年以来,它的年数已经达到两位数。由于这一平庸的决定,在Java世界中有数百万个变通方法正在做1900+(或1900)。< / LI>
  • 月份是零索引,以迎合一个非常不寻常的情况,即拥有一个数月的数组,而不是与13个元素阵列一起生活,其中第一个包含null。结果,我们有0..11(今天是109年的第11个月)。为了转换为字符串,在几个月内有相似数量的++和。
  • 他们是mutable。因此,只要您想要提供日期(例如,作为实例结构),您需要返回该日期的克隆而不是日期对象本身(否则,人们可能会改变您的结构)。
  • 旨在“修复”此问题的Calendar实际上会犯同样的错误。他们仍然是可变的。
  • Date代表一个DateTime,但是为了顺从那些SQL土地,还有另一个子类java.sql.Date,代表一天(虽然没有与之关联的时区)
  • 没有与TimeZone关联的Date,因此范围(例如“整天”)通常表示为午夜 - 午夜(通常在某个任意时区)

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

答案 1 :(得分:40)

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

  

2.5提议将解决Java社区的需求   说明书

     

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

     

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

     

当前的Java SE API也受到影响   在多线程环境中。   众所周知,不可变的类是   本质上是线程安全的   不能变。但是,日期和   日历是可变的,这需要   程序员考虑克隆和   明确地线程化。除此之外   缺乏线程安全性   DateTimeFormat并不广为人知,   并且一直是许多人努力的原因   追踪线程问题。

     

以及与之相关的问题   Java SE具有的日期时间,   它没有用于建模其他类的类   概念。非时区日期或   时间,持续时间,时期和   间隔没有类表示   在Java SE中。结果,开发者   经常使用int来表示a   持续时间,使用javadoc   指定单位。

     

缺乏全面的约会和   时间模型也导致许多共同点   操作比他们更棘手   应该。例如,计算   两个日期之间的天数   是一个特别难的问题   本。

     

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

答案 2 :(得分:27)

  • 日期实例为mutable,这几乎总是不方便。
  • 他们有双重性质。它们代表时间戳和日历日期。事实证明,这在日期计算时会出现问题。
  • 在许多情况下,日历数据的数字表示是违反直觉的。例如:getMonth()从零开始,getYear()基于1900(即2009年代表109)。
  • 他们缺少您期望从Date课程中获得的许多功能。

答案 3 :(得分:12)

我觉得你...作为一名前.NET程序员,我问了同样的问题,.NET中的时间API(timepans,operator overloading)非常方便。

首先,要创建特定日期,请使用已弃用的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似乎比其他任何东西都“普遍”......

答案 4 :(得分:4)

老实说,我发现Java的Date API可用。我所看到和听到的大多数问题都涉及冗长,需要让多个班级做一些有用的事情(CalendarDateDateFormat / SimpleDateFormat )以及缺少像getDayOfWeek()这样的简单访问器。

Joda Time是Java中备受推崇的替代API,在“为什么Joda时间”部分中,它提供了一些更多的论据,说明为什么它可能是一个可行的替代方案。