如何检查日期字符串的有效性?

时间:2010-10-24 20:21:14

标签: java validation date

在我的项目中,我需要检查日期字符串是否评估为正确的Date对象。我决定允许yyyy-MM-dd和日期格式[(年,月,日)和(年,月,日,小时,分)]。我怎样才能检查它们是否有效?我的代码为“1980-01-01”和一些奇怪的日期(如3837.05.01)返回null,它们用逗号分隔一个字符串:

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,但我也看到月份不同等等,我想避免从日期字符串中检查我的数组中的每个元素。是否可以在Calendar或date对象中自动解析它们?

4 个答案:

答案 0 :(得分:7)

您可以为此不同的String格式构造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;
}

答案 1 :(得分:1)

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

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

答案 2 :(得分: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,即使在多线程环境中也可以安全地让格式化程序数组保持静态:与SimpleDateFormat不同,DateTimeFormatter是线程安全的。

LocalDate是没有时间的日期,因此如果字符串中存在任何小时和分钟,则会丢失。要获得小时,分钟和秒数,您需要LocalDateTime,然后您需要一些技巧来使解析工作在字符串中没有小时和分钟的情况下。您可以同时尝试LocalDate.parse()LocalDateTime.parse(),也可以构建一个格式化程序,该字符集在不在字符串中时使用的默认值为小时。 DateTimeFormatterBuilder可以做到这一点。

答案 3 :(得分: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;
}