java.time
现代方法是使用 java.time 类。具体来说,MonthDay 在您的情况下。
请注意,您应始终指定 Locale 以确定在翻译月份名称时使用的人类语言。
DateTimeFormatter f = DateTimeFormatter.ofPattern( "ddMMM" , Locale.ENGLISH );
String input = "29FEB";
MonthDay md = MonthDay.parse( input , f );
您可以将其应用于年份以获取LocalDate 对象,即年-月-日的仅日期值。
LocalDate
LocalDate 类表示没有时间和时区的仅日期值。
时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因区域而异。例如,Paris France 中午夜后几分钟是新的一天,而 Montréal Québec 中仍然是“昨天”。
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
如果我们正在查看 2 月 29 日,请检查闰年。如果这不是闰年,那么你说你想搬到明年。但如果明年也不是闰年呢?你需要继续前进,直到你到达闰年。
int yearNumber today.getYear();
LocalDate ld = null;
if( md.equals( MonthDay.of( 2 , 29 ) && ( ! Year.of( today ).isLeap() ) ) {
// If asking for February 29, and this is not a leap year, move to next year, per our business rule.
… keep adding years until you find a year that *is* a leap year.
ld = md.atYear( yearNumber + x );
} else {
ld = md.atYear( yearNumber );
}
回落到 28 日
如果月日是非闰年的 2 月 29 日,则此问题有一个特殊的业务规则,即跳转到下一年。但是对于其他人来说,请注意 java.time 中的默认行为是在要求 29 日为非闰年时简单地退回到 2 月 28 日。不抛出异常。
LocalDate february28 =
MonthDay.of( 2 , 29 )
.atYear( myNonLeapYearNumber ); // 29th becomes 28th.
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、.Calendar 和 java.text.SimpleDateFormat。
Joda-Time 项目现在位于 maintenance mode,建议迁移到 java.time。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
从哪里获得 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。