2月29日的SimpleDateFormat分析日期错误

2022-08-24 00:00:00 simpledateformat java

我已经连接好了

   public static boolean isFirstDayOfMonth(String format, String value) {
    SimpleDateFormat sdf = new SimpleDateFormat(format);
    Date date = null;
    try {
        date = sdf.parse(value);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
    return dayOfMonth == 1;
   }

测试并返回True:

    boolean actual = CommonUtil.isFirstDayOfMonth("yyyy-MM-dd", "2021-02-29");
    assertTrue(actual);

I Found Out SimpleDateFormat将日期转换为2021年3月1日,尽管2021年没有2月29日。如果我在2021-02-30中通过,这是无效的,但它返回正确的结果。


解决方案

tl;dr

java.time.LocalDate.parse( "2021-02-29" )
…
catch ( DateTimeParseException e )  // Thrown for invalid inputs

java.time

您正在使用几年前被JSR 310中定义的java.time类取代的可怕的日期-时间类。

默认情况下,java.time.LocalDate类拒绝解析无效输入。分析异常的陷阱。

    try {
        LocalDate ld = LocalDate.parse( "2021-02-29" ) ;
        System.out.println( ld ) ;
    } catch ( DateTimeParseException e ) {
        // … handle invalid input
        System.out.println( "Faulty input" ) ;
    }

查看此code run live at IdeOne.com。


关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期-时间类,如java.util.DateCalendar、&;SimpleDateFormat

要了解更多信息,请参阅Oracle Tutorial。和搜索堆栈溢出以获取许多示例和解释。规范为JSR 310。

Joda-Time项目现在位于maintenance mode中,建议迁移到java.time类。

您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC driver。不需要字符串,也不需要java.sql.*类。Hibernate 5&;JPA 2.2支持java.time。

从哪里获取java.time类?

  • Java SE 8、Java SE 9、Java SE 10、Java SE 11以及更高版本--标准Java API的一部分,具有捆绑实现。
    • Java 9带来了一些次要功能和修复。
  • Java SE 6和Java SE 7
    • 大部分java.time功能已后移植到ThreeTen-Backport中的Java 6&;7。
  • Android
    • 更高版本的Android(26+)捆绑了java.time类的实现。
    • 对于更早的Android(<;26),API desugaring的进程带来了Android最初没有内置的subset of the java.time功能。
      • 如果去糖化不能满足您的需求,ThreeTenABP工程会将ThreeTen-Backport(上面提到的)适配到Android。请参见How to use ThreeTenABP…。

相关文章