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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4010258/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:21:45  来源:igfitidea点击:

How to check validity of Date String?

javavalidationdate

提问by dbnazz

In my project I need to check if a date string evaluates to a proper Date object. I've decided to allow yyyy-MM-dd, and Date formats [(year, month, date) and (year, month, date, hrs, min)]. How can I check if they're valid ? My code returns null for "1980-01-01" and some strange dates (like 3837.05.01) whon giving a string separated by commas :

在我的项目中,我需要检查日期字符串是否计算为正确的 Date 对象。我决定允许 yyyy-MM-dd 和日期格式 [(year, month, date) and (year, month, date, hrs, min)]。我如何检查它们是否有效?我的代码为“1980-01-01”和一些奇怪的日期(如 3837.05.01)返回空值,他们给出了一个用逗号分隔的字符串:

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;
}

I remember that I had to subtract 1900 from year date, but I also see that month is different etc, and I'd like to avoid checking every element of my array of ints from date string. Is it possible to parse them automatically in Calendar or date object ?

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

回答by Csaba_H

You can construct SimpleDateFormatobjects for your different String formats like this (returning nullif the parameter cannot be parsed as a valid date):

您可以像这样为不同的 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;
}

回答by Vinko Vrsalovic

You are doing this the wrong way. You should use SimpleDateFormat.

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

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

回答by Ole V.V.

For anyone popping by in 2017 or later, here is the Java 8 solution:

对于在 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();
}

With DateTimeFormatteryou can safely let the array of formatters be static even in a multithreaded environment: unlike SimpleDateFormat, a DateTimeFormatteris thread safe.

有了DateTimeFormatter你可以放心地让格式化的阵列是,即使在多线程环境中静:不像SimpleDateFormat,一个DateTimeFormatter是线程安全的。

A LocalDateis a date without a time, so if any hours and minutes were present in the string, they are lost. To get the hours, minutes and seconds out too you need a LocalDateTime, and then you need some trickery to make the parsing work in the cases where there are no hours and minutes in the string. You may either try both LocalDate.parse()and LocalDateTime.parse(), or you may build a formatter that has a default for hours to use when not in the string. DateTimeFormatterBuildercan do that.

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

回答by dbnazz

Just to show the final outcome, thanks to Csaba_H and Steve Kuo.

只是为了展示最终结果,感谢 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;
}