我使用YearQuarter库中的ThreeTen-Extra代表给定年份内的特定季度。
我使用的是自定义格式而不是默认格式,例如2018年第三季度的“3Q2018”而不是“2018-Q3”。当通过YearQuarter.parse(text, formatter)解析一个值时,我希望拒绝该季度前导零的值(通过标准的DateTimeParseException)。
我的第一次尝试是使用DateTimeFormatter.ofPattern("Q'Q'yy")
。但是,这会在本季度前接受任意多个前导零的字符串。例如,此格式化程序不会拒绝“02Q2007”或“002Q2007”。
这似乎与如何处理其他时间类型的单个字符模式一致。例如,这些成功解析没有错误:
YearMonth.parse("012-2018", DateTimeFormatter.ofPattern("M-yyyy"))
LocalTime.parse("001:00:01", DateTimeFormatter.ofPattern("H:mm:ss"))
LocalTime.parse("01:00:012", DateTimeFormatter.ofPattern("HH:mm:s"))
但是,这些用DateTimeParseException
拒绝输入:
YearMonth.parse("012-2018", DateTimeFormatter.ofPattern("MM-yyyy"))
LocalTime.parse("001:00:01", DateTimeFormatter.ofPattern("HH:mm:ss"))
LocalTime.parse("01:00:012", DateTimeFormatter.ofPattern("HH:mm:ss"))
我如何构建一个DateTimeFormatter来解析我所需格式的YearQuarter
,同时拒绝该季度超过一位数的值?理想情况下,我希望将其作为模式字符串,因为人们更容易阅读,并且更容易外化为文本属性。
我还没有发现一种方法来做一个模式字符串,但以下将以编程方式构造一个具有所需格式的DateTimeFormatter
,拒绝0填充的四分之一:
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.IsoFields;
[...]
new DateTimeFormatterBuilder()
.appendValue(IsoFields.QUARTER_OF_YEAR, 1)
.appendLiteral('Q')
.appendValue(ChronoField.YEAR, 4)
.toFormatter();
如果你坚持使用模式字符串,那么我担心在DateTimeFormatter
的上下文中没有办法,但我已成功测试了我的lib Time4J,如果它提供了所需的行为:
ChronoFormatter<CalendarQuarter> f =
ChronoFormatter.ofPattern(
"Q'Q'uuuu", PatternType.CLDR, Locale.ROOT, CalendarQuarter.chronology());
CalendarQuarter cq = f.parse("3Q2018");
System.out.println(cq); // 2018-Q3
f.parse("13Q2018"); // exception
f.parse("03Q2018"); // exception
CalendarQuarter类型的对象对应于YearQuarter
,因此您可以找到类似的方法将其更改为格里高利日期,例如:
CalendarQuarter cq = f.parse("3Q2018");
LocalDate ld = cq.atEndOfQuarter().toTemporalAccessor();
System.out.println(ld); // 2018-09-30