Java 8 DateTimeFormatter 的符号 "F"

Java 8 DateTimeFormatter's symbol "F"

java.time.format.DateTimeFormatterBuilder中:

/** Map of letters to fields. */
private static final Map<Character, TemporalField> FIELD_MAP = new HashMap<>();

static {
    // SDF = SimpleDateFormat
    // ...
    FIELD_MAP.put('F', ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH);  // SDF, LDML
    // ...
}

说明符号“F”在SimpleDateFormatter(SDF)中可能具有相同的含义。

在 SDF 中,符号“F”表示指定星期几的序号,例如“五月的第二个星期日”、母亲节(美国)。
使用 SDF,我可以将 2021 年的母亲节(美国)定义为“2021-05-2-Sun”,模式为“yyyy-MM-F-EEE”。
但是任何带有 DateTimeFormatter 符号“F”的模式都可能导致 DateTimeParseException。
我发现了一个已经“修复”的问题:
[JDK-8169482]java.time.DateTimeFormatter javadoc: F is not week-of-month
但它只是“修复”了 javadoc! Σ(っ°Д°;)っ
符号“F”仍具有未定义的行为。

SDF“F: Day of week in month”中令人困惑的描述可能是原因。

由于错误的解决是修复文档,而不是修复 DateTimeFormatter 的实现,因此 F 的意思似乎是 ALIGNED_DAY_OF_WEEK_IN_MONTH,并且只是// SDF的评论还没有更正。

并且因为它表示 ALIGNED_DAY_OF_WEEK_IN_MONTH,所以像“2021-05-2-Sun”这样的日期没有多大意义。你只给出了一个月和一年,以及星期几。这些信息不足以确定现在是一个月中的哪一天。 “2021-05-2-Sun”不会发生这种情况,但在“2021-05-2-Mon”这样的情况下,星期几 (Mon) 和对齐的星期几 (2) 甚至可以说关于应该是星期几的不同事情。 :)

要解析“星期几”,您需要 ALIGNED_WEEK_OF_MONTH,其中 DateFormatter doesn't have a symbol for. (Note that W is the non-aligned week of month.) But don't worry, you can append any TemporalField into the pattern with appendValue:

DateTimeFormatter formatter =
    new DateTimeFormatterBuilder()
        .appendPattern("yyyy-MM-")
        .appendValue(ChronoField.ALIGNED_WEEK_OF_MONTH)
        .appendPattern("-EEE").toFormatter(Locale.ENGLISH);

用法:

System.out.println(LocalDate.parse("2021-05-2-Sun", formatter));
// 2021-05-09