简而言之
- 修复未填充月份和日期的格式模式。
- 仅使用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
,因为您的输入字符串缺少任何时区或偏移量指示器。这个值不是一个瞬间,也不是时间线上的一个点。它只是一个大约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);
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教程。在Stack Overflow上搜索许多示例和说明。规范为JSR 310。
您可以直接使用与JDBC 4.2或更高版本兼容的JDBC驱动程序,直接将java.time对象与数据库进行交换。无需使用字符串或java.sql.*
类。
我们从哪里获取java.time类?
ThreeTen-Extra项目扩展了java.time的附加类。该项目是java.time可能未来添加内容的试验场。您可能会在这里找到一些有用的类,例如Interval
, YearWeek
, YearQuarter
, 以及more。
Instant
)和存在问题的传统类(Date
和SimpleDateFormat
)。只需使用java.time类;它们完全取代了旧类。 - Basil Bourque