in libraries/bot-dialogs/src/main/java/com/microsoft/recognizers/text/datetime/parsers/BaseDateTimePeriodParser.java [522:733]
protected DateTimeResolutionResult parseSpecificTimeOfDay(String text, LocalDateTime referenceDate) {
DateTimeResolutionResult result = new DateTimeResolutionResult();
String trimmedText = text.trim().toLowerCase();
String timeText = trimmedText;
Optional<Match> match = Arrays.stream(RegExpUtility.getMatches(config.getPeriodTimeOfDayWithDateRegex(), trimmedText)).findFirst();
// Extract early/late prefix from text if any
boolean hasEarly = false;
boolean hasLate = false;
if (match.isPresent()) {
timeText = match.get().getGroup("timeOfDay").value;
if (!StringUtility.isNullOrEmpty(match.get().getGroup("early").value)) {
hasEarly = true;
result.setComment(Constants.Comment_Early);
result.setMod(Constants.EARLY_MOD);
}
if (!hasEarly && !StringUtility.isNullOrEmpty(match.get().getGroup("late").value)) {
hasLate = true;
result.setComment(Constants.Comment_Late);
result.setMod(Constants.LATE_MOD);
}
} else {
match = Arrays.stream(RegExpUtility.getMatches(config.getAmDescRegex(), trimmedText)).findFirst();
if (!match.isPresent()) {
match = Arrays.stream(RegExpUtility.getMatches(config.getPmDescRegex(), trimmedText)).findFirst();
}
if (match.isPresent()) {
timeText = match.get().value;
}
}
// Handle time of day
String timeStr = null;
int beginHour = -1;
int endHour = -1;
int endMin = -1;
// Late/early only works with time of day
// Only standard time of day (morinng, afternoon, evening and night) will not directly return
MatchedTimeRangeResult matchedTimeRange = config.getMatchedTimeRange(timeText, timeStr, beginHour, endHour, endMin);
timeStr = matchedTimeRange.getTimeStr();
beginHour = matchedTimeRange.getBeginHour();
endHour = matchedTimeRange.getEndHour();
endMin = matchedTimeRange.getEndMin();
if (!matchedTimeRange.getMatched()) {
return result;
}
// Modify time period if "early" or "late" exists
// Since 'time of day' is defined as four hour periods,
// the first 2 hours represent early, the later 2 hours represent late
if (hasEarly) {
endHour = beginHour + 2;
// Handling speical case: night ends with 23:59
if (endMin == 59) {
endMin = 0;
}
} else if (hasLate) {
beginHour = beginHour + 2;
}
if (RegexExtension.isExactMatch(config.getSpecificTimeOfDayRegex(), trimmedText, true)) {
int swift = config.getSwiftPrefix(trimmedText);
LocalDateTime date = referenceDate.plusDays(swift);
int day = date.getDayOfMonth();
int month = date.getMonthValue();
int year = date.getYear();
result.setTimex(DateTimeFormatUtil.formatDate(date) + timeStr);
Pair<LocalDateTime, LocalDateTime> resultValue = new Pair<LocalDateTime, LocalDateTime>(
DateUtil.safeCreateFromMinValue(year, month, day, beginHour, 0, 0),
DateUtil.safeCreateFromMinValue(year, month, day, endHour, endMin, endMin)
);
result.setFutureValue(resultValue);
result.setPastValue(resultValue);
result.setSuccess(true);
return result;
}
// Handle Date followed by morning, afternoon and morning, afternoon followed by Date
match = Arrays.stream(RegExpUtility.getMatches(config.getPeriodTimeOfDayWithDateRegex(), trimmedText)).findFirst();
if (!match.isPresent()) {
match = Arrays.stream(RegExpUtility.getMatches(config.getAmDescRegex(), trimmedText)).findFirst();
if (!match.isPresent()) {
match = Arrays.stream(RegExpUtility.getMatches(config.getPmDescRegex(), trimmedText)).findFirst();
}
}
if (match.isPresent()) {
String beforeStr = trimmedText.substring(0, match.get().index).trim();
String afterStr = trimmedText.substring(match.get().index + match.get().length).trim();
// Eliminate time period, if any
List<ExtractResult> timePeriodErs = config.getTimePeriodExtractor().extract(beforeStr);
if (timePeriodErs.size() > 0) {
beforeStr = beforeStr.substring(0, timePeriodErs.get(0).getStart()) + beforeStr.substring(timePeriodErs.get(0).getStart() + timePeriodErs.get(0).getLength())
.trim();
} else {
timePeriodErs = config.getTimePeriodExtractor().extract(afterStr);
if (timePeriodErs.size() > 0) {
afterStr = afterStr.substring(0, timePeriodErs.get(0).getStart()) + afterStr.substring(timePeriodErs.get(0).getStart() + timePeriodErs.get(0).getLength())
.trim();
}
}
List<ExtractResult> ers = config.getDateExtractor().extract(beforeStr + " " + afterStr, referenceDate);
if (ers.size() == 0 || ers.get(0).getLength() < beforeStr.length()) {
boolean valid = false;
if (ers.size() > 0 && ers.get(0).getStart() == 0) {
String midStr = beforeStr.substring(ers.get(0).getStart() + ers.get(0).getLength());
if (StringUtility.isNullOrWhiteSpace(midStr.replace(",", " "))) {
valid = true;
}
}
if (!valid) {
ers = config.getDateExtractor().extract(afterStr, referenceDate);
if (ers.size() == 0 || ers.get(0).getLength() != beforeStr.length()) {
if (ers.size() > 0 && ers.get(0).getStart() + ers.get(0).getLength() == afterStr.length()) {
String midStr = afterStr.substring(0, ers.get(0).getStart());
if (StringUtility.isNullOrWhiteSpace(midStr.replace(",", " "))) {
valid = true;
}
}
} else {
valid = true;
}
}
if (!valid) {
return result;
}
}
boolean hasSpecificTimePeriod = false;
if (timePeriodErs.size() > 0) {
DateTimeParseResult timePr = config.getTimePeriodParser().parse(timePeriodErs.get(0), referenceDate);
if (timePr != null) {
Pair<LocalDateTime, LocalDateTime> periodFuture = (Pair<LocalDateTime, LocalDateTime>)((DateTimeResolutionResult)timePr.getValue()).getFutureValue();
Pair<LocalDateTime, LocalDateTime> periodPast = (Pair<LocalDateTime, LocalDateTime>)((DateTimeResolutionResult)timePr.getValue()).getPastValue();
if (periodFuture == periodPast) {
beginHour = periodFuture.getValue0().getHour();
endHour = periodFuture.getValue1().getHour();
} else {
if (periodFuture.getValue0().getHour() >= beginHour || periodFuture.getValue1().getHour() <= endHour) {
beginHour = periodFuture.getValue0().getHour();
endHour = periodFuture.getValue1().getHour();
} else {
beginHour = periodPast.getValue0().getHour();
endHour = periodPast.getValue1().getHour();
}
}
hasSpecificTimePeriod = true;
}
}
DateTimeParseResult pr = config.getDateParser().parse(ers.get(0), referenceDate);
LocalDateTime futureDate = (LocalDateTime)((DateTimeResolutionResult)pr.getValue()).getFutureValue();
LocalDateTime pastDate = (LocalDateTime)((DateTimeResolutionResult)pr.getValue()).getPastValue();
if (!hasSpecificTimePeriod) {
result.setTimex(pr.getTimexStr() + timeStr);
} else {
result.setTimex(String.format("(%sT%d,%sT%d,PT%dH)", pr.getTimexStr(), beginHour, pr.getTimexStr(), endHour, endHour - beginHour));
}
Pair<LocalDateTime, LocalDateTime> futureResult = new Pair<LocalDateTime, LocalDateTime>(
DateUtil.safeCreateFromMinValue(
futureDate.getYear(), futureDate.getMonthValue(), futureDate.getDayOfMonth(),
beginHour, 0, 0),
DateUtil.safeCreateFromMinValue(
futureDate.getYear(), futureDate.getMonthValue(), futureDate.getDayOfMonth(),
endHour, endMin, endMin)
);
Pair<LocalDateTime, LocalDateTime> pastResult = new Pair<LocalDateTime, LocalDateTime>(
DateUtil.safeCreateFromMinValue(
pastDate.getYear(), pastDate.getMonthValue(), pastDate.getDayOfMonth(),
beginHour, 0, 0),
DateUtil.safeCreateFromMinValue(
pastDate.getYear(), pastDate.getMonthValue(), pastDate.getDayOfMonth(),
endHour, endMin, endMin)
);
result.setFutureValue(futureResult);
result.setPastValue(pastResult);
result.setSuccess(true);
return result;
}
return result;
}