【问题标题】:Java Date validationJava 日期验证
【发布时间】:2011-09-07 10:21:05
【问题描述】:

我需要将用户输入验证为有效日期。用户可以输入 dd/mm/yyyy 或 mm/yyyy(两者都有效)

为了验证我正在做的事情

try{
    GregorianCalendar cal = new GregorianCalendar(); 
    cal.setLenient(false);  
    String []userDate = uDate.split("/");
    if(userDate.length == 3){
        cal.set(Calendar.YEAR, Integer.parseInt(userDate[2]));  
        cal.set(Calendar.MONTH, Integer.parseInt(userDate[1]));  
        cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(userDate[0]));
        cal.getTime(); 
    }else if(userDate.length == 2){
        cal.set(Calendar.YEAR, Integer.parseInt(userDate[1]));  
        cal.set(Calendar.MONTH, Integer.parseInt(userDate[0]));  
        cal.getTime(); 
    }else{
            // invalid date
    }
}catch(Exception e){
    //Invalid date
}

因为 GregorianCalendar 以 0、30/01/2009 或 12/2009 开始月份会出错。

任何建议如何解决这个问题。

【问题讨论】:

  • mm/yyyy 的格式是否足以让您验证它?
  • 用户只能提供有效的月份和年份。不是一个月中的一天。所以 mm/yyyy 在这种情况下也是有效的。
  • 如果这个应用程序。有一个 GUI,一个明显的答案是为用户提供一个日期选择器,该选择器只能选择有效日期(例如,没有周末或公共假期)。
  • cal.getTime() 自己不做任何事情。您必须使用该表达式的结果。
  • 仅供参考,麻烦的旧日期时间类,如 java.util.Datejava.util.Calendarjava.text.SimpleDateFormat 现在是 legacy,被 Java 8 及更高版本中内置的 java.time 类所取代.见Tutorial by Oracle

标签: java date


【解决方案1】:

使用SimpleDateformat。如果解析失败,它会抛出 ParseException:

private Date getDate(String text) throws java.text.ParseException {

    try {
        // try the day format first
        SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
        df.setLenient(false);

        return df.parse(text);
    } catch (ParseException e) {

        // fall back on the month format
        SimpleDateFormat df = new SimpleDateFormat("MM/yyyy");
        df.setLenient(false);

        return df.parse(text);
    }
}

【讨论】:

  • 我同意您应该使用 SimpleDateFormat,但您的示例不完整:如果不对 SimpleDateFormat 调用“setLenient(false)”,它将接受无效输入并将其转换为无意义的日期。此外,您需要在尝试第二种格式之前捕获第一种 parse() 引发的异常。
  • @Arnout:好点,当你写你的评论时我已经在更新了...... :)
  • @sn s:分隔符是/,如果你想要.,你需要提供格式字符串为"dd.mm.yyyy",但这不起作用,例如"07/01/2001"。
  • @dacwe 它接受 25.45.2001 作为有效日期。知道为什么它不给出异常
  • @sn s:更新(MM 而不是mm)!
【解决方案2】:

使用SimpleDateFormat 验证DatesetLenientfalse

【讨论】:

    【解决方案3】:

    tl;博士

    使用try - catch 来捕获java.time 类中LocalDate.parseYearMonth.parse 抛出的DateTimeParseException

    java.time

    现代方法使用 java.time 类。

    YearMonth

    对于没有日期的年月,请使用YearMonth 类。

    如果可能,让您的用户使用标准的ISO 8601 格式输入数据:YYYY-MMjava.time 类在解析/生成字符串时默认使用标准格式。

    YearMonth ym = YearMonth.parse( "2018-01" ) ;
    

    如果不可能,请指定格式模式。

    DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/uuuu" ) ;
    YearMonth ym = YearMonth.parse( "01/2018" , f ) ;
    

    要测试无效输入,请捕获异常。

    DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/uuuu" ) ;
    YearMonth ym = null ;
    try{
        ym = YearMonth.parse( "01/2018" , f ) ;
    } catch ( DateTimeParseException e ) {
        // Handle faulty input
        …
    }
    

    LocalDate

    对于仅日期值、没有时间和时区,请使用 LocalDate 类。

    同样,如果可能,请使用标准 ISO 8601 格式进行数据输入:YYYY-MM-DD

    LocalDate ld = LocalDate.parse( "2018-01-23" ) ;
    

    如果不是,请指定格式模式并捕获异常,如上所示。

    DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu" ) ;
    LocalDate ld = null ;
    try{
        ld = LocalDate.parse( "23/01/2018" , f ) ;
    } catch ( DateTimeParseException e ) {
        // Handle faulty input
        …
    }
    

    结合

    如果输入可能是仅日期或年月,则测试输入的长度以确定哪个是哪个。

    int length = input.length() ;
    switch ( length ) {
        case 7 :
            …  // Process as year-month using code seen above.
    
        case 10 :
            …  // Process as date-only using code seen above.
    
        default: 
            …  // ERROR, unexpected input.
    }
    

    关于java.time

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

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

    要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

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

    从哪里获得 java.time 类?

    ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

    【讨论】:

      猜你喜欢
      • 2020-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多