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

2022-09-01 19:31:15

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

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

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

  • 使用 joda-time 而不是 java.util.Calendar
  • 将 Web 服务器设置为 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);

这表示时间上的“瞬间”,无论时区如何。您应该能够将这段时间保留在数据库之间,而不必担心发生任何类型的“转换”。数据库是否在上海时区,而Web服务器在洛杉矶时区并不重要 - 无论如何,时间的瞬间都是一样的。

一个问题是一些数据库试图为你管理时区(我正在看着你,Postgres!grr!),更糟糕的是,JDBC驱动程序级别的行为是特定于供应商的 - 即ReaddStatement.setDate/getDate。

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

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

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


答案 1

直到现在,我从未看过date4j,但是我通读了文档,我有一个具体的问题,以及一个关于它的问题的看法。

第一,具体问题。它不维护内部时区。因此,夏令时存在歧义。考虑周日的转换,即 1:59:59am (EDT) 变为 1:00:00am (EST)。显然,在那一天,说凌晨1:30是模棱两可的。这个时间发生两次。所以下面是模棱两可的

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

第二,我的意见。Date的问题在于它没有维护时区。当日历出现时,损害已经造成。此外,日历本身并没有通过可变性给自己带来任何好处。但从本质上讲,解决方案不仅要包括时刻,还要包括感知它的地方 - 时区,文化,区域设置之类的东西。然后,当它们持久化到数据库,序列化,通信等等时,需要与时刻一起维护。同样的个人原则使我谦卑地认为,即使是xsd:dateTime也不足,因为它只是允许相对于UTC表示日期+时间,它没有规定来提供是否,例如,是否遵守夏令时。


答案 2

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

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

缺少一个很可能是库没有被广泛采用的原因。


推荐