我想验证几种日期格式,如下例所示:
YYYY
YYYY-MM
YYYY-MM-DD
验证必须确保日期格式正确且日期存在。
我知道Java 8提供了一个新的Date API,所以我想知道它是否能够做这样的工作。
使用Java 8 date API有更好的方法吗? 将Calendar类与lenient参数一起使用仍然是一个好习惯吗?
答案 0 :(得分:6)
您可以使用Private Sub cmbGetClass_SelectedIndexChanged(sender As Object, e As EventArgs)
'populate the listview
showSched()
dtClass.Rows.Clear()
With dtClass
For row As Integer = 0 To lvSched.Items.Count - 1
For col As Integer = 1 To lvSched.Columns.Count - 1
.Rows.Add((lvSched.Items(row).SubItems(col).Text))
Next
Next
End With
crViewer_Class.ReportSource = dtClass
crViewer_Class.RefreshReport()
crViewer_Class.Show()
End Sub
指定缺少的字段,以使所有格式化工具正常工作:
parseDefaulting
答案 1 :(得分:4)
要验证YYYY-MM-DD
格式,您只需使用自JDK 8以来java.time
中引入的LocalDate.parse
。
从文本字符串中获取LocalDate的实例,例如 2007-12-03。
字符串必须表示有效日期并使用解析 DateTimeFormatter.ISO_LOCAL_DATE。
如果日期无效,则会抛出DateTimeParseException
。
对于您提供给我们的其他两种格式,将抛出异常。这是合乎逻辑的,因为它们不是真正的约会,只是日期的一部分。
LocalDate还提供了一种方法of(int year, int month, int dayOfMonth)
,因此,如果你真的想在某些情况下简单地验证年份,在其他情况下的月份或完整日期那么你可以做这样的事情:
public static final boolean validateInputDate(final String isoDate)
{
String[] dateProperties = isoDate.split("-");
if(dateProperties != null)
{
int year = Integer.parseInt(dateProperties[0]);
// A valid month by default in the case it is not provided.
int month = dateProperties.length > 1 ? Integer.parseInt(dateProperties[1]) : 1;
// A valid day by default in the case it is not provided.
int day = dateProperties.length > 2 ? Integer.parseInt(dateProperties[2]) : 1;
try
{
LocalDate.of(year, month, day);
return true;
}
catch(DateTimeException e)
{
return false;
}
}
return false;
}
请注意,您提到几种格式但没有提供它们,所以我认为这些只是3种。
答案 2 :(得分:3)
parseBest
您只想验证,我理解,但之后您很可能希望以适当的方式提取数据。幸运的是,正如您所写,Java 8提供了这样一种方法parseBest
。
parseBest
适用于可选字段。因此,首先定义要解析的格式:yyyy[-MM[-dd]]
,括号([
和]
)包装可选字段。
parseBest
还要求您提供多个TemporalQuery<R>
。实际上,它只是模板方法<R> R queryFrom(TemporalAccessor)
的功能包装器。因此,我们实际上可以将TemporalQuery<R>
定义为Year::from
。好的:这正是我们想要的。问题是parseBest
没有得到很好的命名:它将按顺序解析所有内容并在匹配的第一个正确的TemporalQuery
之后停止。所以在你的情况下,我们必须从最精确到最不精确。以下是您要处理的各种类型:LocalDate
,YearMonth
和Year
。因此,我们只需将TemporalQuery[]
定义为LocalDate::from, YearMonth::from, Year::from
即可。现在,如果parseBest
无法识别您的输入,则会抛出异常。
总而言之,我们将构建parseBest
,如下所示:
parseBest(DateTimeFormatter.ofPattern("yyyy[-MM[-dd]]"), LocalDate::from, YearMonth::from, Year::from);
所以让我们正确地写下来:
static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy[-MM[-dd]]");
static TemporalAccessor parseDate(String dateAsString) {
return FORMATTER.parseBest(dateAsString, LocalDate::from, YearMonth::from, Year::from);
}
但是......你只想验证......那么在这种情况下,计算一个日期并且已经完成了昂贵的工作。因此,我们只需将验证定义如下:
public static boolean isValidDate(String dateAsString) {
try {
parseDate(dateAsString);
return true;
} catch (DateTimeParseException e) {
return false;
}
}
我知道,使用异常来处理这样的情况是很糟糕的,但是当前的API非常强大时,这个非常具体的情况没有被考虑在内,所以让我们坚持下去并按原样使用它。
这是完整的代码:
import java.time.*;
import java.time.format.*;
import java.time.temporal.*;
class Main {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy[-MM[-dd]]");
static TemporalAccessor parseDate(String dateAsString) {
return FORMATTER.parseBest(dateAsString, LocalDate::from, YearMonth::from, Year::from);
}
public static boolean isValidDate(String dateAsString) {
try {
parseDate(dateAsString);
return true;
} catch (DateTimeParseException e) {
return false;
}
}
public static void main(String[] args) {
String[] datesAsString = {
"2018",
"2018-05",
"2018-05-22",
"abc",
"2018-"
};
for (String dateAsString: datesAsString) {
System.out.printf("%s: %s%n", dateAsString, isValidDate(dateAsString) ? "valid" : "invalid");
}
}
}
输出:
2018: valid
2018-05: valid
2018-05-22: valid
abc: invalid
2018-: invalid
请注意,您仍然可以使用从parseBest
检索到的数据进一步使用,如下所示:
TemporalAccessor dateAccessor = parseDate(dateAsString);
if (dateAccessor instanceof Year) {
Year year = (Year)dateAccessor;
// Use year
} else if (dateAccessor instanceof YearMonth) {
YearMonth yearMonth = (YearMonth)dateAccessor;
// Use yearMonth
} else if (dateAccessor instanceof LocalDate) {
LocalDate localDate = (LocalDate)dateAccessor;
// Use localDate
}
答案 3 :(得分:0)
public static final boolean validateInputDate(final String isoDate, final String dateFormat){
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);
try {
final Date date = simpleDateFormat.parse(isoDate);
System.out.println("Date: " + date);
return true;
} catch (ParseException e) {
e.printStackTrace();
return false;
}
}
答案 4 :(得分:0)
您可以使用宽大,默认为true
以SimpleDAteFormat
SimpleDateFormat sdf = new SimpleDateFormat(dateFromat);
sdf.setLenient(false);
或在JSON中验证:
@JsonFormat(lenient = OptBoolean.FALSE)
答案 5 :(得分:0)
请使用以下代码。这将进行验证,并且可以在每种格式下使用。
public class DateValidator {
public static void main(String[] args) {
String datetoCheck = "999999";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMMdd");
try {
LocalDate localDate = LocalDate.parse(datetoCheck, formatter);
System.out.println(localDate);
} catch ( DateTimeException ex ) {
ex.printStackTrace();
}
}
}