tl;博士
- 不要使用
DateUtil。 (也许是 Apache DateUtils 库?)
- 不要使用糟糕的旧日期时间类,例如
java.util.Date。
- 使用现代行业领先的 java.time 类。
解析缺少偏移量的字符串,然后为 UTC 本身分配零偏移量的代码。
LocalDateTime // Represents a date and a time-of-day but without any concept of time zone or offset-from-UTC. NOT a moment, NOT a point on the timeline.
.parse(
"201801011000" ,
DateTimeFormatter.ofPattern( "uuuuMMddHHmm" )
)
.atOffset( ZoneOffset.UTC ) // Assign an offset-from-UTC. Do this only if you are CERTAIN this offset was originally intended for this input but was unfortunately omitted from the text. Returns an `OffsetDateTime`.
.toInstant() // Extract an `Instant` from the `OffsetDateTime`. Basically the same thing. But `Instant` is always in UTC by definition, so this type is more appropriate if your intention is to work only in UTC. On the other hand, `Instant` is a basic class, and `OffsetDateTime` is more flexible such as various formatting patterns when generating `String` object to represent its value.
使用 java.time
Java 中的现代方法使用 java.time 类。这个行业领先的框架取代了非常麻烦的旧日期时间类,例如Date、Calendar 和SimpleDateFormat。
DateTimeFormatter
解析您的输入字符串。定义要匹配的格式模式。
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMddHHmm" ) ;
String input = "201801011000" ;
LocalDateTime
解析为 LocalDateTime,因为您的输入缺少时区指示符或与 UTC 的偏移量。
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
缺少区域或偏移意味着这不代表一个时刻,不是时间轴上的一个点。相反,这代表了大约 26-27 小时范围内的潜在时刻,即全球时区范围。
OffsetDateTime
如果您确定此日期和时间旨在表示 UTC 中的某个时刻,请应用常量 ZoneOffset.UTC 以获取 OffsetDateTime 对象。
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;
ZonedDateTime
您的问题含糊不清。听起来您可能知道用于此输入的特定时区。如果是这样,分配一个ZoneId 以获得一个ZonedDateTime 对象。
了解与 UTC 的偏移只是小时、分钟和秒数。不多也不少。相比之下,时区要多得多。时区是某个地区的人们使用的偏移量的过去、现在和未来变化的历史。
以continent/region 的格式指定proper time zone name,例如America/Montreal、Africa/Casablanca 或Pacific/Auckland。切勿使用 3-4 个字母的缩写,例如 EST 或 IST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
Instant
调整回 UTC 的快速方法是提取 Instant 对象。 Instant 始终采用 UTC。
Instant instan = zdt.toInstant() ;
ISO 8601
提示:不要使用自定义格式将日期时间值交换为文本,而应仅使用标准 ISO 8601 格式。标准格式实用,易于机器解析,易于跨文化的人类阅读。
java.time 类在解析/生成字符串时默认使用 ISO 8601 格式。 ZonedDateTime::toString 方法明智地扩展了标准,将区域名称附加在方括号中。
Instant instant = Instant.parse( "2018-07-23T16:18:54Z" ) ; // `Z` on the end means UTC, pronounced “Zulu”.
String output = instant.toString() ; // 2018-07-23T16:18:54Z
并且始终在字符串中包含偏移量和时区。暂时忽略偏移量/区域就像忽略价格的货币:你剩下的只是一个不值钱的模棱两可的数字。实际上,总比没有更糟糕,因为它会导致各种混乱和错误。
关于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。