am/pm 的 DateTimeFormatterBuilder
DateTimeFormatterBuilder with am/pm
我正在尝试构建一种接受 AM 和 PM 戳记的日期时间格式。例如,每当调用 java 中的 LocalTime.parse("12:00 am") 时,使用默认格式,就会抛出异常。所以我要像这样添加自己的格式
String time = "2:00 am"
DateTimeFormatter format = new DateTimeFormatterBuilder()
.appendValue(HOUR_OF_DAY, 2)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2)
.optionalStart()
.appendValue(AMPM_OF_DAY)
.toFormatter();
LocalTime.parse(time, format);
怎么好像不行。我得到:
Exception in thread "main" java.time.format.DateTimeParseException:
Text '2:00 am' could not be parsed at index 0
如何构建正确的 DateTimeFormatterBuilder 来解析以下字符串:“2:00 am”、“12:15 pm”?是的,我知道您可以附加格式,但在这种情况下,需要使用附加值。
我认为您需要将 HOUR_OF_DAY
从 (0-23) 更改为 CLOCK_HOUR_OF_AMPM
从 (1-12)。我还在 AM/PM 之前添加了一个 space 文字,并在 AM/PM 字段中使用 appendText
而不是 appendValue
。
以下工作正常。
var formatter = new DateTimeFormatterBuilder()
.appendValue(CLOCK_HOUR_OF_AMPM, 2)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(":")
.appendValue(SECOND_OF_MINUTE, 2)
.optionalStart()
.appendLiteral(" ")
.appendText(AMPM_OF_DAY)
.toFormatter();
//formatter = new DateTimeFormatterBuilder().appendPattern("hh:mm:ss a").toFormatter();
var time = LocalTime.parse("07:20:54 AM", formatted);
System.out.println(time); // 19:20:54
- 由于AM或PM中的小时可以是1位,所以指定。使用接受最小和最大字段宽度的重载
appendValue
方法。
- 正如 Edwin Daloezo 所说,您可能需要
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);
我正在尝试构建一种接受 AM 和 PM 戳记的日期时间格式。例如,每当调用 java 中的 LocalTime.parse("12:00 am") 时,使用默认格式,就会抛出异常。所以我要像这样添加自己的格式
String time = "2:00 am"
DateTimeFormatter format = new DateTimeFormatterBuilder()
.appendValue(HOUR_OF_DAY, 2)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2)
.optionalStart()
.appendValue(AMPM_OF_DAY)
.toFormatter();
LocalTime.parse(time, format);
怎么好像不行。我得到:
Exception in thread "main" java.time.format.DateTimeParseException: Text '2:00 am' could not be parsed at index 0
如何构建正确的 DateTimeFormatterBuilder 来解析以下字符串:“2:00 am”、“12:15 pm”?是的,我知道您可以附加格式,但在这种情况下,需要使用附加值。
我认为您需要将 HOUR_OF_DAY
从 (0-23) 更改为 CLOCK_HOUR_OF_AMPM
从 (1-12)。我还在 AM/PM 之前添加了一个 space 文字,并在 AM/PM 字段中使用 appendText
而不是 appendValue
。
以下工作正常。
var formatter = new DateTimeFormatterBuilder()
.appendValue(CLOCK_HOUR_OF_AMPM, 2)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(":")
.appendValue(SECOND_OF_MINUTE, 2)
.optionalStart()
.appendLiteral(" ")
.appendText(AMPM_OF_DAY)
.toFormatter();
//formatter = new DateTimeFormatterBuilder().appendPattern("hh:mm:ss a").toFormatter();
var time = LocalTime.parse("07:20:54 AM", formatted);
System.out.println(time); // 19:20:54
- 由于AM或PM中的小时可以是1位,所以指定。使用接受最小和最大字段宽度的重载
appendValue
方法。 - 正如 Edwin Daloezo 所说,您可能需要
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);