public List mergeDateAndTime()

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