Blo*_*ler 78 java validation calendar date
我发现很奇怪Date
在Java中创建对象的最明显的方法已经被弃用,并且似乎被"替换"了一个不太明显的使用宽松日历.
如何检查日期,月份和年份组合的日期是否为有效日期?
例如,2008-02-31(如yyyy-mm-dd)将是无效日期.
Ara*_*ram 73
键是df.setLenient(false); .这对于简单的案例来说已经足够了.如果您正在寻找更强大(我怀疑)和/或替代库,如joda-time,那么请用户"tardate"查看答案
final static String DATE_FORMAT = "dd-MM-yyyy";
public static boolean isDateValid(String date)
{
try {
DateFormat df = new SimpleDateFormat(DATE_FORMAT);
df.setLenient(false);
df.parse(date);
return true;
} catch (ParseException e) {
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
tar*_*ate 48
如@Maglob所示,基本方法是使用SimpleDateFormat.parse测试从字符串到日期的转换.这将捕获无效的日/月组合,如2008-02-31.
然而,在实践中,由于SimpleDateFormat.parse非常自由,因此很少.您可能会关注两种行为:
日期字符串中的字符无效 令人惊讶的是,2008-02-2x将作为有效日期"传递",例如,语言环境格式="yyyy-MM-dd".即使isLenient == false.
年份:2,3或4位数? 您可能还希望强制执行4位数年而不是允许默认的SimpleDateFormat行为(根据您的格式是"yyyy-MM-dd"还是"yy-MM-dd",它将以不同的方式解释"12-02-31" )
因此,完整的字符串到目前为止测试可能如下所示:正则表达式匹配的组合,然后是强制日期转换.正则表达式的技巧是使它对语言环境友好.
Date parseDate(String maybeDate, String format, boolean lenient) {
Date date = null;
// test date string matches format structure using regex
// - weed out illegal characters and enforce 4-digit year
// - create the regex based on the local format string
String reFormat = Pattern.compile("d+|M+").matcher(Matcher.quoteReplacement(format)).replaceAll("\\\\d{1,2}");
reFormat = Pattern.compile("y+").matcher(reFormat).replaceAll("\\\\d{4}");
if ( Pattern.compile(reFormat).matcher(maybeDate).matches() ) {
// date string matches format structure,
// - now test it can be converted to a valid date
SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateInstance();
sdf.applyPattern(format);
sdf.setLenient(lenient);
try { date = sdf.parse(maybeDate); } catch (ParseException e) { }
}
return date;
}
// used like this:
Date date = parseDate( "21/5/2009", "d/M/yyyy", false);
Run Code Online (Sandbox Code Playgroud)
请注意,正则表达式假定格式字符串仅包含日,月,年和分隔符.除此之外,格式可以是任何语言环境格式:"d/MM/yy","yyyy-MM-dd"等.可以像这样获取当前语言环境的格式字符串:
Locale locale = Locale.getDefault();
SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateInstance(DateFormat.SHORT, locale );
String format = sdf.toPattern();
Run Code Online (Sandbox Code Playgroud)
我最近听说过joda时间,并且认为我会比较.两点:
它使用起来非常简单:
import org.joda.time.format.*;
import org.joda.time.DateTime;
org.joda.time.DateTime parseDate(String maybeDate, String format) {
org.joda.time.DateTime date = null;
try {
DateTimeFormatter fmt = DateTimeFormat.forPattern(format);
date = fmt.parseDateTime(maybeDate);
} catch (Exception e) { }
return date;
}
Run Code Online (Sandbox Code Playgroud)
Mag*_*lob 38
您可以使用SimpleDateFormat
例如:
boolean isLegalDate(String s) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.setLenient(false);
return sdf.parse(s, new ParsePosition(0)) != null;
}
Run Code Online (Sandbox Code Playgroud)
Ada*_*amC 33
目前的方法是使用日历类.它有setLenient方法,如果它超出范围,将验证日期和抛出以及异常.
忘记添加:如果您获得日历实例并使用日期设置时间,这就是您获得验证的方式.
Calendar cal = Calendar.getInstance();
cal.setLenient(false);
cal.setTime(yourDate);
try {
cal.getTime();
}
catch (Exception e) {
System.out.println("Invalid date");
}
Run Code Online (Sandbox Code Playgroud)
Bas*_*que 21
使用严格模式上java.time.DateTimeFormatter
,以解析LocalDate
.陷阱DateTimeParseException
.
LocalDate.parse( // Represent a date-only value, without time-of-day and without time zone.
"31/02/2000" , // Input string.
DateTimeFormatter // Define a formatting pattern to match your input string.
.ofPattern ( "dd/MM/uuuu" )
.withResolverStyle ( ResolverStyle.STRICT ) // Specify leniency in tolerating questionable inputs.
)
Run Code Online (Sandbox Code Playgroud)
解析后,您可能会检查合理的值.例如,过去一百年内的出生日期.
birthDate.isAfter( LocalDate.now().minusYears( 100 ) )
Run Code Online (Sandbox Code Playgroud)
避免使用最早版本的Java附带的麻烦的旧日期时间类.现在取代了java.time类.
LocalDate
&DateTimeFormatter
&ResolverStyle
该LocalDate
级表示没有时间一天和不同时区的日期,唯一的价值.
String input = "31/02/2000";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "dd/MM/uuuu" );
try {
LocalDate ld = LocalDate.parse ( input , f );
System.out.println ( "ld: " + ld );
} catch ( DateTimeParseException e ) {
System.out.println ( "ERROR: " + e );
}
Run Code Online (Sandbox Code Playgroud)
的java.time.DateTimeFormatter
类可以被设置与任何在定义了三种模式从宽解析字符串ResolverStyle
枚举.我们在上面的代码中插入一行来尝试每种模式.
f = f.withResolverStyle ( ResolverStyle.LENIENT );
Run Code Online (Sandbox Code Playgroud)
结果:
ResolverStyle.LENIENT
ResolverStyle.SMART
ResolverStyle.STRICT
我们可以看到在ResolverStyle.LENIENT
模式下,无效日期向前移动相同的天数.在ResolverStyle.SMART
模式(默认值)下,做出逻辑决定,将日期保持在月份内,并在2月29日的闰年中与当月的最后一天保持一致,因为该月没有第31天.该ResolverStyle.STRICT
模式抛出异常,抱怨没有这样的日期.
根据您的业务问题和政策,所有这三项都是合理的.在您的情况下,您希望严格模式拒绝无效日期而不是调整它.
该java.time框架是建立在Java 8和更高版本.这些类取代麻烦的老传统日期时间类,如java.util.Date
,Calendar
,和SimpleDateFormat
.
现在处于维护模式的Joda-Time项目建议迁移到java.time类.
要了解更多信息,请参阅Oracle教程.并搜索Stack Overflow以获取许多示例和解释.规范是JSR 310.
您可以直接与数据库交换java.time对象.使用符合JDBC 4.2或更高版本的JDBC驱动程序.不需要字符串,不需要课程.java.sql.*
从哪里获取java.time类?
该ThreeTen-额外项目与其他类扩展java.time.该项目是未来可能添加到java.time的试验场.您可以在此比如找到一些有用的类Interval
,YearWeek
,YearQuarter
,和更多.
Mat*_*aun 12
使用Java 8及更高版本中内置的Date和Time API(java.time类),您可以使用LocalDate
该类.
public static boolean isDateValid(int year, int month, int day) {
boolean dateIsValid = true;
try {
LocalDate.of(year, month, day);
} catch (DateTimeException e) {
dateIsValid = false;
}
return dateIsValid;
}
Run Code Online (Sandbox Code Playgroud)
建立在应允@Pangea来解决这个问题所指出的@ceklock,我添加了一个方法来验证dateString
不包含任何无效字符.
我是这样做的:
private boolean isDateCorrect(String dateString) {
try {
Date date = mDateFormatter.parse(dateString);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return matchesOurDatePattern(dateString); //added my method
}
catch (ParseException e) {
return false;
}
}
/**
* This will check if the provided string matches our date format
* @param dateString
* @return true if the passed string matches format 2014-1-15 (YYYY-MM-dd)
*/
private boolean matchesDatePattern(String dateString) {
return dateString.matches("^\\d+\\-\\d+\\-\\d+");
}
Run Code Online (Sandbox Code Playgroud)
小智 6
使用标准库的另一种严格解决方案是执行以下操作:
1)使用您的模式创建严格的SimpleDateFormat
2)尝试使用format对象解析用户输入的值
3)如果成功,使用相同的日期格式(从(1))重新格式化由(2)得到的日期
4)将重新格式化的日期与用户输入的原始值进行比较.如果它们相等,则输入的值严格匹配您的模式.
这样,您不需要创建复杂的正则表达式 - 在我的情况下,我需要支持所有SimpleDateFormat的模式语法,而不是仅限于某些类型,例如几天,几个月和几年.
我建议你使用org.apache.commons.validator.GenericValidator
apache 的类。
GenericValidator.isDate(String value, String datePattern, boolean strict);
注意:strict - 是否与 datePattern 完全匹配。
小智 5
我认为最简单的就是将字符串转换为日期对象并将其转换回字符串。如果两个字符串仍然匹配,则给定的日期字符串很好。
public boolean isDateValid(String dateString, String pattern)
{
try
{
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
if (sdf.format(sdf.parse(dateString)).equals(dateString))
return true;
}
catch (ParseException pe) {}
return false;
}
Run Code Online (Sandbox Code Playgroud)