Java:检查当前字符串的日期格式是否符合要求的格式

80

我想知道在Java中是否有可用的方法来实现这一点。否则,我可能会采用正则表达式的解决方案。

我从用户那里得到了一个可以包含任何字符的输入字符串。我想检查输入字符串是否符合我要求的日期格式。

例如,如果我的输入是20130925,而我的要求格式是dd/MM/yyyy,那么对于这种情况,我应该得到false

我不想转换此日期,我只想检查输入字符串是否符合所需的日期格式。



我尝试过以下方法:

Date date = null;
try {
date = new SimpleDateFormat("dd/MM/yyyy").parse("20130925");
} catch (Exception ex) {
// do something for invalid dateformat
}

但是我的catch(Exception ex)代码块无法捕获任何由SimpleDateFormat.Parse()生成的异常。


2
您的示例代码现已过时。那些令人烦恼的旧日期时间类现在是遗留的。被java.time类所取代。 - Basil Bourque
8个回答

132

免责声明

将一个字符串解析回一个未知格式的日期/时间值是本质上不可能的(面对现实吧,3/3/3 到底意味着什么?!),我们所能做的只是尽力而为。

重要提示

这个解决方案不会抛出异常,它返回一个布尔值,这是设计上的。任何Exception都只是用作保护机制。

2018

由于现在已经是2018年了,Java 8+拥有了日期/时间API(其余还有ThreeTen backport)。这个解决方案基本上保持不变,但会稍微复杂一些,因为我们需要进行以下检查:

  • 日期和时间
  • 仅日期
  • 仅时间

这使得它看起来像...

public static boolean isValidFormat(String format, String value, Locale locale) {
    LocalDateTime ldt = null;
    DateTimeFormatter fomatter = DateTimeFormatter.ofPattern(format, locale);

    try {
        ldt = LocalDateTime.parse(value, fomatter);
        String result = ldt.format(fomatter);
        return result.equals(value);
    } catch (DateTimeParseException e) {
        try {
            LocalDate ld = LocalDate.parse(value, fomatter);
            String result = ld.format(fomatter);
            return result.equals(value);
        } catch (DateTimeParseException exp) {
            try {
                LocalTime lt = LocalTime.parse(value, fomatter);
                String result = lt.format(fomatter);
                return result.equals(value);
            } catch (DateTimeParseException e2) {
                // Debugging purposes
                //e2.printStackTrace();
            }
        }
    }

    return false;
}

这将导致以下的结果...

System.out.println("isValid - dd/MM/yyyy with 20130925 = " + isValidFormat("dd/MM/yyyy", "20130925", Locale.ENGLISH));
System.out.println("isValid - dd/MM/yyyy with 25/09/2013 = " + isValidFormat("dd/MM/yyyy", "25/09/2013", Locale.ENGLISH));
System.out.println("isValid - dd/MM/yyyy with 25/09/2013 12:13:50 = " + isValidFormat("dd/MM/yyyy", "25/09/2013  12:13:50", Locale.ENGLISH));
System.out.println("isValid - yyyy-MM-dd with 2017-18--15 = " + isValidFormat("yyyy-MM-dd", "2017-18--15", Locale.ENGLISH));

输出...

isValid - dd/MM/yyyy with 20130925 = false
isValid - dd/MM/yyyy with 25/09/2013 = true
isValid - dd/MM/yyyy with 25/09/2013 12:13:50 = false
isValid - yyyy-MM-dd with 2017-18--15 = false

原始回答

尝试使用类似于SimpleDateFormat的工具将String解析为所需的Date

Date date = null;
try {
    SimpleDateFormat sdf = new SimpleDateFormat(format);
    date = sdf.parse(value);
    if (!value.equals(sdf.format(date))) {
        date = null;
    }
} catch (ParseException ex) {
    ex.printStackTrace();
}
if (date == null) {
    // Invalid date format
} else {
    // Valid date format
}

你可以编写一个简单的方法来执行此操作,并在Date不为null时返回true...

以下是建议...

使用运行示例进行更新

