25

我最近遇到了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!),更糟糕的是,JDBC 驱动程序级别的行为是特定于供应商的——即 PreparedStatement.setDate/getDate。

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

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

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

4

2 回答 2

7

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

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

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

第二,我的看法。Date 的问题在于它没有维护时区。当 Calendar 出现时,损害已经造成。此外,Calendar 本身并没有因为可变而给自己带来任何好处。但从本质上讲,解决方案必须不仅包括时刻,还包括感知它的地方——时区、文化、地区之类的东西。然后需要在持久化到数据库、序列化、通信等时同时维护这些内容。同样的个人原则使我谦虚地建议即使 xsd:dateTime 也不足,因为它仅允许相对于 UTC 表示日期+时间,它没有规定是否提供例如是否遵守夏令时。

于 2011-08-25T05:23:14.903 回答
1

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

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

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

于 2015-07-01T16:38:21.543 回答