我已阅读有关日期操作的所有其他问答
不,你确实没有读过它们。
- 您会了解到传统的日期时间类(例如
java.util.Date 和 java.util.Calendar)和 Joda-Time 项目都被 java.time 类所取代(在 'java.time 上搜索的 1,890 个结果')。
- 您将学会不将日期时间值作为从纪元开始的计数来跟踪。由于人类无法将长整数的含义解读为日期时间,因此调试和日志记录变得非常困难,因为无法发现错误。并且由于在各种软件项目中使用了许多计数粒度(整秒、毫秒、微秒、纳秒、整天等)和至少一个 couple dozen of epochs,因此会导致您的数据模棱两可,假设会导致错误、误解和混淆.
- 您应该已经学会在数据库中使用日期时间类型来跟踪日期时间值。
- 您应该已经学会了以 UTC 格式工作和存储日期时间值。仅在逻辑需要或用户预期的情况下调整到时区以进行演示。 “放眼全球,立足本土。”
- 您会了解到,尽管是业界首创的勇敢尝试,但旧的日期时间类设计不佳、令人困惑且麻烦。请参阅What's wrong with Java Date & Time API? 进行一些讨论。 Joda-Time 是业界第一个优秀的日期时间库,并激发了它的替代品,即 Java 8 及更高版本中内置的 java.time 类。
我会稍微简短一些,因为所有这些内容已经在 Stack Overflow 上多次介绍过。
在 UTC 工作。在 Java 中,这意味着 Instant 类是常用的。 Instant 类代表UTC 中时间线上的时刻,分辨率为nanoseconds(最多九 (9) 位小数)。
Instant instant = Instant.now();
任何重要的数据库(例如 Postgres)都以 UTC 跟踪日期时间值。您的 JDBC 驱动程序处理从数据库内部存储的数据转换为 Java 类型的细节。符合JDBC 4.2 及更高版本的JDBC 驱动程序可以通过PreparedStatement::setObject 和ResultSet::getObject 方法直接处理java.time 类型。
myPreparedStatement.setObject( … , instant );
对于不兼容的驱动程序,回退到使用 java.sql.Timestamp 等 java.sql 类型与数据库通信,并通过添加到旧类的新方法转换为 java.time 类型。数据库如何处理日期时间值的内部细节可能与 java.time 的处理方式完全不同。在大多数情况下,JDBC 驱动程序对您隐藏了所有细节。但是一个关键问题是分辨率,你应该在你的数据库中研究它。 java.time 类处理分辨率高达nanoseconds 的日期时间,但您的数据库可能不会。例如,Postgres 使用microseconds 的分辨率。因此,来回意味着数据丢失。您想使用 java.time 类的截断方法来匹配您的数据库。
myPreparedStatement.setTimestamp( … , java.sql.Timestamp.from( instant ) );
因此,不涉及时区。因此,无需“在处理数据库日期时担心时区”。
如果您想通过某个地区的wall-clock time 的镜头看到同一时刻,请应用ZoneId 以获得ZonedDateTime。
ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = instant.atZone( z );
将分区日期时间返回数据库时,提取Instant。
Instant instant = zdt.toInstant();
请注意,对于任何特定时刻,日期和时间在全球各地都会因时区而异。因此,如果确切的时间很重要,例如合同到期时,请注意使用仅日期值。要么使用日期时间值作为确切时刻,要么将预期时区存储在仅日期旁边,以便稍后计算确切时刻。
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.
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、.Calendar 和 java.text.SimpleDateFormat。
Joda-Time 项目现在位于 maintenance mode,建议迁移到 java.time。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
从哪里获得 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。