private DateTimeResolutionResult parseSpecificTimeCases()

in Java/libraries/recognizers-text-date-time/src/main/java/com/microsoft/recognizers/text/datetime/parsers/BaseTimePeriodParser.java [273:519]


    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;
    }