in libraries/bot-dialogs/src/main/java/com/microsoft/recognizers/text/datetime/extractors/BaseDateTimeExtractor.java [201:307]
public List<Token> mergeDateAndTime(String input, LocalDateTime reference) {
List<Token> ret = new ArrayList<>();
List<ExtractResult> dateErs = this.config.getDatePointExtractor().extract(input, reference);
if (dateErs.size() == 0) {
return ret;
}
List<ExtractResult> timeErs = this.config.getTimePointExtractor().extract(input, reference);
Match[] timeNumMatches = RegExpUtility.getMatches(config.getNumberAsTimeRegex(), input);
if (timeErs.size() == 0 && timeNumMatches.length == 0) {
return ret;
}
List<ExtractResult> ers = dateErs;
ers.addAll(timeErs);
// handle cases which use numbers as time points
// only enabled in CalendarMode
if (this.config.getOptions().match(DateTimeOptions.CalendarMode)) {
List<ExtractResult> numErs = new ArrayList<>();
for (Match timeNumMatch : timeNumMatches) {
ExtractResult node = new ExtractResult(timeNumMatch.index, timeNumMatch.length, timeNumMatch.value, SYS_NUM_INTEGER);
numErs.add(node);
}
ers.addAll(numErs);
}
ers.sort(Comparator.comparingInt(erA -> erA.getStart()));
int i = 0;
while (i < ers.size() - 1) {
int j = i + 1;
while (j < ers.size() && ers.get(i).isOverlap(ers.get(j))) {
j++;
}
if (j >= ers.size()) {
break;
}
ExtractResult ersI = ers.get(i);
ExtractResult ersJ = ers.get(j);
if (ersI.getType() == Constants.SYS_DATETIME_DATE && ersJ.getType() == Constants.SYS_DATETIME_TIME ||
ersI.getType() == Constants.SYS_DATETIME_TIME && ersJ.getType() == Constants.SYS_DATETIME_DATE ||
ersI.getType() == Constants.SYS_DATETIME_DATE && ersJ.getType() == SYS_NUM_INTEGER) {
int middleBegin = ersI != null ? ersI.getStart() + ersI.getLength() : 0;
int middleEnd = ersJ != null ? ersJ.getStart() : 0;
if (middleBegin > middleEnd) {
i = j + 1;
continue;
}
String middleStr = input.substring(middleBegin, middleEnd).trim().toLowerCase();
boolean valid = false;
// for cases like "tomorrow 3", "tomorrow at 3"
if (ersJ.getType() == SYS_NUM_INTEGER) {
Optional<Match> matches = Arrays.stream(RegExpUtility.getMatches(this.config.getDateNumberConnectorRegex(), input)).findFirst();
if (StringUtility.isNullOrEmpty(middleStr) || matches.isPresent()) {
valid = true;
}
} else {
// For case like "3pm or later on monday"
Optional<Match> match = Arrays.stream(RegExpUtility.getMatches(this.config.getSuffixAfterRegex(), middleStr)).findFirst();
if (match.isPresent()) {
middleStr = middleStr.substring(match.get().index + match.get().length).trim();
}
if (!(match.isPresent() && middleStr.isEmpty())) {
if (this.config.isConnector(middleStr)) {
valid = true;
}
}
}
if (valid) {
int begin = ersI.getStart();
int end = ersJ.getStart() + ersJ.getLength();
ret.add(new Token(begin, end));
i = j + 1;
continue;
}
}
i = j;
}
// Handle "in the afternoon" at the end of entity
for (int idx = 0; idx < ret.size(); idx++) {
Token idxToken = ret.get(idx);
String afterStr = input.substring(idxToken.getEnd());
Optional<Match> match = Arrays.stream(RegExpUtility.getMatches(this.config.getSuffixRegex(), afterStr)).findFirst();
if (match.isPresent()) {
ret.set(idx, new Token(idxToken.getStart(), idxToken.getEnd() + match.get().length));
}
}
// Handle "day" prefixes
for (int idx = 0; idx < ret.size(); idx++) {
Token idxToken = ret.get(idx);
String beforeStr = input.substring(0, idxToken.getStart());
Optional<Match> match = Arrays.stream(RegExpUtility.getMatches(this.config.getUtilityConfiguration().getCommonDatePrefixRegex(), beforeStr)).findFirst();
if (match.isPresent()) {
ret.set(idx, new Token(idxToken.getStart() - match.get().length, idxToken.getEnd()));
}
}
return ret;
}