Joe*_*ore 7 java database datetime date
我已经阅读了关于日期操作的所有其他Q/A,但它们似乎都没有给我满意的答案.
我有一个地理位置不同的用户项目,它Date在一些类和数据中使用.问题是我正在寻找一种有效的方法来操纵各自时区中不同用户的日期,大多数答案建议使用Joda库进行Date操作,这还不太明白,因为我还没有找到任何操作你不能用传统的Java做,所以如果有人可以解释我用Joda做什么不能用传统的Java做,那么我可以考虑使用它.
我终于开始使用System.currentTimeMillis()将日期保存到数据库(任何数据库)的方法.这样可以避免让我担心使用数据库存储日期的时区.如果我想查询数据库中的特定日期或日期范围,我会使用我想要查询的long值Date来执行查询:
SELECT * FROM table1 WHERE date1>=1476653369000
Run Code Online (Sandbox Code Playgroud)
然后,在检索时,ResultSet我会使用请求数据的用户的时区long将从数据库检索到的值格式化为可读Date.
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(resultSet.getLong(1));
cal.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
Date myDate = cal.getTime();
Run Code Online (Sandbox Code Playgroud)
根据我读过的一些观点,有些人强调说存储System.currentTimeMillis()肯定不是最好的做法,然而,由于某种原因,他们都错过了说为什么它不值得推荐.我错过了什么吗?这会导致转换的性能问题Long->Date/ Date->Long?有没有使用时无法实现任何使用情况下Long,而不是Date在数据库?有人可以发布关于此的理由解释吗?
另一方面,假设我继续使用Date值来存储数据库中的日期,有没有办法避免在处理数据库时担心时区Date?
提前致谢.
Bas*_*que 25
我已经阅读了关于日期操作的所有其他Q/A.
不,你当然也不能阅读所有.
java.util.Date&java.util.Calendar)和Joda-Time项目都被java.time类取代(搜索'java.time'时为1,890个结果).我会稍微简短一点,因为所有这些已经在Stack Overflow上已经多次介绍过了.
以UTC工作.在Java中,这意味着Instant该类是常用的.该Instant级表示时间轴上的时刻UTC,分辨率为纳秒(最多9个(9)小数的位数).
Instant instant = Instant.now();
Run Code Online (Sandbox Code Playgroud)
任何严肃的数据库(如Postgres)都会以UTC格式跟踪日期时间值.JDBC驱动程序处理从数据库内部存储数据转换为Java类型的详细信息.符合JDBC 4.2及更高版本的JDBC驱动程序可以通过PreparedStatement::setObject&ResultSet::getObjectmethods 直接处理java.time类型.
myPreparedStatement.setObject( … , instant );
Run Code Online (Sandbox Code Playgroud)
对于不兼容的驱动程序,可以回退到使用java.sql类型,例如java.sql.Timestamp与数据库通信,以及通过添加到旧类的新方法转换为java.time类型.数据库如何处理日期时间值的内部细节可能与java.time的完全不同.在大多数情况下,JDBC驱动程序会隐藏您的所有细节.但是一个关键问题是解决方案,您应该在数据库中学习.java.time类处理日期时间,分辨率高达纳秒,但您的数据库可能不会.例如,Postgres使用微秒的分辨率.因此,来回往往意味着数据丢失.您希望在java.time类上使用截断方法来匹配您的数据库.
myPreparedStatement.setTimestamp( … , java.sql.Timestamp.from( instant ) );
Run Code Online (Sandbox Code Playgroud)
所以,没有涉及时区.所以没有"担心处理数据库日期时的时区".
当你想通过一个区域的挂钟时间镜头看同一时刻时,应用a ZoneId来获得一个ZonedDateTime.
ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = instant.atZone( z );
Run Code Online (Sandbox Code Playgroud)
将分区日期时间带回数据库时,提取一个Instant.
Instant instant = zdt.toInstant();
Run Code Online (Sandbox Code Playgroud)
请注意,在任何特定时刻,日期和时间在全球各个时区都有所不同.因此,如果确切的时刻很重要,例如合同到期时,请注意使用仅限日期的值.要么使用确切时刻的日期时间值,要么将预期时区与日期一起存储,以便稍后计算确切时刻.
LocalDate ld = LocalDate.of( 2016, 1 , 1 );
// Determine the first moment of 2016-01-01 as it happens in Kolkata.
ZonedDateTime zdt = ld.atStartOfDay( ZoneId.of( "Asia/Kolkata" ) );
Instant instant = zdt.toInstant(); // Adjust to UTC and store.
Run Code Online (Sandbox Code Playgroud)
该java.time框架是建立在Java 8和更高版本.这些类取代麻烦的老传统日期时间类,如java.util.Date,.Calendar,和java.text.SimpleDateFormat.
现在处于维护模式的Joda-Time项目建议迁移到java.time.
要了解更多信息,请参阅Oracle教程.并搜索Stack Overflow以获取许多示例和解释.规范是JSR 310.
从哪里获取java.time类?
该ThreeTen-额外项目与其他类扩展java.time.该项目是未来可能添加到java.time的试验场.您可以在此比如找到一些有用的类Interval,YearWeek,YearQuarter,和更多.
我可以用 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 时间。它也不一定是准确的时钟,实际上不能保证精确到毫秒。基本上,无论发生什么,都可以作为当前时间的外观。
这意味着,例如,如果您想使用多个服务器来处理传入请求,那么当您必须考虑在第二天在不同服务器上运行的程序的上下文中处理System.currentTimeMillis()from server的输出时,就会变得很棘手。AB
| 归档时间: |
|
| 查看次数: |
4430 次 |
| 最近记录: |