简述
只需使用LocalDate
,忘记所有关于Calendar
(麻烦的旧类)的问题。
LocalDate.parse( "2000-01-31" ).plusMonths( 1 ).toString()
2000年2月29日
方法1
方法1:使用LocalDate plusMonths():
LocalDate
类的文档解释了它首先添加月份,保持日期不变。如果该日期在该月份中无效(例如29、30或31),则向后调整到上一个有效日期。
此方法将按以下三个步骤将指定数量添加到月份字段中:
- 将输入月份添加到年份字段中
- 检查结果日期是否无效
- 必要时将日期调整为上一个有效日期
例如,2007-03-31加一月会导致无效日期2007-04-31。而不是返回无效结果,选择该月的最后一个有效日期2007-04-30。
我认为这是一个聪明的方法。
在您的示例中,LocalDate
首先将2000-01-31
更改为2000-02-31
。二月没有31号,因此它向后走到30号。但是二月也没有30日。所以它继续向后走到29日。恭喜!在那一年的那个月中确实有29天,因为2000年是闰年。因此答案是2000-02-29
。
LocalDate.parse( "2000-01-31" )
.plusMonths( 1 )
.toString()
2000-02-29
方法2
方法2:使用Calendar:
不要再烦恼了。
这个极其麻烦的旧的Calendar
类现已被完全取代,由JSR 310中定义的java.time类替代。具体而言,被ZonedDateTime
替换。
永远不要再碰Calendar
类了。节省一些痛苦和头疼,假装这个类从未存在过。
此外,Calendar
是一个带有时间值的日期。不适合像问题中那样只有日期的值。
转换旧版<->现代版
如果您必须与尚未更新到java.time的代码进行交互,请通过调用添加到旧类中的新转换方法在旧类和java.time之间进行转换。有关更多信息,请参见问题:将java.util.Date转换为“java.time”类型?
关于java.time
java.time框架内置于Java 8及更高版本。这些类取代了麻烦的旧旧版日期时间类,例如java.util.Date
、Calendar
和SimpleDateFormat
。
Joda-Time项目现在处于维护模式,建议迁移到java.time类。
要了解更多,请参阅
Oracle Tutorial。并在Stack Overflow上搜索许多示例和解释。规范为
JSR 310。
您可以直接与数据库交换
java.time对象。使用符合
JDBC 4.2或更高版本的
JDBC驱动程序。不需要字符串,也不需要
java.sql.*
类。
如何获取java.time类?
ThreeTen-Extra 项目是在 java.time 的基础上扩展出的额外类库。该项目是可能未来添加到 java.time 中的一个试验场。您可以在这里找到一些有用的类,例如
Interval
、
YearWeek
、
YearQuarter
等等。
更多信息。
zcal.add(Calendar.MONTH, 0)
不会改变日历的日期,因为你加的是零。此外,zcal.set(Calendar.MONTH, 1)
将月份设置为二月,因为 Calendar.FEBRUARY 等于 1,而不是 2。Calendar.JANUARY 是 0。许多人认为这是一个设计错误,但无论如何,如果你使用常量而不是字面整数值,就不会有这个问题。 - VGRjava.util.Date
、java.util.Calendar
和java.text.SimpleDateFormat
等老旧的日期-时间类现已成为遗留的类,已被内置于 Java 8 及更高版本的 java.time 类所取代。请参阅 Oracle 的 教程。 - Basil Bourque