我最近遇到了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 这样的库?