// Check every integers and ordinal number for date
        private List <Token> NumberWithMonth(string text, DateObject reference)
        {
            var ret = new List <Token>();

            var er = this.Config.OrdinalExtractor.Extract(text);

            er.AddRange(this.Config.IntegerExtractor.Extract(text));

            foreach (var result in er)
            {
                var parsed = int.TryParse((this.Config.NumberParser.Parse(result).Value ?? 0).ToString(), out int num);

                if (!parsed || (num < 1 || num > 31))
                {
                    continue;
                }

                if (result.Start >= 0)
                {
                    // Handling cases like '(Monday,) Jan twenty two'
                    var prefixStr = text.Substring(0, result.Start ?? 0);

                    // Check that the extracted number is not part of a decimal number, time expression or currency
                    // (e.g. '123.24', '12:24', '$12')
                    if (MatchingUtil.IsInvalidDayNumberPrefix(prefixStr))
                    {
                        continue;
                    }

                    var match = this.Config.MonthEnd.Match(prefixStr);
                    if (match.Success)
                    {
                        var startIndex = match.Index;
                        var endIndex   = match.Index + match.Length + (result.Length ?? 0);

                        ExtendWithWeekdayAndYear(
                            ref startIndex, ref endIndex, Config.MonthOfYear.GetValueOrDefault(match.Groups["month"].Value, reference.Month),
                            num, text, reference);

                        ret.Add(new Token(startIndex, endIndex));
                        continue;
                    }

                    // Handling cases like 'for the 25th'
                    var  matches = this.Config.ForTheRegex.Matches(text);
                    bool isFound = false;
                    foreach (Match matchCase in matches)
                    {
                        if (matchCase.Success)
                        {
                            var ordinalNum = matchCase.Groups["DayOfMonth"].Value;
                            if (ordinalNum == result.Text)
                            {
                                var endLength = 0;
                                if (matchCase.Groups["end"].Value.Length > 0)
                                {
                                    endLength = matchCase.Groups["end"].Value.Length;
                                }

                                ret.Add(new Token(matchCase.Index, matchCase.Index + matchCase.Length - endLength));
                                isFound = true;
                            }
                        }
                    }

                    if (isFound)
                    {
                        continue;
                    }

                    // Handling cases like 'Thursday the 21st', which both 'Thursday' and '21st' refer to a same date
                    matches = this.Config.WeekDayAndDayOfMonthRegex.Matches(text);

                    foreach (Match matchCase in matches)
                    {
                        if (matchCase.Success)
                        {
                            var ordinalNum = matchCase.Groups["DayOfMonth"].Value;
                            if (ordinalNum == result.Text && matchCase.Groups["DayOfMonth"].Index == result.Start)
                            {
                                // Get week of day for the ordinal number which is regarded as a date of reference month
                                var date          = DateObject.MinValue.SafeCreateFromValue(reference.Year, reference.Month, num);
                                var numWeekDayInt = (int)date.DayOfWeek;

                                // Get week day from text directly, compare it with the weekday generated above
                                // to see whether they refer to the same week day
                                var extractedWeekDayStr = matchCase.Groups["weekday"].Value;

                                if (!date.Equals(DateObject.MinValue) &&
                                    numWeekDayInt == Config.DayOfWeek[extractedWeekDayStr])
                                {
                                    ret.Add(new Token(matchCase.Index, matchCase.Index + matchCase.Length));

                                    isFound = true;
                                }
                            }
                        }
                    }

                    if (isFound)
                    {
                        continue;
                    }

                    // Handling cases like 'Monday 21', which both 'Monday' and '21' refer to the same date
                    // The year of expected date can be different to the year of referenceDate.
                    matches = this.Config.WeekDayAndDayRegex.Matches(text);
                    foreach (Match matchCase in matches)
                    {
                        if (matchCase.Success)
                        {
                            var matchLength = result.Start + result.Length - matchCase.Index;

                            if (matchLength == matchCase.Length)
                            {
                                // check if day number is compatible with reference month
                                if (DateObjectExtension.IsValidDate(reference.Year, reference.Month, num) || !this.Config.CheckBothBeforeAfter)
                                {
                                    ret.Add(new Token(matchCase.Index, result.Start + result.Length ?? 0));
                                    isFound = true;
                                }
                            }
                        }
                    }

                    if (isFound)
                    {
                        continue;
                    }

                    // Handling cases like '20th of next month'
                    var suffixStr  = text.Substring(result.Start + result.Length ?? 0);
                    var beginMatch = this.Config.RelativeMonthRegex.MatchBegin(suffixStr.Trim(), trim: true);

                    if (beginMatch.Success && beginMatch.Index == 0)
                    {
                        var spaceLen = suffixStr.Length - suffixStr.Trim().Length;
                        var resStart = result.Start;
                        var resEnd   = resStart + result.Length + spaceLen + beginMatch.Length;

                        // Check if prefix contains 'the', include it if any
                        var prefix      = text.Substring(0, resStart ?? 0);
                        var prefixMatch = this.Config.PrefixArticleRegex.Match(prefix);

                        if (prefixMatch.Success)
                        {
                            resStart = prefixMatch.Index;
                        }

                        ret.Add(new Token(resStart ?? 0, resEnd ?? 0));
                    }

                    // Handling cases like 'second Sunday'
                    suffixStr = text.Substring(result.Start + result.Length ?? 0);

                    beginMatch = this.Config.WeekDayRegex.MatchBegin(suffixStr.Trim(), trim: true);

                    if (beginMatch.Success && num >= 1 && num <= 5 &&
                        result.Type.Equals(Number.Constants.SYS_NUM_ORDINAL, StringComparison.Ordinal) &&
                        !this.Config.WeekDayRegex.IsExactMatch(result.Text, trim: true))
                    {
                        var weekDayStr = beginMatch.Groups["weekday"].Value;
                        if (this.Config.DayOfWeek.ContainsKey(weekDayStr))
                        {
                            var spaceLen = suffixStr.Length - suffixStr.Trim().Length;
                            ret.Add(new Token(result.Start ?? 0, result.Start + result.Length + spaceLen + beginMatch.Length ?? 0));
                        }
                    }
                }

                // For cases like "I'll go back twenty second of June"
                if (result.Start + result.Length < text.Length)
                {
                    var afterStr = text.Substring(result.Start + result.Length ?? 0);

                    var match = this.Config.OfMonth.Match(afterStr);
                    if (match.Success)
                    {
                        var startIndex = result.Start ?? 0;
                        var endIndex   = (result.Start + result.Length ?? 0) + match.Length;

                        ExtendWithWeekdayAndYear(ref startIndex, ref endIndex,
                                                 Config.MonthOfYear.GetValueOrDefault(match.Groups["month"].Value, reference.Month),
                                                 num, text, reference);

                        ret.Add(new Token(startIndex, endIndex));
                    }
                }
            }

            return(ret);
        }