Подход Мэтта, описанный выше, подойдет, но учтите, что у вас возникнут проблемы, если вы будете использовать его для различения дат в формате y/M/d
и d/M/y
.Например, средство форматирования, инициализированное y/M/d
, примет дату, подобную 01/01/2009
, и вернет вам дату, которая явно не соответствует вашей.Я исправил проблему следующим образом, но у меня ограниченное время, и я не доволен решением по двум основным причинам:
- Это нарушает одну из рекомендаций Джоша Блоха, в частности, «не используйте исключения»для обработки потока программы ".
- Я вижу, что метод
getDateFormat()
становится чем-то вроде кошмара, если вам нужно было обрабатывать множество других форматов даты.
Если бы я имелчтобы создать что-то, что могло бы обрабатывать множество разных форматов даты и требовало высокой производительности, тогда я думаю, что я бы использовал подход создания перечисления, связывающего каждое другое регулярное выражение даты с его форматом.Затем используйте MyEnum.values()
для обхода перечисления и тестирования с помощью if(myEnum.getPattern().matches(date))
вместо того, чтобы перехватывать dateformatexception.
В любом случае, следующее может обрабатывать даты форматов 'y/M/d' 'y-M-d' 'y M d' 'd/M/y' 'd-M-y' 'd M y'
и всех других вариантовте, которые также включают форматы времени:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtil {
private static final String[] timeFormats = {"HH:mm:ss","HH:mm"};
private static final String[] dateSeparators = {"/","-"," "};
private static final String DMY_FORMAT = "dd{sep}MM{sep}yyyy";
private static final String YMD_FORMAT = "yyyy{sep}MM{sep}dd";
private static final String ymd_template = "\\d{4}{sep}\\d{2}{sep}\\d{2}.*";
private static final String dmy_template = "\\d{2}{sep}\\d{2}{sep}\\d{4}.*";
public static Date stringToDate(String input){
Date date = null;
String dateFormat = getDateFormat(input);
if(dateFormat == null){
throw new IllegalArgumentException("Date is not in an accepted format " + input);
}
for(String sep : dateSeparators){
String actualDateFormat = patternForSeparator(dateFormat, sep);
//try first with the time
for(String time : timeFormats){
date = tryParse(input,actualDateFormat + " " + time);
if(date != null){
return date;
}
}
//didn't work, try without the time formats
date = tryParse(input,actualDateFormat);
if(date != null){
return date;
}
}
return date;
}
private static String getDateFormat(String date){
for(String sep : dateSeparators){
String ymdPattern = patternForSeparator(ymd_template, sep);
String dmyPattern = patternForSeparator(dmy_template, sep);
if(date.matches(ymdPattern)){
return YMD_FORMAT;
}
if(date.matches(dmyPattern)){
return DMY_FORMAT;
}
}
return null;
}
private static String patternForSeparator(String template, String sep){
return template.replace("{sep}", sep);
}
private static Date tryParse(String input, String pattern){
try{
return new SimpleDateFormat(pattern).parse(input);
}
catch (ParseException e) {}
return null;
}
}