Java ResolverStyle 枚举
最后修改时间:2025 年 4 月 16 日
java.time.format.ResolverStyle
枚举控制日期和时间解析如何处理冲突和歧义。它是 Java 8 日期和时间 API 的一部分。该枚举定义了三种风格:STRICT(严格)、SMART(智能)和 LENIENT(宽松)。
ResolverStyle 决定了日期时间解析如何将字段解析为值。它会影响解析期间的验证。风格的选择会影响是否拒绝或调整无效日期。这对于健壮的日期时间处理至关重要。
ResolverStyle 枚举概述
ResolverStyle 枚举提供了三种解析策略。STRICT 严格遵循精确的日历规则。SMART 进行合理的调整。LENIENT 允许任何值,并处理溢出。每种风格都服务于应用程序中的不同用例。
public enum ResolverStyle { STRICT, SMART, LENIENT }
代码显示了简单的枚举定义。尽管它很简单,但它对解析行为有重大影响。该风格通常在解析操作之前在 DateTimeFormatter 上设置。
STRICT ResolverStyle
STRICT 模式根据其有效范围严格验证所有字段。它拒绝这些范围之外的任何值。当输入必须完全根据日历规则正确时,这很有用。
package com.zetcode; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.ResolverStyle; public class Main { public static void main(String[] args) { DateTimeFormatter strictFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd") .withResolverStyle(ResolverStyle.STRICT); // Valid date LocalDate validDate = LocalDate.parse("2023-02-28", strictFormatter); System.out.println("Valid date: " + validDate); try { // Invalid date (February 30 doesn't exist) LocalDate invalidDate = LocalDate.parse("2023-02-30", strictFormatter); System.out.println("This won't be printed"); } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } } }
此示例显示 STRICT 模式拒绝无效日期。2 月 30 日不存在,因此解析失败。对于其他 Resolver 风格,可能会接受相同的输入。STRICT 是验证场景的理想选择。
SMART ResolverStyle
SMART 模式对无效值进行合理的调整。在大多数情况下,它是默认样式。例如,2 月 30 日变为 2 月 28 日(或闰年的 2 月 29 日)。这平衡了验证与可用性。
package com.zetcode; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.ResolverStyle; public class Main { public static void main(String[] args) { DateTimeFormatter smartFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd") .withResolverStyle(ResolverStyle.SMART); // Adjusts February 30 to February 28 (2023 not a leap year) LocalDate adjustedDate = LocalDate.parse("2023-02-30", smartFormatter); System.out.println("Adjusted date: " + adjustedDate); // Leap year example (adjusts to February 29) LocalDate leapYearDate = LocalDate.parse("2024-02-30", smartFormatter); System.out.println("Leap year adjusted date: " + leapYearDate); } }
此示例演示了 SMART 模式的智能调整。无效日期被映射到最近的有效日期。调整考虑了闰年和月份长度。SMART 为大多数应用程序提供了良好的平衡。
LENIENT ResolverStyle
LENIENT 模式允许任何值,并通过滚动到后续单元来处理溢出。这可以在未来或过去创建遥远的日期。它对于某些计算很有用,但对于验证来说很危险。
package com.zetcode; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.ResolverStyle; public class Main { public static void main(String[] args) { DateTimeFormatter lenientFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd") .withResolverStyle(ResolverStyle.LENIENT); // Rolls over extra days to next months LocalDate rolledDate = LocalDate.parse("2023-02-45", lenientFormatter); System.out.println("Lenient date: " + rolledDate); // 2023-03-17 // Negative values roll backwards LocalDate negativeDate = LocalDate.parse("2023-02--10", lenientFormatter); System.out.println("Negative days: " + negativeDate); // 2023-01-21 } }
此示例显示了 LENIENT 模式的溢出处理。超出月份长度的天数将滚动到后续月份。负值向后滚动。这对于计算功能强大,但不适用于输入验证。
比较 ResolverStyles
不同的 Resolver 风格对相同的输入产生不同的结果。此示例并排演示了所有三种风格。比较突出了它们在有问题的输入下的不同行为。
package com.zetcode; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.ResolverStyle; public class Main { public static void main(String[] args) { String input = "2023-04-31"; // April has only 30 days DateTimeFormatter strict = DateTimeFormatter.ofPattern("uuuu-MM-dd") .withResolverStyle(ResolverStyle.STRICT); DateTimeFormatter smart = DateTimeFormatter.ofPattern("uuuu-MM-dd") .withResolverStyle(ResolverStyle.SMART); DateTimeFormatter lenient = DateTimeFormatter.ofPattern("uuuu-MM-dd") .withResolverStyle(ResolverStyle.LENIENT); try { System.out.println("STRICT: " + LocalDate.parse(input, strict)); } catch (Exception e) { System.out.println("STRICT failed: " + e.getMessage()); } System.out.println("SMART: " + LocalDate.parse(input, smart)); System.out.println("LENIENT: " + LocalDate.parse(input, lenient)); } }
此示例清楚地显示了三种行为。STRICT 拒绝无效输入。SMART 调整到最后一个有效日期。LENIENT 滚动到下个月。理解这些差异有助于为每个用例选择正确的风格。
ResolverStyle 与 DateTimeFormatterBuilder
在构建自定义格式化程序时可以设置 ResolverStyle。此示例展示了与 DateTimeFormatterBuilder 的集成。即使在复杂的格式化程序配置中,该风格也会影响解析行为。
package com.zetcode; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.ResolverStyle; import java.time.format.SignStyle; import java.time.temporal.ChronoField; public class Main { public static void main(String[] args) { DateTimeFormatter customFormatter = new DateTimeFormatterBuilder() .appendValue(ChronoField.YEAR, 4, 4, SignStyle.EXCEEDS_PAD) .appendLiteral('-') .appendValue(ChronoField.MONTH_OF_YEAR, 2) .appendLiteral('-') .appendValue(ChronoField.DAY_OF_MONTH, 2) .appendLiteral(' ') .appendValue(ChronoField.HOUR_OF_DAY, 2) .appendLiteral(':') .appendValue(ChronoField.MINUTE_OF_HOUR, 2) .toFormatter() .withResolverStyle(ResolverStyle.STRICT); try { LocalDateTime dt = LocalDateTime.parse("2023-02-30 12:30", customFormatter); System.out.println("Parsed: " + dt); } catch (Exception e) { System.out.println("Failed with STRICT: " + e.getMessage()); } } }
此示例使用 STRICT 解析构建了一个自定义格式化程序。无效日期 2 月 30 日被拒绝。相同的构建器可以使用 SMART 或 LENIENT 风格。该风格会影响格式化程序的所有解析操作。
ResolverStyle 与 Year-Month 模式
ResolverStyle 对年份月份解析的影响与完整日期不同。此示例显示了年份月份模式下的行为。该风格会影响如何处理无效的月份值。
package com.zetcode; import java.time.YearMonth; import java.time.format.DateTimeFormatter; import java.time.format.ResolverStyle; public class Main { public static void main(String[] args) { DateTimeFormatter strict = DateTimeFormatter.ofPattern("uuuu-MM") .withResolverStyle(ResolverStyle.STRICT); DateTimeFormatter smart = DateTimeFormatter.ofPattern("uuuu-MM") .withResolverStyle(ResolverStyle.SMART); String input = "2023-13"; // Invalid month 13 try { YearMonth.parse(input, strict); } catch (Exception e) { System.out.println("STRICT rejects month 13: " + e.getMessage()); } try { YearMonth.parse(input, smart); } catch (Exception e) { System.out.println("SMART also rejects month 13: " + e.getMessage()); } // LENIENT allows month overflow DateTimeFormatter lenient = DateTimeFormatter.ofPattern("uuuu-MM") .withResolverStyle(ResolverStyle.LENIENT); YearMonth lenientYm = YearMonth.parse("2023-13", lenient); System.out.println("LENIENT rolls over: " + lenientYm); // 2024-01 } }
此示例表明 SMART 和 STRICT 都会拒绝月份 13。只有 LENIENT 允许它通过滚动到下一年。此行为与完整日期中的日期处理不同。了解这些细微差别可以避免意外情况。
来源
在本文中,我们彻底探讨了 ResolverStyle 枚举及其对日期时间解析的影响。理解这些风格有助于在 Java 应用程序中构建健壮的日期时间处理。
作者
列出所有Java教程。