为什么我不应该使用date4j而不是joda java.util.Calendar或jsr 310?

时间:2011-08-25 04:40:30

标签: java timezone jodatime java.util.date

我最近遇到了date4j,这是一个非常简单的库(基本上是一个单独的类),用于处理Java中的日期。从概念上讲,我非常喜欢date4j的“想法”。事实上,在阅读了整个主站点和javadoc中的文档之后,我几乎同意所说的一切。

现在,可能是我不应该使用date4j的几个原因 - 错误,性能,缺乏用户等等。我不是在问这些事情。从概念上讲,我问的是date4j的概念有什么问题(对于那里的大多数应用程序而言)?当然,可能有一些应用程序需要像joda或threeten这样的东西 - 但我相信那些应用程序是少数。

人们给处理日期/时间的用户提供的正常建议(几乎所有人都在编写Java应用程序)是这样的:

  • 使用joda-time代替java.util.Calendar
  • 将您的网络服务器设置为UTC
  • 将数据库服务器设置为UTC
  • 以UTC格式存储您的日期时间

事实上,最后三个要点说明了人们在处理日期时目前的心理模型存在的问题。人们试图在应用程序和数据库级别管理时区(更不用说ORM框架添加了另一层抽象,这使得事情变得更加复杂)。

你不应该做那些事情。例如,如果您正在使用java.util.Calendar,并且您正在某个用户定义的时区中操作时间:

Calendar c = Calendar.getInstance(TimeZone.getTimeZone("America/New_York"));
c.set(Calendar.YEAR, 2011);
c.set(Calendar.MONTH, 0);
c.set(Calendar.DAY_OF_MONTH, 1);
c.set(Calendar.HOUR_OF_DAY, 3);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);

无论时区如何,这都代表了“瞬间”。您应该能够将此时间保留在数据库中,而不必担心会发生任何类型的“转换”。如果数据库位于上海时区并且网络服务器位于洛杉矶时区也无关紧要 - 无论何时,时间都是相同的。

一个问题是某些数据库试图为您管理时区(我正在看着你,Postgres!grr!)并使behavior at the JDBC driver level is vendor specific更糟糕 - 即PreparedStatement.setDate / GETDATE。

date4j使用的心智模型似乎摆脱了所有困惑。例如,显式强制用户在调用now()时提供时区。网站上有一些非常好的推荐使用该库(这些我以前在我自己的应用程序中已经做过的事情),例如:

  • 不要使用试图管理时区的数据库类型
  • 将时区存储为单独的列(如果需要)

为什么没有更多的人采用像date4j这样的库?

2 个答案:

答案 0 :(得分:7)

到目前为止,我从未查看过date4j,但是我阅读了文档,我有一个具体的问题,以及一个关于它有什么问题的看法。

首先,具体问题。它不会在内部维护时区。所以夏令时含糊不清。考虑周日凌晨1:59:59(美国东部夏令时间)变为凌晨1:00:00(美国东部时间)。很明显,在那一天,说凌晨1:30是模棱两可的。那个时间发生了两次。所以以下是不明确的

new DateTime("2011-11-06 01:30:00")

第二,我的意见。 Date的问题在于它没有维护时区。当Calendar出现时,损坏已经完成。此外,日历本身并没有因为可变而对自己有任何好处。但从本质上讲,解决方案不仅包括时刻,还包括感知时间 - 时区,文化,地区类型的东西。然后,这些需要与持久保存到数据库,序列化,通信等的时刻一起维护。同样的个人原则让我谦卑地建议即使xsd:dateTime也不合适,因为它只允许相对于UTC表示日期+时间,它没有规定提供是否,例如,是否正在观察夏令时。

答案 1 :(得分:1)

四年后,我遇到了这个问题。对我来说,date4j的问题#1是错误。我知道你特别没有问过这些,但这是一个主要问题。

更具体地说,错误本身并不是一个问题,它完全没有某种错误报告系统让我对date4j感到困扰。甚至还没有邮件列表,据我所知,根本没有任何东西。我知道这对于API应该是什么样的日期/时间的讨论可能并不是很有趣,但基础设施仍然很重要。

缺乏一个可能是图书馆未被广泛采用的原因。