Как показывает @Maglob, основной подход состоит в том, чтобы протестировать преобразование строки в дату с помощью SimpleDateFormat.parse . Это приведет к обнаружению недопустимых комбинаций дня / месяца, например 31.02.2008.
Однако на практике этого бывает достаточно редко, поскольку SimpleDateFormat.parse чрезвычайно либерален. Есть два варианта поведения, которые могут вас заинтересовать:
Недопустимые символы в строке даты.
Удивительно, но 2008-02-2x будет "проходить" как допустимую дату, например, с locale format = "yyyy-MM-dd". Даже когда isLenient == false.
Годы: 2, 3 или 4 цифры?
Вы также можете использовать 4-значные годы вместо того, чтобы разрешать поведение SimpleDateFormat по умолчанию (которое будет интерпретировать «12-02-31» по-разному в зависимости от того, был ли ваш формат «гггг-ММ-дд» или «гг-ММ-дд» )
Строгое решение со стандартной библиотекой
Таким образом, полная проверка строки на дату может выглядеть так: комбинация совпадения регулярных выражений и последующего принудительного преобразования даты. Хитрость с регулярным выражением заключается в том, чтобы сделать его адаптированным к локали.
Date parseDate(String maybeDate, String format, boolean lenient) {
Date date = null;
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() ) {
SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateInstance();
sdf.applyPattern(format);
sdf.setLenient(lenient);
try { date = sdf.parse(maybeDate); } catch (ParseException e) { }
}
return date;
}
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();
Джода Тайм - лучшая альтернатива?
Я недавно слышал о joda time и подумал, что сравню . Два момента:
- Кажется, лучше быть строгим в отношении недопустимых символов в строке даты, в отличие от SimpleDateFormat
- Пока не вижу способа установить с ним 4-значные годы (но я думаю, вы могли бы создать свой собственный DateTimeFormatter для этой цели)
Использовать довольно просто:
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;
}