避免使用旧的日期时间类
避免使用麻烦的旧日期时间类,例如 java.util.Date。仅使用 java.time 类。同样,Joda-Time 项目现在也被 java.time 类所取代,这两个类都是由同一个人 Stephen Colebourne 创建的。
Instant
将您的Date 转换为Instant。这两个类都代表UTC 中的一个时刻,总是在UTC 中,尽管Date::toString 方法对你撒谎。
使用添加到旧类的新方法进行转换。
Instant instant = myJavaUtilDate.toInstant() ;
ZonedDateTime
将时区或与 UTC 的偏移量应用于您的一对时间字符串预期的挂钟时间。你是说纽约的下午 5 点,突尼斯的下午 5 点,还是印度的下午 5 点?
以continent/region 的格式指定proper time zone name,例如America/Montreal、Africa/Casablanca 或Pacific/Auckland。切勿使用 3-4 个字母的缩写,例如 EST 或 IST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ; // Or "Pacific/Auckland" etc.
ZonedDateTime zdt = instant.atZone( z ) ;
提取没有日期和区域的时间。
LocalTime lt = zdt.toLocalTime() ;
LocalTime
将您的限制解析为LocalTime 对象。
DateTimeFormatter f = DateTimeFormatter.ofPattern( "h:mm a" , Locale.US ) ;
LocalTime start = LocalTime.parse( "5:03 PM" , f ) ;
LocalTime stop = LocalTime.parse( "5:11 PM" , f ) ;
半开
通常最好使用半开方法来定义时间跨度。这意味着开头是inclusive,而结尾是exclusive。因此,如果您想排除第 10 分钟的所有内容,请测试“五点后不到十一点”。
提示:“等于或在之后”的更简短的说法是“不在之前”。
if ( ( ! lt.isBefore( start ) ) && lt.isBefore( stop ) ) {
zdt = zdt.with( stop ) ; // Change to a different time-of-day.
}
如果该区域中该日期的时间无效,ZonedDateTime 类会根据需要进行调整。
数据库
为了在TIMESTAMP WITH TIME ZONE 类型的列中保存到数据库,让我们通过提取Instant 将时刻调整为UTC。
Instant instantForDatabase = zdt.toInstant() ;
…
myPreparedStatement.setObject( … , instantForDatabase ) ;
从数据库中检索。
Instant instantFromDatabase = myResultSet.getObject( … , Instant.class ) ;
ZoneId zMontreal = ZoneId.of( "America/Montreal" ) ; // Or "Asia/Kolkata" etc.
ZondDateTime zdtMontreal = instantFromDatabase.atZone( zMontreal ) ;
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。
从哪里获得 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。