我不确定你在做什么,但以下示例...

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class TestDateParser {

    public static void main(String[] args) {
        System.out.println("isValid - dd/MM/yyyy with 20130925 = " + isValidFormat("dd/MM/yyyy", "20130925"));
        System.out.println("isValid - dd/MM/yyyy with 25/09/2013 = " + isValidFormat("dd/MM/yyyy", "25/09/2013"));
        System.out.println("isValid - dd/MM/yyyy with 25/09/2013 12:13:50 = " + isValidFormat("dd/MM/yyyy", "25/09/2013  12:13:50"));
    }

    public static boolean isValidFormat(String format, String value) {
        Date date = null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            date = sdf.parse(value);
            if (!value.equals(sdf.format(date))) {
                date = null;
            }
        } catch (ParseException ex) {
            ex.printStackTrace();
        }
        return date != null;
    }

}

输出(类似于)...

java.text.ParseException: Unparseable date: "20130925"
isValid - dd/MM/yyyy with 20130925 = false
isValid - dd/MM/yyyy with 25/09/2013 = true
isValid - dd/MM/yyyy with 25/09/2013 12:13:50 = false
    at java.text.DateFormat.parse(DateFormat.java:366)
    at javaapplication373.JavaApplication373.isValidFormat(JavaApplication373.java:28)
    at javaapplication373.JavaApplication373.main(JavaApplication373.java:19)
不正确的。对于isValidFormat("yyyy-MM-dd", "2017-18--15"); 不会抛出任何异常。
isValid - yyyy-MM-dd", "2017-18--15 = false

对我来说,它似乎按预期工作-该方法不仅依赖于(也不会抛出)异常来执行其操作


1
我以前尝试过,但无法理解为什么没有方式可以捕获该异常。在你的回答后,我再次尝试了一遍,出现了同样的问题。我有意地以mm/dd/yyyy格式传递日期,但它并未进入catch块。 - Elvin
尝试 { date = new SimpleDateFormat("dd/MM/yyyy").parse(sDOB); } catch (ParseException e) { System.out.println(e.toString()); } - Elvin
1
@mnicky 好的,因此格式化了生成的“日期”(使用相同的模式),并将其与原始日期进行了比较。这比使用正则表达式更好,因为它可以“验证”或使日期无效。 :P - MadProgrammer
1
@TylerHoppe 实际上,有一个内部测试,它会获取生成的 Date,根据提供的 format 进行格式化,并检查结果是否与原始的 value 匹配,在您的情况下,这将返回 false,表示格式不匹配所提供的值。我甚至尝试了前导和尾随字符,它仍然会返回 false(正如我所预期的那样)。 - MadProgrammer
1
@D.B. 因为它将允许不匹配格式的日期通过,就像TylerHoppe试图做的那样,但我并没有看到这是最初的问题,问题是关于将日期与特定格式匹配,因此这是一个严格的匹配。 - MadProgrammer
显示剩余24条评论

47

对于您的情况,您可以使用正则表达式:

boolean isValidFormat = input.matches("([0-9]{2})/([0-9]{2})/([0-9]{4})");

如果您需要更广泛的范围或者想要一个灵活的解决方案,请参考MadProgrammer的答案。

编辑

发布此回答将近5年后,我意识到这是一种愚蠢的验证日期格式的方法。但我还是会把它留在这里告诉人们,使用正则表达式验证日期是不可接受的。


1
这是做这件事的好方法!其他方法都是老派的... - Clemzd
32
除了你可以输入像“99/99/9999”这样明显无效的内容之外,你还可以做一些其他的事情。 ;P - MadProgrammer
2
我需要一个正则表达式来满足类似于2015-9-18和2015-09-18这两种格式。 - user5268786
2016年9月12日,16年8月3日,2015年10月6日怎么样? - Yan Khonski
1
你可以像这样内联执行:checkformat = input.matches("([0-9]{2})/([0-9]{2})/([0-9]{4})") - luiscosta
1
不可能!如果我们进一步开发它,比如添加String[] t = value.split("/"); return (Integer.valueOf(t[0]) <= 31 && Integer.valueOf(t[1]) <= 12);并支持所有API,这将是最聪明的解决方案。当然,我们可以使用switch case来处理不同月份的天数。 - Taufik Nur Rahmanda

