2010-10-24 55 views
0

在我的项目中,我需要检查日期字符串是否计算为适当的Date对象。我决定允许yyyy-MM-dd和日期格式[(年,月,日)和(年,月,日,时,分)]。我如何检查它们是否有效?我的代码返回null“1980-01-01”和一些奇怪的日期(如3837.05.01)whon,给出了由逗号分隔的字符串:如何检查日期字符串的有效性?

private Date parseDate(String date){ 
    Date data = null; 

    // yyy-mm-dd 
    try { 
     DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT); 
     df.setLenient(false); 
     df.parse(date); 
     return data; 
    } 
    catch (Exception e) { 
     try{ 
      int[] datArr = parseStringForDate(date); 
      int len = datArr.length; 
      // year, month, day 
      if(len == 3){ 
       return new Date(datArr[0], datArr[1], datArr[2]); 
      } 
      // year, montd, day, hours, mins 
      else if(len ==5){ 
       return new Date(datArr[0], datArr[1], datArr[2], datArr[3], datArr[4]); 
      } 
      // year, month, day, hours, mins, secs 
      else if(len == 6){ 
       return new Date(datArr[0], datArr[1], datArr[2], datArr[3], datArr[4], datArr[5]); 
      } 
      else { 
       return data; 
      } 
     } 
     catch (Exception f){ 
      return data; 
     } 
    } 
} 

private int[] parseStringForDate(String s){ 
    String[] sArr = s.split(","); 
    int[] dateArr = new int[sArr.length]; 

    for(int i=0; i< dateArr.length; i++){ 
     dateArr[i] = Integer.parseInt(sArr[i]); 
    } 

    return dateArr; 
} 

我记得我不得不从一年日期减去1900,但我也看到那个月不同等,我想避免检查从日期字符串我的整数数组的每个元素。是否可以在日历或日期对象中自动解析它们?

+1

欢迎来到Stack Overflow!这不会直接解决你的问题,但你使用try-catch块来实现你的逻辑;你可能会发现,如果你保留例外条件,事情会变得更加清晰。 – Pops 2010-10-24 20:35:36

+0

与您的问题更相关:什么是yyy-mm-dd格式? “999-10-10”是指1999年10月10日?或999年10月10日? 2099年10月10日? – Pops 2010-10-24 20:38:13

+0

哎呦,应该是yyyy – dbnazz 2010-10-24 21:01:11

回答

6

您可以构建SimpleDateFormat对象为不同的字符串格式,这样(返回null如果参数不能被解析为有效日期):

// Initializing possibleFormats somewhere only once 
SimpleDateFormat[] possibleFormats = new SimpleDateFormat[] { 
    new SimpleDateFormat("yyyy-MM-dd"), 
    new SimpleDateFormat("yyyy,MM,dd"), 
    new SimpleDateFormat("yyyy,MM,dd,HH,mm") }; 
for (SimpleDateFormat format: possibleFormats) 
{ 
    format.setLenient(false); 
} 
// initializing ends 

public Date parseDate(String date) { 
    Date retVal = null; 
    int index = 0; 
    while (retVal == null && index < possibleFormats.length) { 
    try { 
     retVal = possibleFormats[index++].parse(date); 
    } catch (ParseException ex) { /* Do nothing */ } 
    } 
    return retVal; 
} 
+2

顺便说一句你可以使用for循环('for(Format f:possibleFormat){...}')来代替while循环的所有逻辑。 – 2010-10-24 20:58:10

+0

哇,这是一个很好的方法来解决这个问题。我看到的唯一问题是OP谈到在1980年和3837年获得奇怪的日期,但你只检查是否日期为空。 – TheLQ 2010-10-24 21:01:15

+1

如果抛出ParseException,这将以永无止境的循环结束 - 应该在try-catch之外增加。这也会将无效日期解析为'2010-14-24'(返回2011年2月24日) - SimpleDateFormat必须设置为非宽松。 – 2010-10-24 21:01:20

1

你这样做是错误的。你应该使用SimpleDateFormat

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 
try { 
    Date test = sdf.parse(input); 
} catch (ParseException pe) { 
    //Date is invalid, try next format 
} 
+0

好的,我看你已经更新了。但是OP使用某种三位数年份格式,所以这个答案可能没有用。 – Pops 2010-10-24 20:41:03

+0

失败时不会返回'null'。 – BalusC 2010-10-24 20:43:10

+0

如果是这种情况,而不是拼写错误,我想它仍然很有用,你可以拆分有效的分隔符,并根据读取的值预先设置1或2,然后应用SimpleDateFormat让它处理闰年和什么。 – 2010-10-24 20:43:54

0

只是为了显示最终结果,由于Csaba_H和Steve Kuo。

private Date parseDate(String date){ 

    SimpleDateFormat[] possibleFormats = new SimpleDateFormat[] { 
     new SimpleDateFormat("yyyy-MM-dd"), 
     new SimpleDateFormat("yyyy,MM,dd"), 
     new SimpleDateFormat("yyyy,MM,dd,HH,mm") }; 

    Date retVal = null; 
    for (SimpleDateFormat f: possibleFormats) { 
     f.setLenient(false); 
     try { 
      retVal = f.parse(date); 
     } catch (ParseException e) {} 
    } 
    return retVal; 
} 
+0

我很高兴提供帮助。最后一句话:你应该只构造一次可能的格式(如果你不在多线程的情况下可能是静态的),以避免构建许多“丢弃”对象;并且在成功解析之后应该返回以避免不必要的异常创建和捕获。 – 2010-10-24 21:25:49

1

对于任何人在2017年突然出现的或更高版本,这里是Java 8的解决方案:

private static DateTimeFormatter[] possibleFormats = { 
    DateTimeFormatter.ofPattern("uuuu-MM-dd").withResolverStyle(ResolverStyle.STRICT), 
    DateTimeFormatter.ofPattern("uuuu,MM,dd").withResolverStyle(ResolverStyle.STRICT), 
    DateTimeFormatter.ofPattern("uuuu,MM,dd,HH,mm").withResolverStyle(ResolverStyle.STRICT), 
    DateTimeFormatter.ofPattern("uuuu,MM,dd,HH,mm,ss").withResolverStyle(ResolverStyle.STRICT) 
}; 

public Optional<LocalDate> parseDate(String date) { 
    for (DateTimeFormatter format : possibleFormats) { 
     try { 
      LocalDate result = LocalDate.parse(date, format); 
      return Optional.of(result); 
     } catch (DateTimeParseException dtpe) { 
      // ignore, try next format 
     } 
    } 
    return Optional.empty(); 
} 

随着DateTimeFormatter你可以放心地让格式化的数组是静态的,即使在多线程环境:不像SimpleDateFormatDateTimeFormatter是线程安全的。

A LocalDate是没有时间的日期,所以如果字符串中存在任何小时和分钟,则它们将丢失。为了得到小时,分钟和秒数,你需要一个LocalDateTime,然后在字符串中没有小时和分钟的情况下,你需要一些技巧来使解析工作。您既可以尝试LocalDate.parse()也可以尝试LocalDateTime.parse(),或者您可以构建一个格式器,该格式器在不在字符串中时可以使用默认的小时数。 DateTimeFormatterBuilder可以做到这一点。

相关问题