- 由于 AM 或 PM 中的小时可以是 1 位数字,因此请指定。
appendValue
使用接受最小和最大字段宽度的重载方法。
- 正如 Edwin Dalezo 已经说过的,你可能想要
ChronoField.CLOCK_HOUR_OF_AMPM
.
- 您无条件地需要 am 或 pm,所以它应该在……之外
optionalStart()
……optionalEnd()
正如 Turing85 在评论中所说。
- 考虑您是否需要接受
am
或AM
两者兼而有之。在最后一种情况下,您需要指定不区分大小写的解析。
- 始终为格式化程序指定区域设置(一种语言)。虽然 AM 和 PM 在英语以外的其他语言中几乎不使用,但它们在其他语言中确实具有不同的值(文本)。
所以我的做法是:
String time = "2:00 am";
DateTimeFormatter format = new DateTimeFormatterBuilder()
.appendValue(ChronoField.CLOCK_HOUR_OF_AMPM, 1, 2, SignStyle.NEVER)
.appendLiteral(':')
.appendValue(ChronoField.MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(':')
.appendValue(ChronoField.SECOND_OF_MINUTE, 2)
.optionalEnd()
.appendLiteral(' ')
.appendText(ChronoField.AMPM_OF_DAY)
.toFormatter(Locale.forLanguageTag("en-AU"));
System.out.println(LocalTime.parse(time, format));
输出是:
02:00
在澳大利亚英语中,am 和 pm 是小写的(根据我的 Java 11),所以我指定了这个语言环境。只有当您的输入来自澳大利亚时,您才应该这样做,否则只会混淆(还有一些地方 am 和 pm 是小写的)。要接受来自另一个英语区域设置的小写 am 和 pm,请使用parseCaseInsensitive()
. 例如:
DateTimeFormatter format = new DateTimeFormatterBuilder()
.appendValue(ChronoField.CLOCK_HOUR_OF_AMPM, 1, 2, SignStyle.NEVER)
.appendLiteral(':')
.appendValue(ChronoField.MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(':')
.appendValue(ChronoField.SECOND_OF_MINUTE, 2)
.optionalEnd()
.appendLiteral(' ')
.parseCaseInsensitive() // Accept AM or am
.appendText(ChronoField.AMPM_OF_DAY)
.toFormatter(Locale.ENGLISH);
如果你想要一个格式模式字符串
这本身不是建议。如果您不需要不区分大小写的解析,则可以从格式模式字符串而不是构建器构建格式化程序。一方面它可能更容易出错,另一方面它更短。
DateTimeFormatter format = DateTimeFormatter
.ofPattern("h:mm[.ss] a", Locale.forLanguageTag("en-AU"));
输出和以前一样。格式模式字符串中的方括号指定秒是可选的。
如果您确实需要不区分大小写的解析,则需要构建器来指定它。
您也可以混合使用这些方法,因为构建器也接受格式模式字符串:
DateTimeFormatter format = new DateTimeFormatterBuilder()
.parseCaseInsensitive() // Accept AM or am
.appendPattern("h:mm[.ss] a")
.toFormatter(Locale.ENGLISH);