tl;博士
- 修复未填充月份和日期的格式模式。
- 仅使用 java.time 类,切勿使用旧类。
人为的例子:
LocalDateTime.parse( // Parse as an indeterminate `LocalDate`, devoid of time zone or offset-from-UTC. NOT a moment, NOT a point on the timeline.
"04:30 PM, Sat 5/12/2018" , // This input uses a poor choice of format. Whenever possible, use standard ISO 8601 formats when exchanging date-time values as text. Conveniently, the java.time classes use the standard formats by default when parsing/generating strings.
DateTimeFormatter.ofPattern( "hh:mm a, EEE M/d/uuuu" , Locale.US ) // Use single-character `M` & `d` when the number lacks a leading padded zero for single-digit values.
) // Returns a `LocalDateTime` object.
.atZone( // Apply a zone to that unzoned `LocalDateTime`, giving it meaning, determining a point on the timeline.
ZoneId.of( "America/Toronto" ) // Always specify a proper time zone with `Contintent/Region` format, never a 3-4 letter pseudo-zone such as `PST`, `CST`, or `IST`.
) // Returns a `ZonedDateTime`. `toString` → 2018-05-12T16:30-04:00[America/Toronto].
.toInstant() // Extract a `Instant` object, always in UTC by definition.
.toString() // Generate a String in standard ISO 8601 format representing the value within this `Instant` object. Note that this string is *generated*, not *contained*.
2018-05-12T20:30:00Z
使用一位数的格式化模式
您在格式化模式中使用了MM,这意味着任何一位数的值(1 月至 9 月)都将显示带有填充的前导零。
但是您的输入缺少填充的前导零。所以使用单个M。
我期望的每月日期同上:d 而不是 dd。
仅使用 java.time
您正在使用有缺陷的旧日期时间类(Date 和SimpleDateFormat),这些类在多年前已被 java.time 类取代。新的阶级完全取代了旧的阶级。无需将传统与现代混为一谈。
LocalDateTime
解析为LocalDateTime,因为您的输入字符串缺少time zone 或offset-from-UTC 的任何指示符。这样的值是不是一个时刻,是不是时间轴上的一个点。这只是大约 26-27 小时范围内的一组潜在时刻。
String input = "04:30 PM, Sat 5/12/2018";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "hh:mm a, EEE M/d/uuuu" , Locale.US ); // Specify locale to determine human language and cultural norms used in translating that input string.
LocalDateTime ldt = LocalDateTime.parse( input , f );
ldt.toString(): 2018-05-12T16:30
ZonedDateTime
如果您确定输入旨在使用加拿大多伦多地区人们使用的挂钟时间来表示某个时刻,请应用ZoneId 来获取ZonedDateTime 对象。
分配时区为您未分区的LocalDateTime 赋予意义。现在我们有一个时刻,时间轴上的一个点。
ZoneId z = ZoneId.of( "America/Toronto" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ; // Give meaning to that `LocalDateTime` by assigning the context of a particular time zone. Now we have a moment, a point on the timeline.
zdt.toString(): 2018-05-12T16:30-04:00[美国/多伦多]
Instant
要查看与UTC 相同的时刻,请提取Instant。同一时刻,不同的挂钟时间。
Instant instant = zdt.toInstant() ;
instant.toString(): 2018-05-12T20:30:00Z
关于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。