25

您可以尝试使用此方法来进行简单的日期格式验证

 public Date validateDateFormat(String dateToValdate) {

    SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HHmmss");
    //To make strict date format validation
    formatter.setLenient(false);
    Date parsedDate = null;
    try {
        parsedDate = formatter.parse(dateToValdate);
        System.out.println("++validated DATE TIME ++"+formatter.format(parsedDate));

    } catch (ParseException e) {
        //Handle exception
    }
    return parsedDate;
}

2
这对我有用。相当简单。谢谢! - Emiliano Zilocchi
请注意,像java.util.Datejava.util.Calendarjava.text.SimpleDateFormat这样的旧日期时间类现在已经成为遗留系统,被内置于Java 8及更高版本中的java.time类所取代。请参阅Oracle的教程 - Basil Bourque
它对我起作用了。唯一完美的解决方案。 - Fawad Khaliq

20
DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
formatter.setLenient(false);
try {
    Date date= formatter.parse("02/03/2010");
} catch (ParseException e) {
    //If input date is in different format or invalid.
}

formatter.setLenient(false) 会强制执行严格匹配。

如果您正在使用Joda-Time -

private boolean isValidDate(String dateOfBirth) {
        boolean valid = true;
        try {
            DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy");
            DateTime dob = formatter.parseDateTime(dateOfBirth);
        } catch (Exception e) {
            valid = false;
        }
        return valid;
    }

4
这个解决方案如何解决问题,如果您能进行解释就更好了。 - Markus W Mahlberg
@MarkusWMahlberg 完成。 - tiwari.vikash
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy"); 这个对我有用。谢谢。 - undefined

4
这里有一个简单的方法:
public static boolean checkDatePattern(String padrao, String data) {
    try {
        SimpleDateFormat format = new SimpleDateFormat(padrao, LocaleUtils.DEFAULT_LOCALE);
        format.parse(data);
        return true;
    } catch (ParseException e) {
        return false;
    }
}

2
例如,如果您想要日期格式为“03.11.2017”。
 if (String.valueOf(DateEdit.getText()).matches("([1-9]{1}|[0]{1}[1-9]{1}|[1]{1}[0-9]{1}|[2]{1}[0-9]{1}|[3]{1}[0-1]{1})" +
           "([.]{1})" +
           "([0]{1}[1-9]{1}|[1]{1}[0-2]{1}|[1-9]{1})" +
           "([.]{1})" +
           "([20]{2}[0-9]{2})"))
           checkFormat=true;
 else
           checkFormat=false;

 if (!checkFormat) {
 Toast.makeText(getApplicationContext(), "incorrect date format! Ex.23.06.2016", Toast.LENGTH_SHORT).show();
                }

0

我相信正则表达式和SimpleDateFormat的组合是正确的答案。如果单个组件无效,SimpleDateFormat不会捕获异常,这意味着格式定义为:yyyy-mm-dd,输入为:201-0-12,不会抛出异常。这种情况应该得到处理。但是,使用Sok Pomaranczowy和Baby建议的正则表达式将处理这种特殊情况。


-1
正则表达式可以用于此,提供一些详细信息进行验证。例如,可以使用以下代码验证任何以(DD/MM/yyyy)格式表示的日期,确保日期和月份的值正确,并且年份在1950-2050之间。
    public Boolean checkDateformat(String dateToCheck){   
        String rex="([0]{1}[1-9]{1}|[1-2]{1}[0-9]{1}|[3]{1}[0-1]{1})+
        \/([0]{1}[1-9]{1}|[1]{1}[0-2]{2})+
        \/([1]{1}[9]{1}[5-9]{1}[0-9]{1}|[2]{1}[0]{1}([0-4]{1}+
        [0-9]{1}|[5]{1}[0]{1}))";

        return(dateToCheck.matches(rex));
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接