in libraries/bot-dialogs/src/main/java/com/microsoft/recognizers/text/datetime/parsers/BaseTimePeriodParser.java [270:516]
private DateTimeResolutionResult parseSpecificTimeCases(String text, LocalDateTime referenceTime) {
DateTimeResolutionResult ret = new DateTimeResolutionResult();
int year = referenceTime.getYear();
int month = referenceTime.getMonthValue();
int day = referenceTime.getDayOfMonth();
// Handle cases like "from 4:30 to 5"
ConditionalMatch match = RegexExtension.matchExact(config.getSpecificTimeFromToRegex(), text, true);
if (!match.getSuccess()) {
// Handle cases like "between 5:10 and 7"
match = RegexExtension.matchExact(config.getSpecificTimeBetweenAndRegex(), text, true);
}
if (match.getSuccess()) {
// Cases like "half past seven" are not handled here
if (!match.getMatch().get().getGroup(Constants.PrefixGroupName).value.equals("")) {
return ret;
}
// Cases like "4" is different with "4:00" as the Timex is different "T04H" vs "T04H00M"
// Uses this invalidFlag to differentiate
int beginHour;
int beginMinute = Constants.InvalidMinute;
int beginSecond = Constants.InvalidSecond;
int endHour;
int endMinute = Constants.InvalidMinute;
int endSecond = Constants.InvalidSecond;
// Get time1 and time2
MatchGroup hourGroup = match.getMatch().get().getGroup(Constants.HourGroupName);
String hourStr = hourGroup.captures[0].value;
if (config.getNumbers().containsKey(hourStr)) {
beginHour = config.getNumbers().get(hourStr);
} else {
beginHour = Integer.parseInt(hourStr);
}
hourStr = hourGroup.captures[1].value;
if (config.getNumbers().containsKey(hourStr)) {
endHour = config.getNumbers().get(hourStr);
} else {
endHour = Integer.parseInt(hourStr);
}
int time1StartIndex = match.getMatch().get().getGroup("time1").index;
int time1EndIndex = time1StartIndex + match.getMatch().get().getGroup("time1").length;
int time2StartIndex = match.getMatch().get().getGroup("time2").index;
int time2EndIndex = time2StartIndex + match.getMatch().get().getGroup("time2").length;
// Get beginMinute (if exists) and endMinute (if exists)
for (int i = 0; i < match.getMatch().get().getGroup(Constants.MinuteGroupName).captures.length; i++) {
Capture minuteCapture = match.getMatch().get().getGroup(Constants.MinuteGroupName).captures[i];
if (minuteCapture.index >= time1StartIndex && (minuteCapture.index + minuteCapture.length) <= time1EndIndex) {
beginMinute = Integer.parseInt(minuteCapture.value);
} else if (minuteCapture.index >= time2StartIndex && (minuteCapture.index + minuteCapture.length) <= time2EndIndex) {
endMinute = Integer.parseInt(minuteCapture.value);
}
}
// Get beginSecond (if exists) and endSecond (if exists)
for (int i = 0; i < match.getMatch().get().getGroup(Constants.SecondGroupName).captures.length; i++) {
Capture secondCapture = match.getMatch().get().getGroup(Constants.SecondGroupName).captures[i];
if (secondCapture.index >= time1StartIndex && (secondCapture.index + secondCapture.length) <= time1EndIndex) {
beginSecond = Integer.parseInt(secondCapture.value);
} else if (secondCapture.index >= time2StartIndex && (secondCapture.index + secondCapture.length) <= time2EndIndex) {
endSecond = Integer.parseInt(secondCapture.value);
}
}
// Desc here means descriptions like "am / pm / o'clock"
// Get leftDesc (if exists) and rightDesc (if exists)
String leftDesc = match.getMatch().get().getGroup("leftDesc").value;
String rightDesc = match.getMatch().get().getGroup("rightDesc").value;
for (int i = 0; i < match.getMatch().get().getGroup(Constants.DescGroupName).captures.length; i++) {
Capture descCapture = match.getMatch().get().getGroup(Constants.DescGroupName).captures[i];
if (descCapture.index >= time1StartIndex && (descCapture.index + descCapture.length) <= time1EndIndex && StringUtility.isNullOrEmpty(leftDesc)) {
leftDesc = descCapture.value;
} else if (descCapture.index >= time2StartIndex && (descCapture.index + descCapture.length) <= time2EndIndex && StringUtility.isNullOrEmpty(rightDesc)) {
rightDesc = descCapture.value;
}
}
LocalDateTime beginDateTime = DateUtil.safeCreateFromMinValue(
year,
month,
day,
beginHour,
beginMinute >= 0 ? beginMinute : 0,
beginSecond >= 0 ? beginSecond : 0);
LocalDateTime endDateTime = DateUtil.safeCreateFromMinValue(
year,
month,
day,
endHour,
endMinute >= 0 ? endMinute : 0,
endSecond >= 0 ? endSecond : 0);
boolean hasLeftAm = !StringUtility.isNullOrEmpty(leftDesc) && leftDesc.toLowerCase().startsWith("a");
boolean hasLeftPm = !StringUtility.isNullOrEmpty(leftDesc) && leftDesc.toLowerCase().startsWith("p");
boolean hasRightAm = !StringUtility.isNullOrEmpty(rightDesc) && rightDesc.toLowerCase().startsWith("a");
boolean hasRightPm = !StringUtility.isNullOrEmpty(rightDesc) && rightDesc.toLowerCase().startsWith("p");
boolean hasLeft = hasLeftAm || hasLeftPm;
boolean hasRight = hasRightAm || hasRightPm;
// Both timepoint has description like 'am' or 'pm'
if (hasLeft && hasRight) {
if (hasLeftAm) {
if (beginHour >= Constants.HalfDayHourCount) {
beginDateTime = beginDateTime.minusHours(Constants.HalfDayHourCount);
}
} else if (hasLeftPm) {
if (beginHour < Constants.HalfDayHourCount) {
beginDateTime = beginDateTime.plusHours(Constants.HalfDayHourCount);
}
}
if (hasRightAm) {
if (endHour > Constants.HalfDayHourCount) {
endDateTime = endDateTime.minusHours(Constants.HalfDayHourCount);
}
} else if (hasRightPm) {
if (endHour < Constants.HalfDayHourCount) {
endDateTime = endDateTime.plusHours(Constants.HalfDayHourCount);
}
}
} else if (hasLeft || hasRight) { // one of the timepoint has description like 'am' or 'pm'
if (hasLeftAm) {
if (beginHour >= Constants.HalfDayHourCount) {
beginDateTime = beginDateTime.minusHours(Constants.HalfDayHourCount);
}
if (endHour < Constants.HalfDayHourCount) {
if (endDateTime.isBefore(beginDateTime)) {
endDateTime = endDateTime.plusHours(Constants.HalfDayHourCount);
}
}
} else if (hasLeftPm) {
if (beginHour < Constants.HalfDayHourCount) {
beginDateTime = beginDateTime.plusHours(Constants.HalfDayHourCount);
}
if (endHour < Constants.HalfDayHourCount) {
if (endDateTime.isBefore(beginDateTime)) {
Duration span = Duration.between(endDateTime, beginDateTime).abs();
if (span.toHours() >= Constants.HalfDayHourCount) {
endDateTime = endDateTime.plusHours(24);
} else {
endDateTime = endDateTime.plusHours(Constants.HalfDayHourCount);
}
}
}
}
if (hasRightAm) {
if (endHour >= Constants.HalfDayHourCount) {
endDateTime = endDateTime.minusHours(Constants.HalfDayHourCount);
}
if (beginHour < Constants.HalfDayHourCount) {
if (endDateTime.isBefore(beginDateTime)) {
beginDateTime = beginDateTime.minusHours(Constants.HalfDayHourCount);
}
}
} else if (hasRightPm) {
if (endHour < Constants.HalfDayHourCount) {
endDateTime = endDateTime.plusHours(Constants.HalfDayHourCount);
}
if (beginHour < Constants.HalfDayHourCount) {
if (endDateTime.isBefore(beginDateTime)) {
beginDateTime = beginDateTime.minusHours(Constants.HalfDayHourCount);
} else {
Duration span = Duration.between(beginDateTime, endDateTime);
if (span.toHours() > Constants.HalfDayHourCount) {
beginDateTime = beginDateTime.plusHours(Constants.HalfDayHourCount);
}
}
}
}
} else if (beginHour <= Constants.HalfDayHourCount && endHour <= Constants.HalfDayHourCount) {
// No 'am' or 'pm' indicator
if (beginHour > endHour) {
if (beginHour == Constants.HalfDayHourCount) {
beginDateTime = beginDateTime.minusHours(Constants.HalfDayHourCount);
} else {
endDateTime = endDateTime.plusHours(Constants.HalfDayHourCount);
}
}
ret.setComment(Constants.Comment_AmPm);
}
if (endDateTime.isBefore(beginDateTime)) {
endDateTime = endDateTime.plusHours(24);
}
String beginStr = DateTimeFormatUtil.shortTime(beginDateTime.getHour(), beginMinute, beginSecond);
String endStr = DateTimeFormatUtil.shortTime(endDateTime.getHour(), endMinute, endSecond);
ret.setSuccess(true);
ret.setTimex(String.format("(%s,%s,%s)", beginStr, endStr, DateTimeFormatUtil.luisTimeSpan(Duration.between(beginDateTime, endDateTime))));
ret.setFutureValue(new Pair<LocalDateTime, LocalDateTime>(beginDateTime, endDateTime));
ret.setPastValue(new Pair<LocalDateTime, LocalDateTime>(beginDateTime, endDateTime));
List<Object> subDateTimeEntities = new ArrayList<>();
// In SplitDateAndTime mode, time points will be get from these SubDateTimeEntities
// Cases like "from 4 to 5pm", "4" should not be treated as SubDateTimeEntity
if (hasLeft || beginMinute != Constants.InvalidMinute || beginSecond != Constants.InvalidSecond) {
ExtractResult er = new ExtractResult(
time1StartIndex,
time1EndIndex - time1StartIndex,
text.substring(time1StartIndex, time1EndIndex),
Constants.SYS_DATETIME_TIME);
DateTimeParseResult pr = this.config.getTimeParser().parse(er, referenceTime);
subDateTimeEntities.add(pr);
}
// Cases like "from 4am to 5", "5" should not be treated as SubDateTimeEntity
if (hasRight || endMinute != Constants.InvalidMinute || endSecond != Constants.InvalidSecond) {
ExtractResult er = new ExtractResult(
time2StartIndex,
time2EndIndex - time2StartIndex,
text.substring(time2StartIndex, time2EndIndex),
Constants.SYS_DATETIME_TIME
);
DateTimeParseResult pr = this.config.getTimeParser().parse(er, referenceTime);
subDateTimeEntities.add(pr);
}
ret.setSubDateTimeEntities(subDateTimeEntities);
ret.setSuccess(true);
}
return ret;
}