我已经阅读了所有其他关于日期操纵的问答,但似乎没有一个对我的担忧给出满意的答案。
我有一个项目,地理位置不同的用户在它的一些类和数据中使用Date
。问题是,我正在寻找一种有效的方法来操纵不同用户在各自时区的日期,大多数答案建议使用Joda库进行Date
操纵,我还不太明白,因为我还没有发现任何传统Java不能做的操作,所以如果有人能解释一下我用Joda能做什么传统Java不能做的事情,那么我可能会考虑使用它。
最后我想到了使用System.currentTimeMillis()
将我的日期保存到数据库(任何数据库)中的方法。这将避免我担心哪个时区使用数据库存储日期。如果我想查询数据库中的特定日期或日期范围,我将使用我要查询的Date
的long
值执行查询:
SELECT * FROM table1 WHERE date1>=1476653369000
字符串
当检索ResultSet
时,我会使用请求数据的用户的时区将从数据库检索到的long
值格式化为可读的Date
。
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(resultSet.getLong(1));
cal.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
Date myDate = cal.getTime();
型
根据我读到的一些观点,有些人强调存储System.currentTimeMillis()
绝对不是最佳实践,然而,出于某种原因,他们都没有说为什么它是不可复制的。我错过了什么吗?这会导致转换Long->Date
/Date->Long
的性能问题吗?当在数据库中使用Long
而不是Date
时,是否有任何用例无法完成?有人可以对此发表合理的解释吗?
另一方面,假设我一直使用Date
值在数据库中存储日期,有没有一种方法可以避免在处理数据库Date
时担心时区?
先谢了。
2条答案
按热度按时间x8diyxa71#
我已阅读有关日期操纵的所有其他问答
不,你肯定没有把它们都读完。
java.util.Date
和java.util.Calendar
)和Joda-Time项目都被java.time类取代了(在“java. time”上搜索1,890个结果)。我将稍微简短一点,因为所有这些都已经在堆栈溢出中讨论了 * 很多 * 次。
在UTC中工作。在Java中,这意味着通常使用
Instant
类。Instant
类以UTC表示时间轴上的时刻,分辨率为nanoseconds(最多九(9)位小数)。字符串
任何严肃的数据库(如Posterre)都可以跟踪UTC中的日期时间值。JDBC驱动程序处理从数据库内部存储的数据转换为Java类型的详细信息。符合JDBC 4.2和更高版本的JDBC驱动程序可以通过
PreparedStatement::setObject
和ResultSet::getObject
方法直接处理java.time类型。型
对于不兼容的驱动程序,请退回到使用java.sql类型(如
java.sql.Timestamp
)与数据库通信,并通过添加到旧类中的新方法与java.time类型进行转换。数据库处理日期时间值的内部细节可能与java.time处理日期时间值的内部细节有很大不同。在大多数情况下,JDBC驱动程序对您隐藏了所有的实质性细节。但一个关键问题是解决方案。你应该在你的数据库中学习。java.time类处理的日期时间的分辨率最高为nanoseconds,但你的数据库可能不是。例如,Posterre使用的分辨率为microseconds。所以来回转换意味着数据丢失。你想在java.time类上使用截断方法来匹配你的数据库。型
因此,不涉及时区。所以没有“在处理数据库日期时担心时区”。
当您想要透过某个区域的wall-clock time的透镜看到相同的瞬间时,请套用
ZoneId
以取得ZonedDateTime
。型
将分区日期-时间带回数据库时,提取一个
Instant
。型
请注意,对于任何给定的时刻,日期和一天中的时间在地球仪各地因时区而异。因此,如果某个确切的时刻很重要,例如合同到期时,请注意不要使用仅日期值。要么为确切的时刻使用日期-时间值,要么将所需的时区与仅日期值一起存储,以便以后可以计算确切的时刻。
型
关于java.时间
java.time框架内置于Java 8和更高版本中。这些类取代了麻烦的旧的legacy日期-时间类,如
java.util.Date
、.Calendar
和java.text.SimpleDateFormat
。Joda-Time项目(现在在maintenance mode中)建议迁移到java. time。
要了解更多信息,请参阅Oracle Tutorial。并搜索堆栈溢出以获得许多示例和解释。规范是JSR 310。
在哪里可以获得java.time类?
*Java SE 8和SE 9及更高版本
*Java SE 6和SE 7
ThreeTen-Extra项目使用其他类扩展了java.time。此项目是将来可能添加到java. time的试验场。您可能会在此处找到一些有用的类,如
Interval
、YearWeek
、YearQuarter
和more。3zwtqj6y2#
我能用Joda做什么传统Java做不到的事情
这并不是说在一般情况下你能或不能用传统Java做什么,而是说库API如何工作,使你比传统Java更容易编写更好(更健壮和正确)的代码。
如此之多,以至于到Java 8时,Joda API或多或少被逐字复制/采用,只是改变了包名并合并到Java 8 SE标准库中。
因此,如果你正在使用Java 8,你应该选择新的API,如果不是,你应该考虑使用Joda至少会为你升级/移植到Java 8铺平道路。
举几个例子:
toString()
这样的东西的默认设置是合理的,所以序列化/重序列化可以以最小的努力正确工作。Instant
的概念表示“绝对”时间戳,这在使用地理分布式系统时(当系统默认时钟/时区和DST规则可能不同时)或用于互操作时非常有用,因为它使用UTC。编辑以添加:
根据我读到的一些观点,有些人强调存储
System.currentTimeMillis()
绝对不是最佳实践,然而,出于某种原因,他们都没有说为什么它是不可存储的。System.currentTimeMillis()
有几个缺点。最大的缺点是时钟的类型定义不清。它可能是单调时钟,可能是受DST和时区影响的时钟,也可能是UTC时间。它也不一定是准确的时钟,它实际上并不能保证精确到毫秒。只是无论什么碰巧是手的东西,将工作作为一个语义的电流现在的时间,基本上。这意味着,如果你想使用多个服务器来处理传入的请求,比如说,当你必须考虑在第二天在不同的服务器
B
上运行程序的上下文中处理来自服务器A
的System.currentTimeMillis()
的输出时,这就变得很棘手了。