Текущий путь состоит в том, чтобы использовать календарный класс. Это имеет метод setLenient , который проверит дату и бросок и исключение, если это будет вне диапазона как в Вашем примере.
Забыл добавлять: Если Вы получаете календарный экземпляр и устанавливаете время с помощью даты, это - то, как Вы получаете проверку.
Calendar cal = Calendar.getInstance();
cal.setLenient(false);
cal.setTime(yourDate);
try {
cal.getTime();
}
catch (Exception e) {
System.out.println("Invalid date");
}
Можно использовать SimpleDateFormat
, Например, что-то как:
boolean isLegalDate(String s) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.setLenient(false);
return sdf.parse(s, new ParsePosition(0)) != null;
}
С форматом даты 'прежней версии' мы можем отформатировать результат и сравнить его назад с источником.
public boolean isValidFormat(String source, String pattern) {
SimpleDateFormat sd = new SimpleDateFormat(pattern);
sd.setLenient(false);
try {
Date date = sd.parse(source);
return date != null && sd.format(date).equals(source);
} catch (Exception e) {
return false;
}
}
Этот execerpt говорит 'ложь' source=01.01.04 с шаблоном '01.01.2004'
Два комментария по использованию SimpleDateFormat.
он должен быть объявлен как статический экземпляр если объявлен как статический, доступ должен быть синхронизирован, поскольку он не является потокобезопасным
IME, который лучше, чем создание экземпляра для каждого синтаксического анализа даты.
Как показано @Maglob, основной подход состоит в том, чтобы протестировать преобразование строки в дату с помощью SimpleDateFormat.parse . При этом будут обнаружены недопустимые комбинации дня / месяца, например 31 февраля 2008 г.
Однако на практике этого бывает достаточно редко, поскольку SimpleDateFormat.parse чрезвычайно либерален. Вы можете быть обеспокоены двумя вариантами поведения:
Недействительные символы в строке даты Удивительно, но 2008-02-2x будет "проходить" как допустимую дату с locale format = "yyyy-MM-dd", например. Даже если isLenient == false.
Годы: 2, 3 или 4 цифры? Вы также можете использовать 4-значные годы вместо того, чтобы разрешать поведение SimpleDateFormat по умолчанию (которое будет интерпретировать «12-02-31» по-разному в зависимости от того, был ли ваш формат «yyyy-MM-dd» или «yy-MM-dd» )
Таким образом, полная проверка строки до даты может выглядеть так: комбинация совпадения регулярного выражения и последующего принудительного преобразования даты. Уловка с регулярным выражением состоит в том, чтобы сделать его совместимым с локалью.
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);
Обратите внимание, что регулярное выражение предполагает, что строка формата содержит только день, месяц, год и символы-разделители. Кроме того, формат может быть в любом формате локали: «д / ММ / гг», «гггг-ММ-дд» и так далее. Строку формата для текущего языкового стандарта можно получить следующим образом:
Locale locale = Locale.getDefault();
SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateInstance(DateFormat.SHORT, locale );
String format = sdf.toPattern();
I ' Я недавно слышал о joda time и решил сравнить. Два момента:
Это довольно просто использовать:
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;
}
Альтернативным строгим решением с использованием стандартной библиотеки является выполнение следующего:
1) Создайте строгий SimpleDateFormat, используя свой шаблон
2) Попытка для синтаксического анализа введенного пользователем значения с использованием объекта формата
3) В случае успеха переформатируйте дату, полученную из (2), используя тот же формат даты (из (1))
4) Сравните переформатированную дату с исходной, введенное пользователем значение. Если они равны, то введенное значение строго соответствует вашему шаблону.
Таким образом, вам не нужно создавать сложные регулярные выражения - в моем случае мне нужно было поддерживать весь синтаксис шаблона SimpleDateFormat, а не ограничиваться определенными типами, такими как дни, месяцы и годы.