我目前正在用Java编写验证方法,以检查字符串是否为几种不同的格式之一,以便更改为日期。
我希望它接受的格式如下:MM / DD / YY,M / DD / YY,MM / D / YY和M / D / YY。
我正在测试第一种格式,每当它告诉我即使我进入有效日期它也无效。
以下是我目前的代码:
public class IsDateFormatValid
{
public boolean isValid(String date)
{
boolean result = true;
if(date.length()>8||date.length()<6)
{
result= false;
}
if(date.length()==8)
{
if((Character.toString(date.charAt(2))!= "/")||(Character.toString(date.charAt(5))!="/"))
{
result=false;
}
}
if(date.length()==7)
{
if((Character.toString(date.charAt(2))!="/"&&Character.toString(date.charAt(1))!="/") ||(Character.toString(date.charAt(3))!="/"&&Character.toString(date.charAt(4))!= "/"))
{
result=false;
}
}
return result;
}
}
我仍然需要为最后一个格式案例添加条件。我做了一个调试方法,发现总是返回false的部分是说:if((Character.toString(date.charAt(2))!=“/")||(Character.toString(date.charAt) (5))!= “/”))
这个问题的主要观点是尝试针对多种格式进行检查,而不仅仅是单一格式,这里的大多数其他问题都是如此。
答案 0 :(得分:7)
您可能希望迭代可能的格式,例如:
实施例
private static String[] date_formats = {
"yyyy-MM-dd",
"yyyy/MM/dd",
"dd/MM/yyyy",
"dd-MM-yyyy",
"yyyy MMM dd",
"yyyy dd MMM",
"dd MMM yyyy",
"dd MMM yyyy"
};
/**
* A brute-force workaround for Java's failure to accept "any arbitrary date format"
*/
public static Date tryDifferentFormats (String sDate) {
Date myDate = null;
for (String formatString : date_formats) {
try {
SimpleDateFormat format = new SimpleDateFormat(formatString);
format.setLenient(false);
myDate = format.parse(sDate);
break;
}
catch (ParseException e) {
// System.out.println(" fmt: " + formatString + ": FAIL");
}
}
return myDate;
}
答案 1 :(得分:6)
一种可能很昂贵的简单方法;但不知何故,反对良好做法是这样的:
要使用格式进行解析,您可以查看此question。
正如彼得指出的那样,这个解决方案并非线程安全。所以你需要调查那个question来处理它。
另一方面,当像paulsm4那样建议时;你避免了线程问题...但不幸的是,你正在创建很多的格式化程序对象;之后你立即扔掉了。谈论浪费CPU周期和创建内存垃圾&#34;那里。
选项2;更少&#34;昂贵&#34;是想出一个(或多个)正则表达式来匹配给定格式的字符串。但是,当然,它并不像苏珊娜所建议的那样容易;如你所知,你真的想拒绝像#34; 55/66/77&#34;它完全匹配一个简单的正则表达式,它只检查&#34;两个数字两个数字冲破两个数字&#34;。
所以,是的,选项1很贵;所以这里的问题是:你的验证应该有多好?你想拒绝语法上的日期和#34;正确的#34;但那是&#34;语义上&#34;错了,比如&#34; 02/29/15&#34; (2015年不是闰年!)?!
更新:考虑到这一点,一个很好的解决方案就像:
Map<Regex, String>
,其值为一个字符串,可用作&#34;格式化程序输入&#34 ;;并且相应的密钥是&#34;匹配&#34;的正则表达式。格式答案 2 :(得分:4)
尝试匹配正则表达式,它会减少你正在做的工作。
if(date.matches("\\d{1-2}\\\\d{1-2}\\\\d{1-2}")){
// ..do something
}
答案 3 :(得分:0)
DateTimeFormatter
。!=
来比较字符串。除非我完全误解,否则格式的变化是月份可以是一位或两位数,月份中的一天可以是一位或两位数。我们可以将其作为一种单一格式进行处理。与其他两个答案一样,我认为对于大多数目的而言,最好对我们是否有有效的日期进行全面验证。不仅仅是数字位数和斜线位置的验证(正如Susannah Potts回答的那样,正则表达式可以做到)。因此,我们需要做的是:
1。定义格式器
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("M/d/uu")
.withResolverStyle(ResolverStyle.STRICT);
一个模式字母M
将以一个或两位数字匹配月份数字。每月d
类似。
首先让我们看看这一点。
System.out.println(LocalDate.parse("12/28/66", dateFormatter));
System.out.println(LocalDate.parse("11/06/37", dateFormatter));
System.out.println(LocalDate.parse("11/2/58", dateFormatter));
System.out.println(LocalDate.parse("03/14/35", dateFormatter));
System.out.println(LocalDate.parse("05/04/68", dateFormatter));
System.out.println(LocalDate.parse("09/3/06", dateFormatter));
System.out.println(LocalDate.parse("5/23/99", dateFormatter));
System.out.println(LocalDate.parse("1/06/00", dateFormatter));
System.out.println(LocalDate.parse("2/8/76", dateFormatter));
输出为:
2066-12-28 2037-11-06 2058-11-02 2035-03-14 2068-05-04 2006-09-03 2099-05-23 2000-01-06 2076-02-08
2。尝试解析和捕获异常
String dateString = "12/28/66";
try {
LocalDate.parse(dateString, dateFormatter);
System.out.println(dateString + " is valid");
} catch (DateTimeParseException dtpe) {
System.out.println(dateString + " is not valid: " + dtpe.getMessage());
}
12/28/66 is valid
尝试使用不遵循任何格式的日期字符串:
String dateString = "ab/cd/ef";
ab/cd/ef is not valid: Text 'ab/cd/ef' could not be parsed at index 0
我建议使用java.time(现代Java日期和时间API)。一个答案中使用的Date
和SimpleDateFormat
类的设计很差,而且已经过时了,后者特别麻烦。 java.time更好用。
有两个问题。
一个,正如您所说的,此if
条件的总值为true
,这会使您的result
设置为false
:
if((Character.toString(date.charAt(2))!= "/")||(Character.toString(date.charAt(5))!="/"))
将字符串与!=
进行比较并不符合您的期望。这将测试两个字符串对象是否相同,而不是两个字符串是否相等。 Character.toString()
将创建一个新的字符串对象,因此,它将始终是"/"
之外的另一个对象。因此,即使来自Character.toString()
的字符串也包含一个斜杠,!=
的计算结果仍为true。
第二,您不能验证斜线之前,之间和之后的字符是否为数字。