Java 如何检查和分析不同的日期样式
我从一个表中获取出生日期数据,Oracle列类型为Java 如何检查和分析不同的日期样式,java,date-parsing,date,Java,Date Parsing,Date,我从一个表中获取出生日期数据,Oracle列类型为varchar2,而不是date,主要原因是数据由CV解析公司解析,因为不同的CV具有不同的出生日期样式,如: 3-3-1986 11.04.1983 07/24/1969 December, 05, 1986 NOVEMBER 03, 1981 OCTOBER 06,1973 May 18th, 1984 Jan. 27th, 1967 Nov. 18, 1976 July 3,1989 27/02/1978 Place of birt
varchar2
,而不是date
,主要原因是数据由CV解析公司解析,因为不同的CV具有不同的出生日期样式,如:
3-3-1986
11.04.1983
07/24/1969
December, 05, 1986
NOVEMBER 03, 1981
OCTOBER 06,1973
May 18th, 1984
Jan. 27th, 1967
Nov. 18, 1976
July 3,1989
27/02/1978 Place of birthLisbon, Portugal
June,11,1979
以下是迄今为止我所写的方法:
public int getAge(String dob){
int age = 0;
if(dob==null || dob.equals("")){
age = 0;
}
else{
dob = dob.trim();
String[] words = dob.split ("-|/");
String day = words[0];
String month = words[1];
String year = words[2];
age = CalculateAge.AgeCalculator(day, month, year);
}
return age;
}
但在这种方法中,我只能处理斜杠和破折号。请帮我整理一下如何从上述日期样本中准确获取日期、月份和年份。你不能
以任何可能的格式解析任何字符串都是不可能的
举一个例子:1983年4月11日
那是4月11日还是11月4日?根本没有办法知道
你能做的最好的事情就是当你看到一个四位数的年份时提取年份,如果大于12,也许可以判断月份的哪一天
顺便说一句,跟踪出生日期和计算求职者的年龄似乎很奇怪。年龄通常是工作资格的一个很差的标准。在许多地方这样做是违法的 虽然可以使用正则表达式来获取值,但您仍然需要对这些值进行一些决策/验证:
11.04.1983
,当你不知道是4月11日还是11月4日:在这种情况下,你必须选择一个(或者尝试猜测)如果您使用的是Java,那么@Populus可能是我同意的副本,您链接到的问题中可以找到一些灵感,但它很难是严格的副本。如果我们再搜索一段时间,可能会发现一个……似乎暗示了许多类似的问题。请注意,尽管大多数答案使用的是早已过时的
SimpleDateFormat
,而今天我们更倾向于使用DateTimeFormatter
。不过,这些答案的想法可以应用到现代课堂上,可能是重复的,因为没有一种方法可以将所有输入解析为一个日期。您必须映射所有可能的格式,为每种格式创建一个DateTimeFormatter
,并与这些格式化程序进行循环,尝试解析为LocalDate
,如果出现解析错误,则转到下一个。您可以在中阅读如何使用格式化程序,并查看和了解与日期解析相关的类似问题。我们可以使用正则表达式找到解析的日期格式,然后将其转换为日期吗?@Ghayel(a)我不理解您评论的问题。正则表达式不是魔法;从11月4日起,Regex将无法在4月11日做出决定。(B) 您的主题已在堆栈溢出上多次提到。在发布之前一定要彻底搜索。是否有任何正则表达式可以从上述日期样式中提取年份?不需要正则表达式。只需拆分字符串并查找四位数字。对于所有其他格式,您需要各种模式的各种字符串拆分器、正则表达式或DateTimeFormatter
对象。再说一次,没有魔法。搜索堆栈溢出作为拆分字符串、使用正则表达式和使用java.tine类进行解析的主题已经被多次提到。@Ghayel正则表达式不是这个问题的最佳解决方案。如前所述,您应该为每个模式使用许多不同的DateTimeFormatter
对象。国际海事组织称,虽然使用单一正则表达式是可能的,但它太复杂(无法执行和维护),不值得付出努力。
// list of different formatters
List<DateTimeFormatter> list = new ArrayList<>();
// 3-3-1986 (assuming it's day-month-year)
list.add(DateTimeFormatter.ofPattern("d-M-yyyy"));
// 11.04.1983 (assuming it's day.month.year)
list.add(DateTimeFormatter.ofPattern("dd.MM.yyyy"));
// 07/24/1969 (month/day/year)
list.add(DateTimeFormatter.ofPattern("MM/dd/yyyy"));
// "December, 05, 1986", "NOVEMBER 03, 1981", "July 3,1989" and "June,11,1979"
// for " OCTOBER 06,1973", I'll remove the spaces before parsing
list.add(new DateTimeFormatterBuilder()
// case insensitive for month name
.parseCaseInsensitive()
// optional "," after month and optional spaces (after month and before year)
.appendPattern("MMMM[ ][','][ ]d','[ ]yyyy")
// use English locale for month name
.toFormatter(Locale.ENGLISH));
// "May 18th, 1984", "Jan. 27th, 1967" and "Nov. 18, 1976"
// append suffix for days (st, nd, rd and th)
// add suffix to days
Map<Long, String> days = new HashMap<>();
for (int i = 1; i <= 31; i++) {
String s;
switch (i) {
case 1:
case 21:
case 31:
s = "st";
break;
case 2:
case 22:
s = "nd";
break;
case 3:
case 23:
s = "rd";
break;
default:
s = "th";
}
days.put((long) i, i + s);
}
list.add(new DateTimeFormatterBuilder()
// month name with optional "."
.appendPattern("MMM[.] ")
// optional day with suffix
.optionalStart().appendText(ChronoField.DAY_OF_MONTH, days).optionalEnd()
// optional day without suffix
.optionalStart().appendValue(ChronoField.DAY_OF_MONTH, 1, 2, SignStyle.NEVER).optionalEnd()
// year
.appendPattern(", yyyy")
// use English locale for month name
.toFormatter(Locale.ENGLISH));
// 27/02/1978 Place of birthLisbon, Portugal ("Place of birth etc" will be removed manually)
list.add(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
String[] inputs = new String[] { "3-3-1986", "11.04.1983", "07/24/1969", "December, 05, 1986", "NOVEMBER 03, 1981", " OCTOBER 06,1973",
"May 18th, 1984", "Jan. 27th, 1967", "Nov. 18, 1976", "July 3,1989", "27/02/1978 Place of birthLisbon, Portugal", "June,11,1979" };
LocalDate now = LocalDate.now(); // current date
for (String s : inputs) {
LocalDate d = parse(list, s);
if (d != null) {
// get age in years
long years = ChronoUnit.YEARS.between(d, now);
}
}
// auxiliary method
public LocalDate parse(List<DateTimeFormatter> list, String s) {
// remove the unnecessary stuff
// you can customize it to remove whatever unnecessary stuff you have in the inputs
String input = s.replaceAll("Place of birth.*", "").trim();
for (DateTimeFormatter fmt : list) {
try {
return LocalDate.parse(input, fmt);
} catch (Exception e) {
// can't parse: do nothing and try the next DateTimeFormatter
}
}
// can't parse, return null
return null;
}
// assuming you've already got year, month, day from the regex
LocalDate d = LocalDate.of(year, month, day);