コード例 #1
0
        private DateTimeResolutionResult ParseMergedDuration(string text, DateObject referenceTime)
        {
            var ret = new DateTimeResolutionResult();
            var durationExtractor = DurationExtractor;

            // DurationExtractor without parameter will not extract merged duration
            var ers = durationExtractor.Extract(text, referenceTime);

            // only handle merged duration cases like "1 month 21 days"
            if (ers.Count <= 1)
            {
                ret.Success = false;
                return(ret);
            }

            var start = ers[0].Start ?? 0;

            if (start != 0)
            {
                var beforeStr = text.Substring(0, start - 1);
                if (!string.IsNullOrWhiteSpace(beforeStr))
                {
                    return(ret);
                }
            }

            var end = ers[ers.Count - 1].Start + ers[ers.Count - 1].Length ?? 0;

            if (end != text.Length)
            {
                var afterStr = text.Substring(end);
                if (!string.IsNullOrWhiteSpace(afterStr))
                {
                    return(ret);
                }
            }

            var prs       = new List <DateTimeParseResult>();
            var timexDict = new Dictionary <string, string>();

            // insert timex into a dictionary
            foreach (var er in ers)
            {
                var unitRegex = DurationUnitRegex;
                var unitMatch = unitRegex.Match(er.Text);
                if (unitMatch.Success)
                {
                    var pr = (DateTimeParseResult)Parse(er);
                    if (pr.Value != null)
                    {
                        timexDict.Add(UnitMap[unitMatch.Groups["unit"].Value], pr.TimexStr);
                        prs.Add(pr);
                    }
                }
            }

            // sort the timex using the granularity of the duration, "P1M23D" for "1 month 23 days" and "23 days 1 month"
            if (prs.Count == ers.Count)
            {
                ret.Timex = TimexUtility.GenerateCompoundDurationTimex(timexDict, UnitValueMap);

                double value = 0;
                foreach (var pr in prs)
                {
                    value += double.Parse(((DateTimeResolutionResult)pr.Value).FutureValue.ToString(), CultureInfo.InvariantCulture);
                }

                ret.FutureValue = ret.PastValue = value;
            }

            ret.Success = true;
            return(ret);
        }
コード例 #2
0
ファイル: DateParser.cs プロジェクト: warnov/Recognizers-Text
        // match several other cases
        // including '今天', '后天', '十三日'
        protected DateTimeResolutionResult ParseImplicitDate(string text, DateObject referenceDate)
        {
            var trimedText = text.Trim();

            var ret = new DateTimeResolutionResult();

            // handle "十二日" "明年这个月三日" "本月十一日"
            var match = DateExtractorChs.SpecialDate.Match(trimedText);

            if (match.Success && match.Length == trimedText.Length)
            {
                var yearStr  = match.Groups["thisyear"].Value.ToLower();
                var monthStr = match.Groups["thismonth"].Value.ToLower();
                var dayStr   = match.Groups["day"].Value.ToLower();

                int month = referenceDate.Month, year = referenceDate.Year;
                var day = this.config.DayOfMonth[dayStr];

                bool hasYear = false, hasMonth = false;

                if (!string.IsNullOrEmpty(monthStr))
                {
                    hasMonth = true;
                    if (DateExtractorChs.NextRe.Match(monthStr).Success)
                    {
                        month++;
                        if (month == 13)
                        {
                            month = 1;
                            year++;
                        }
                    }
                    else if (DateExtractorChs.LastRe.Match(monthStr).Success)
                    {
                        month--;
                        if (month == 0)
                        {
                            month = 12;
                            year--;
                        }
                    }

                    if (!string.IsNullOrEmpty(yearStr))
                    {
                        hasYear = true;
                        if (DateExtractorChs.NextRe.Match(yearStr).Success)
                        {
                            ++year;
                        }
                        else if (DateExtractorChs.LastRe.Match(yearStr).Success)
                        {
                            --year;
                        }
                    }
                }

                ret.Timex = FormatUtil.LuisDate(hasYear ? year : -1, hasMonth ? month : -1, day);

                DateObject futureDate, pastDate;

                if (day > MonthMaxDays[month - 1])
                {
                    futureDate = DateObject.MinValue.SafeCreateFromValue(year, month + 1, day);
                    pastDate   = DateObject.MinValue.SafeCreateFromValue(year, month - 1, day);
                }
                else
                {
                    futureDate = DateObject.MinValue.SafeCreateFromValue(year, month, day);
                    pastDate   = DateObject.MinValue.SafeCreateFromValue(year, month, day);
                    if (!hasMonth)
                    {
                        if (futureDate < referenceDate)
                        {
                            futureDate = futureDate.AddMonths(1);
                        }

                        if (pastDate >= referenceDate)
                        {
                            pastDate = pastDate.AddMonths(-1);
                        }
                    }
                    else if (!hasYear)
                    {
                        if (futureDate < referenceDate)
                        {
                            futureDate = futureDate.AddYears(1);
                        }

                        if (pastDate >= referenceDate)
                        {
                            pastDate = pastDate.AddYears(-1);
                        }
                    }
                }

                ret.FutureValue = futureDate;
                ret.PastValue   = pastDate;
                ret.Success     = true;

                return(ret);
            }

            // handle cases like "昨日", "明日", "大后天"
            match = DateExtractorChs.SpecialDayRegex.Match(trimedText);
            if (match.Success && match.Index == 0 && match.Length == trimedText.Length)
            {
                var value = referenceDate.AddDays(config.GetSwiftDay(match.Value.ToLower()));
                ret.Timex       = FormatUtil.LuisDate(value);
                ret.FutureValue = ret.PastValue = value;
                ret.Success     = true;

                return(ret);
            }

            if (!ret.Success)
            {
                ret = MatchThisWeekday(text, referenceDate);
            }

            if (!ret.Success)
            {
                ret = MatchNextWeekday(text, referenceDate);
            }

            if (!ret.Success)
            {
                ret = MatchLastWeekday(text, referenceDate);
            }

            if (!ret.Success)
            {
                ret = MatchWeekdayAlone(text, referenceDate);
            }

            return(ret);
        }
コード例 #3
0
ファイル: DateParser.cs プロジェクト: warnov/Recognizers-Text
        // handle cases like "三天前"
        private DateTimeResolutionResult ParserDurationWithBeforeAndAfter(string text, DateObject referenceDate)
        {
            var ret         = new DateTimeResolutionResult();
            var durationRes = durationExtractor.Extract(text, referenceDate);
            var numStr      = string.Empty;
            var unitStr     = string.Empty;

            if (durationRes.Count > 0)
            {
                var match = DateExtractorChs.UnitRegex.Match(text);
                if (match.Success)
                {
                    var afterStr =
                        text.Substring((int)durationRes[0].Start + (int)durationRes[0].Length, 1)
                        .Trim()
                        .ToLowerInvariant();
                    var srcUnit   = match.Groups["unit"].Value.ToLowerInvariant();
                    var numberStr =
                        text.Substring((int)durationRes[0].Start, match.Index - (int)durationRes[0].Start)
                        .Trim()
                        .ToLowerInvariant();
                    var number = ConvertChineseToNum(numberStr);
                    if (this.config.UnitMap.ContainsKey(srcUnit))
                    {
                        unitStr = this.config.UnitMap[srcUnit];
                        numStr  = number.ToString();
                        if (afterStr.Equals("前"))
                        {
                            DateObject date;
                            switch (unitStr)
                            {
                            case "D":
                                date = referenceDate.AddDays(-double.Parse(numStr));
                                break;

                            case "W":
                                date = referenceDate.AddDays(-7 * double.Parse(numStr));
                                break;

                            case "MON":
                                date = referenceDate.AddMonths(-Convert.ToInt32(double.Parse(numStr)));
                                break;

                            case "Y":
                                date = referenceDate.AddYears(-Convert.ToInt32(double.Parse(numStr)));
                                break;

                            default:
                                return(ret);
                            }
                            ret.Timex       = $"{FormatUtil.LuisDate(date)}";
                            ret.FutureValue = ret.PastValue = date;
                            ret.Success     = true;
                            return(ret);
                        }

                        if (afterStr.Equals("后"))
                        {
                            DateObject date;
                            switch (unitStr)
                            {
                            case "D":
                                date = referenceDate.AddDays(double.Parse(numStr));
                                break;

                            case "W":
                                date = referenceDate.AddDays(7 * double.Parse(numStr));
                                break;

                            case "MON":
                                date = referenceDate.AddMonths(Convert.ToInt32(double.Parse(numStr)));
                                break;

                            case "Y":
                                date = referenceDate.AddYears(Convert.ToInt32(double.Parse(numStr)));
                                break;

                            default:
                                return(ret);
                            }

                            ret.Timex       = $"{FormatUtil.LuisDate(date)}";
                            ret.FutureValue = ret.PastValue = date;
                            ret.Success     = true;
                            return(ret);
                        }
                    }
                }
            }

            return(ret);
        }
コード例 #4
0
        private DateTimeResolutionResult MergeTwoTimePoints(string text, DateObject referenceTime)
        {
            var ret = new DateTimeResolutionResult();
            DateTimeParseResult pr1 = null, pr2 = null;
            bool bothHaveDates = false, beginHasDate = false, endHasDate = false;

            var er1 = SingleTimeExtractor.Extract(text, referenceTime);
            var er2 = TimeWithDateExtractor.Extract(text, referenceTime);

            var rightTime = DateObject.MinValue.SafeCreateFromValue(referenceTime.Year, referenceTime.Month, referenceTime.Day);
            var leftTime  = DateObject.MinValue.SafeCreateFromValue(referenceTime.Year, referenceTime.Month, referenceTime.Day);

            if (er2.Count == 2)
            {
                pr1           = this.config.DateTimeParser.Parse(er2[0], referenceTime);
                pr2           = this.config.DateTimeParser.Parse(er2[1], referenceTime);
                bothHaveDates = true;
            }
            else if (er2.Count == 1 && er1.Count == 2)
            {
                if (!er2[0].IsOverlap(er1[0]))
                {
                    pr1        = this.config.TimeParser.Parse(er1[0], referenceTime);
                    pr2        = this.config.DateTimeParser.Parse(er2[0], referenceTime);
                    endHasDate = true;
                }
                else
                {
                    pr1          = this.config.DateTimeParser.Parse(er2[0], referenceTime);
                    pr2          = this.config.TimeParser.Parse(er1[1], referenceTime);
                    beginHasDate = true;
                }
            }
            else if (er2.Count == 1 && er1.Count == 1)
            {
                if (er1[0].Start < er2[0].Start)
                {
                    pr1        = this.config.TimeParser.Parse(er1[0], referenceTime);
                    pr2        = this.config.DateTimeParser.Parse(er2[0], referenceTime);
                    endHasDate = true;
                }
                else
                {
                    pr1          = this.config.DateTimeParser.Parse(er2[0], referenceTime);
                    pr2          = this.config.TimeParser.Parse(er1[0], referenceTime);
                    beginHasDate = true;
                }
            }
            else if (er1.Count == 2)
            {
                // if both ends are Time. then this is a TimePeriod, not a DateTimePeriod
                return(ret);
            }
            else
            {
                return(ret);
            }

            if (pr1.Value == null || pr2.Value == null)
            {
                return(ret);
            }

            DateObject futureBegin = (DateObject)((DateTimeResolutionResult)pr1.Value).FutureValue,
                       futureEnd   = (DateObject)((DateTimeResolutionResult)pr2.Value).FutureValue;

            DateObject pastBegin = (DateObject)((DateTimeResolutionResult)pr1.Value).PastValue,
                       pastEnd   = (DateObject)((DateTimeResolutionResult)pr2.Value).PastValue;

            if (futureBegin > futureEnd)
            {
                futureBegin = pastBegin;
            }

            if (pastEnd < pastBegin)
            {
                pastEnd = futureEnd;
            }

            if (bothHaveDates)
            {
                rightTime = DateObject.MinValue.SafeCreateFromValue(futureEnd.Year, futureEnd.Month, futureEnd.Day);
                leftTime  = DateObject.MinValue.SafeCreateFromValue(futureBegin.Year, futureBegin.Month, futureBegin.Day);
            }
            else if (beginHasDate)
            {
                // TODO: Handle "明天下午两点到五点"
                futureEnd = DateObject.MinValue.SafeCreateFromValue(futureBegin.Year, futureBegin.Month, futureBegin.Day,
                                                                    futureEnd.Hour, futureEnd.Minute, futureEnd.Second);
                pastEnd = DateObject.MinValue.SafeCreateFromValue(pastBegin.Year, pastBegin.Month, pastBegin.Day,
                                                                  pastEnd.Hour, pastEnd.Minute, pastEnd.Second);

                leftTime = DateObject.MinValue.SafeCreateFromValue(futureBegin.Year, futureBegin.Month, futureBegin.Day);
            }
            else if (endHasDate)
            {
                // TODO: Handle "明天下午两点到五点"
                futureBegin = DateObject.MinValue.SafeCreateFromValue(futureEnd.Year, futureEnd.Month, futureEnd.Day,
                                                                      futureBegin.Hour, futureBegin.Minute, futureBegin.Second);
                pastBegin = DateObject.MinValue.SafeCreateFromValue(pastEnd.Year, pastEnd.Month, pastEnd.Day,
                                                                    pastBegin.Hour, pastBegin.Minute, pastBegin.Second);

                rightTime = DateObject.MinValue.SafeCreateFromValue(futureEnd.Year, futureEnd.Month, futureEnd.Day);
            }

            var leftResult      = (DateTimeResolutionResult)pr1.Value;
            var rightResult     = (DateTimeResolutionResult)pr2.Value;
            var leftResultTime  = (DateObject)leftResult.FutureValue;
            var rightResultTime = (DateObject)rightResult.FutureValue;

            int day   = referenceTime.Day,
                month = referenceTime.Month,
                year  = referenceTime.Year;

            //check if the right time is smaller than the left time, if yes, add one day
            int hour   = leftResultTime.Hour > 0 ? leftResultTime.Hour : 0,
                min    = leftResultTime.Minute > 0 ? leftResultTime.Minute : 0,
                second = leftResultTime.Second > 0 ? leftResultTime.Second : 0;

            leftTime = leftTime.AddHours(hour);
            leftTime = leftTime.AddMinutes(min);
            leftTime = leftTime.AddSeconds(second);
            DateObject.MinValue.SafeCreateFromValue(year, month, day, hour, min, second);

            hour   = rightResultTime.Hour > 0 ? rightResultTime.Hour : 0;
            min    = rightResultTime.Minute > 0 ? rightResultTime.Minute : 0;
            second = rightResultTime.Second > 0 ? rightResultTime.Second : 0;

            rightTime = rightTime.AddHours(hour);
            rightTime = rightTime.AddMinutes(min);
            rightTime = rightTime.AddSeconds(second);

            //the right side time contains "ampm", while the left side doesn't
            if (rightResult.Comment != null && rightResult.Comment.Equals(Constants.Comment_AmPm) &&
                leftResult.Comment == null && rightTime < leftTime)
            {
                rightTime = rightTime.AddHours(Constants.HalfDayHourCount);
            }

            if (rightTime < leftTime)
            {
                rightTime = rightTime.AddDays(1);
            }

            ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(leftTime, rightTime);

            var leftTimex  = "";
            var rightTimex = "";

            //"X" is timex token for not determined time
            if (!pr1.TimexStr.Contains("X") && !pr2.TimexStr.Contains("X"))
            {
                leftTimex  = DateTimeFormatUtil.LuisDateTime(leftTime);
                rightTimex = DateTimeFormatUtil.LuisDateTime(rightTime);
            }
            else
            {
                leftTimex  = pr1.TimexStr;
                rightTimex = pr2.TimexStr;
            }

            ret.Timex = $"({leftTimex},{rightTimex},PT{Convert.ToInt32((rightTime - leftTime).TotalHours)}H)";

            ret.Success = true;
            return(ret);
        }
コード例 #5
0
        // parse "in 20 minutes"
        private DateTimeResolutionResult ParseNumberWithUnit(string text, DateObject referenceTime)
        {
            var    ret = new DateTimeResolutionResult();
            string numStr, unitStr;

            // if there are spaces between nubmer and unit
            var ers = CardinalExtractor.Extract(text);

            if (ers.Count == 1)
            {
                var pr      = CardinalParser.Parse(ers[0]);
                var srcUnit = text.Substring(ers[0].Start + ers[0].Length ?? 0).Trim().ToLower();
                if (srcUnit.StartsWith("个"))
                {
                    srcUnit = srcUnit.Substring(1);
                }

                var beforeStr = text.Substring(0, ers[0].Start ?? 0).ToLowerInvariant();
                if (this.config.UnitMap.ContainsKey(srcUnit))
                {
                    numStr  = pr.ResolutionStr;
                    unitStr = this.config.UnitMap[srcUnit];

                    if (DateTimePeriodExtractor.PastRegex.IsExactMatch(beforeStr, trim: true))
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "H":
                            beginDate = referenceTime.AddHours(-(double)pr.Value);
                            endDate   = referenceTime;
                            break;

                        case "M":
                            beginDate = referenceTime.AddMinutes(-(double)pr.Value);
                            endDate   = referenceTime;
                            break;

                        case "S":
                            beginDate = referenceTime.AddSeconds(-(double)pr.Value);
                            endDate   = referenceTime;
                            break;

                        default:
                            return(ret);
                        }

                        ret.Timex =
                            $"({DateTimeFormatUtil.LuisDate(beginDate)}T{DateTimeFormatUtil.LuisTime(beginDate)},{DateTimeFormatUtil.LuisDate(endDate)}T{DateTimeFormatUtil.LuisTime(endDate)},PT{numStr}{unitStr[0]})";
                        ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginDate, endDate);
                        ret.Success     = true;
                        return(ret);
                    }

                    if (DateTimePeriodExtractor.FutureRegex.IsExactMatch(beforeStr, trim: true))
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "H":
                            beginDate = referenceTime;
                            endDate   = referenceTime.AddHours((double)pr.Value);
                            break;

                        case "M":
                            beginDate = referenceTime;
                            endDate   = referenceTime.AddMinutes((double)pr.Value);
                            break;

                        case "S":
                            beginDate = referenceTime;
                            endDate   = referenceTime.AddSeconds((double)pr.Value);
                            break;

                        default:
                            return(ret);
                        }

                        ret.Timex =
                            $"({DateTimeFormatUtil.LuisDate(beginDate)}T{DateTimeFormatUtil.LuisTime(beginDate)},{DateTimeFormatUtil.LuisDate(endDate)}T{DateTimeFormatUtil.LuisTime(endDate)},PT{numStr}{unitStr[0]})";
                        ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginDate, endDate);
                        ret.Success     = true;
                        return(ret);
                    }
                }
            }

            // handle "last hour"
            var match = DateTimePeriodExtractor.UnitRegex.Match(text);

            if (match.Success)
            {
                var srcUnit   = match.Groups["unit"].Value.ToLower();
                var beforeStr = text.Substring(0, match.Index).ToLowerInvariant();
                if (this.config.UnitMap.ContainsKey(srcUnit))
                {
                    unitStr = this.config.UnitMap[srcUnit];

                    if (DateTimePeriodExtractor.PastRegex.IsExactMatch(beforeStr, trim: true))
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "H":
                            beginDate = referenceTime.AddHours(-1);
                            endDate   = referenceTime;
                            break;

                        case "M":
                            beginDate = referenceTime.AddMinutes(-1);
                            endDate   = referenceTime;
                            break;

                        case "S":
                            beginDate = referenceTime.AddSeconds(-1);
                            endDate   = referenceTime;
                            break;

                        default:
                            return(ret);
                        }

                        ret.Timex =
                            $"({DateTimeFormatUtil.LuisDate(beginDate)}T{DateTimeFormatUtil.LuisTime(beginDate)},{DateTimeFormatUtil.LuisDate(endDate)}T{DateTimeFormatUtil.LuisTime(endDate)},PT1{unitStr[0]})";
                        ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginDate, endDate);
                        ret.Success     = true;
                        return(ret);
                    }

                    if (DateTimePeriodExtractor.FutureRegex.IsExactMatch(beforeStr, trim: true))
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "H":
                            beginDate = referenceTime;
                            endDate   = referenceTime.AddHours(1);
                            break;

                        case "M":
                            beginDate = referenceTime;
                            endDate   = referenceTime.AddMinutes(1);
                            break;

                        case "S":
                            beginDate = referenceTime;
                            endDate   = referenceTime.AddSeconds(1);
                            break;

                        default:
                            return(ret);
                        }

                        ret.Timex =
                            $"({DateTimeFormatUtil.LuisDate(beginDate)}T{DateTimeFormatUtil.LuisTime(beginDate)},{DateTimeFormatUtil.LuisDate(endDate)}T{DateTimeFormatUtil.LuisTime(endDate)},PT1{unitStr[0]})";
                        ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginDate, endDate);
                        ret.Success     = true;
                        return(ret);
                    }
                }
            }
            return(ret);
        }
コード例 #6
0
        // handle cases like "5分钟前", "1小时以后"
        private DateTimeResolutionResult ParserDurationWithAgoAndLater(string text, DateObject referenceDate)
        {
            var ret         = new DateTimeResolutionResult();
            var durationRes = durationExtractor.Extract(text, referenceDate);

            if (durationRes.Count > 0)
            {
                var match = ChineseDateTimeExtractorConfiguration.DateTimePeriodUnitRegex.Match(text);
                if (match.Success)
                {
                    var suffix  = text.Substring((int)durationRes[0].Start + (int)durationRes[0].Length).Trim();
                    var srcUnit = match.Groups["unit"].Value;

                    var numberStr = text.Substring((int)durationRes[0].Start, match.Index - (int)durationRes[0].Start).Trim();
                    var number    = ConvertChineseToNum(numberStr);

                    if (this.config.UnitMap.ContainsKey(srcUnit))
                    {
                        var unitStr = this.config.UnitMap[srcUnit];

                        var beforeMatch = ChineseDateTimeExtractorConfiguration.BeforeRegex.Match(suffix);
                        if (beforeMatch.Success && suffix.StartsWith(beforeMatch.Value, StringComparison.InvariantCulture))
                        {
                            DateObject date;
                            switch (unitStr)
                            {
                            case Constants.TimexHour:
                                date = referenceDate.AddHours(-number);
                                break;

                            case Constants.TimexMinute:
                                date = referenceDate.AddMinutes(-number);
                                break;

                            case Constants.TimexSecond:
                                date = referenceDate.AddSeconds(-number);
                                break;

                            default:
                                return(ret);
                            }

                            ret.Timex       = $"{DateTimeFormatUtil.LuisDate(date)}";
                            ret.FutureValue = ret.PastValue = date;
                            ret.Success     = true;
                            return(ret);
                        }

                        var afterMatch = ChineseDateTimeExtractorConfiguration.AfterRegex.Match(suffix);
                        if (afterMatch.Success && suffix.StartsWith(afterMatch.Value))
                        {
                            DateObject date;
                            switch (unitStr)
                            {
                            case Constants.TimexHour:
                                date = referenceDate.AddHours(number);
                                break;

                            case Constants.TimexMinute:
                                date = referenceDate.AddMinutes(number);
                                break;

                            case Constants.TimexSecond:
                                date = referenceDate.AddSeconds(number);
                                break;

                            default:
                                return(ret);
                            }

                            ret.Timex       = $"{DateTimeFormatUtil.LuisDate(date)}";
                            ret.FutureValue = ret.PastValue = date;
                            ret.Success     = true;
                            return(ret);
                        }
                    }
                }
            }

            return(ret);
        }
コード例 #7
0
        // match several other cases
        // including '今天', '后天', '十三日'
        protected DateTimeResolutionResult ParseImplicitDate(string text, DateObject referenceDate)
        {
            var ret = new DateTimeResolutionResult();

            // handle "十二日" "明年这个月三日" "本月十一日"
            var match = ChineseDateExtractorConfiguration.SpecialDate.MatchExact(text, trim: true);

            if (match.Success)
            {
                var yearStr  = match.Groups["thisyear"].Value.ToLower();
                var monthStr = match.Groups["thismonth"].Value.ToLower();
                var dayStr   = match.Groups["day"].Value.ToLower();

                int month = referenceDate.Month, year = referenceDate.Year;
                var day = this.config.DayOfMonth[dayStr];

                bool hasYear = false, hasMonth = false;

                if (!string.IsNullOrEmpty(monthStr))
                {
                    hasMonth = true;
                    if (ChineseDateExtractorConfiguration.NextRe.Match(monthStr).Success)
                    {
                        month++;
                        if (month == Constants.MaxMonth + 1)
                        {
                            month = Constants.MinMonth;
                            year++;
                        }
                    }
                    else if (ChineseDateExtractorConfiguration.LastRe.Match(monthStr).Success)
                    {
                        month--;
                        if (month == Constants.MinMonth - 1)
                        {
                            month = Constants.MaxMonth;
                            year--;
                        }
                    }

                    if (!string.IsNullOrEmpty(yearStr))
                    {
                        hasYear = true;
                        if (ChineseDateExtractorConfiguration.NextRe.Match(yearStr).Success)
                        {
                            ++year;
                        }
                        else if (ChineseDateExtractorConfiguration.LastRe.Match(yearStr).Success)
                        {
                            --year;
                        }
                    }
                }

                ret.Timex = DateTimeFormatUtil.LuisDate(hasYear ? year : -1, hasMonth ? month : -1, day);

                DateObject futureDate, pastDate;

                if (day > GetMonthMaxDay(year, month))
                {
                    var futureMonth = month + 1;
                    var pastMonth   = month - 1;
                    var futureYear  = year;
                    var pastYear    = year;

                    if (futureMonth == Constants.MaxMonth + 1)
                    {
                        futureMonth = Constants.MinMonth;
                        futureYear  = year++;
                    }

                    if (pastMonth == Constants.MinMonth - 1)
                    {
                        pastMonth = Constants.MaxMonth;
                        pastYear  = year--;
                    }

                    var isFutureValid = DateObjectExtension.IsValidDate(futureYear, futureMonth, day);
                    var isPastValid   = DateObjectExtension.IsValidDate(pastYear, pastMonth, day);

                    if (isFutureValid && isPastValid)
                    {
                        futureDate = DateObject.MinValue.SafeCreateFromValue(futureYear, futureMonth, day);
                        pastDate   = DateObject.MinValue.SafeCreateFromValue(pastYear, pastMonth, day);
                    }
                    else if (isFutureValid && !isPastValid)
                    {
                        futureDate = pastDate = DateObject.MinValue.SafeCreateFromValue(futureYear, futureMonth, day);
                    }
                    else if (!isFutureValid && !isPastValid)
                    {
                        futureDate = pastDate = DateObject.MinValue.SafeCreateFromValue(pastYear, pastMonth, day);
                    }
                    else
                    {
                        // Fall back to normal cases, might lead to resolution failure
                        // TODO: Ideally, this failure should be filtered out in extract phase
                        futureDate = pastDate = DateObject.MinValue.SafeCreateFromValue(year, month, day);
                    }
                }
                else
                {
                    futureDate = DateObject.MinValue.SafeCreateFromValue(year, month, day);
                    pastDate   = DateObject.MinValue.SafeCreateFromValue(year, month, day);

                    if (!hasMonth)
                    {
                        if (futureDate < referenceDate)
                        {
                            if (IsValidDate(year, month + 1, day))
                            {
                                futureDate = futureDate.AddMonths(1);
                            }
                        }

                        if (pastDate >= referenceDate)
                        {
                            if (IsValidDate(year, month - 1, day))
                            {
                                pastDate = pastDate.AddMonths(-1);
                            }
                            else if (IsNonleapYearFeb29th(year, month - 1, day))
                            {
                                pastDate = pastDate.AddMonths(-2);
                            }
                        }
                    }
                    else if (!hasYear)
                    {
                        if (futureDate < referenceDate)
                        {
                            if (IsValidDate(year + 1, month, day))
                            {
                                futureDate = futureDate.AddYears(1);
                            }
                        }

                        if (pastDate >= referenceDate)
                        {
                            if (IsValidDate(year - 1, month, day))
                            {
                                pastDate = pastDate.AddYears(-1);
                            }
                        }
                    }
                }

                ret.FutureValue = futureDate;
                ret.PastValue   = pastDate;
                ret.Success     = true;

                return(ret);
            }

            // handle cases like "昨日", "明日", "大后天"
            match = ChineseDateExtractorConfiguration.SpecialDayRegex.MatchExact(text, trim: true);

            if (match.Success)
            {
                var value = referenceDate.AddDays(ChineseDateTimeParserConfiguration.GetSwiftDay(match.Value.ToLower()));
                ret.Timex       = DateTimeFormatUtil.LuisDate(value);
                ret.FutureValue = ret.PastValue = value;
                ret.Success     = true;

                return(ret);
            }

            if (!ret.Success)
            {
                ret = MatchThisWeekday(text, referenceDate);
            }

            if (!ret.Success)
            {
                ret = MatchNextWeekday(text, referenceDate);
            }

            if (!ret.Success)
            {
                ret = MatchLastWeekday(text, referenceDate);
            }

            if (!ret.Success)
            {
                ret = MatchWeekdayAlone(text, referenceDate);
            }

            return(ret);
        }
コード例 #8
0
        private DateTimeResolutionResult ParseQuarter(string text, DateObject referenceDate)
        {
            var ret   = new DateTimeResolutionResult();
            var match = DatePeriodExtractorChs.QuarterRegex.Match(text);

            if (!(match.Success && match.Length == text.Length))
            {
                return(ret);
            }

            // pare year
            var year    = referenceDate.Year;
            var yearNum = match.Groups["year"].Value;
            var yearChs = match.Groups["yearchs"].Value;
            var yearRel = match.Groups["yearrel"].Value;

            if (!string.IsNullOrEmpty(yearNum))
            {
                if (yearNum.EndsWith("年"))
                {
                    yearNum = yearNum.Substring(0, yearNum.Length - 1);
                }
                year = int.Parse(yearNum);
            }
            else if (!string.IsNullOrEmpty(yearChs))
            {
                if (yearChs.EndsWith("年"))
                {
                    yearChs = yearChs.Substring(0, yearChs.Length - 1);
                }
                year = ConvertChineseToInteger(yearChs);
            }
            else if (!string.IsNullOrEmpty(yearRel))
            {
                if (yearRel.EndsWith("去年"))
                {
                    year--;
                }
                else if (yearRel.EndsWith("明年"))
                {
                    year++;
                }
            }

            if (year < 100 && year >= 90)
            {
                year += 1900;
            }
            else if (year < 100 && year < 20)
            {
                year += 2000;
            }

            // parse quarterNum
            var cardinalStr = match.Groups["cardinal"].Value;
            var quarterNum  = this.config.CardinalMap[cardinalStr];

            var beginDate = DateObject.MinValue.SafeCreateFromValue(year, quarterNum * 3 - 2, 1);
            var endDate   = DateObject.MinValue.SafeCreateFromValue(year, quarterNum * 3 + 1, 1);

            ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginDate, endDate);
            ret.Timex       = $"({FormatUtil.LuisDate(beginDate)},{FormatUtil.LuisDate(endDate)},P3M)";
            ret.Success     = true;

            return(ret);
        }
コード例 #9
0
        private DateTimeResolutionResult ParseSimpleCases(string text, DateObject referenceDate)
        {
            var ret = new DateTimeResolutionResult();
            int year = referenceDate.Year, month = referenceDate.Month;
            int beginDay, endDay;
            var noYear    = false;
            var inputYear = false;

            var    trimedText = text.Trim();
            var    match = DatePeriodExtractorChs.SimpleCasesRegex.Match(trimedText);
            string beginLuisStr, endLuisStr;

            if (match.Success && match.Index == 0 && match.Length == trimedText.Length)
            {
                var days = match.Groups["day"];
                beginDay = this.config.DayOfMonth[days.Captures[0].Value.ToLower()];
                endDay   = this.config.DayOfMonth[days.Captures[1].Value.ToLower()];

                var monthStr = match.Groups["month"].Value;
                var yearStr  = match.Groups["year"].Value;
                if (!string.IsNullOrEmpty(yearStr))
                {
                    year      = int.Parse(yearStr);
                    inputYear = true;
                }
                else
                {
                    noYear = true;
                }

                if (!string.IsNullOrEmpty(monthStr))
                {
                    month = this.config.MonthOfYear[monthStr.ToLower()];
                }
                else
                {
                    monthStr = match.Groups["relmonth"].Value.Trim().ToLower();
                    var thismatch = DatePeriodExtractorChs.ThisRegex.Match(monthStr);
                    var nextmatch = DatePeriodExtractorChs.NextRegex.Match(monthStr);
                    var lastmatch = DatePeriodExtractorChs.LastRegex.Match(monthStr);

                    if (thismatch.Success)
                    {
                        // do nothing
                    }
                    else if (nextmatch.Success)
                    {
                        if (month != 12)
                        {
                            month += 1;
                        }
                        else
                        {
                            month = 1;
                            year += 1;
                        }
                    }
                    else
                    {
                        if (month != 1)
                        {
                            month -= 1;
                        }
                        else
                        {
                            month = 12;
                            year -= 1;
                        }
                    }
                }

                if (inputYear || DatePeriodExtractorChs.ThisRegex.Match(monthStr).Success ||
                    DatePeriodExtractorChs.NextRegex.Match(monthStr).Success)
                {
                    beginLuisStr = FormatUtil.LuisDate(year, month, beginDay);
                    endLuisStr   = FormatUtil.LuisDate(year, month, endDay);
                }
                else
                {
                    beginLuisStr = FormatUtil.LuisDate(-1, month, beginDay);
                    endLuisStr   = FormatUtil.LuisDate(-1, month, endDay);
                }
            }
            else
            {
                return(ret);
            }

            int futureYear = year, pastYear = year;
            var startDate = DateObject.MinValue.SafeCreateFromValue(year, month, beginDay);

            if (noYear && startDate < referenceDate)
            {
                futureYear++;
            }

            if (noYear && startDate >= referenceDate)
            {
                pastYear--;
            }

            ret.Timex = $"({beginLuisStr},{endLuisStr},P{endDay - beginDay}D)";

            ret.FutureValue = new Tuple <DateObject, DateObject>(
                DateObject.MinValue.SafeCreateFromValue(futureYear, month, beginDay),
                DateObject.MinValue.SafeCreateFromValue(futureYear, month, endDay));

            ret.PastValue = new Tuple <DateObject, DateObject>(
                DateObject.MinValue.SafeCreateFromValue(pastYear, month, beginDay),
                DateObject.MinValue.SafeCreateFromValue(pastYear, month, endDay));

            ret.Success = true;

            return(ret);
        }
コード例 #10
0
 public TestParserResultValue(DateTimeResolutionResult result)
 {
     this.Timex            = result.Timex;
     this.FutureResolution = result.FutureResolution;
     this.PastResolution   = result.PastResolution;
 }
コード例 #11
0
        // parse "今年夏天"
        private DateTimeResolutionResult ParseSeason(string text, DateObject referenceDate)
        {
            var ret   = new DateTimeResolutionResult();
            var match = DatePeriodExtractorChs.SeasonWithYear.Match(text);

            if (match.Success && match.Length == text.Length)
            {
                // parse year
                var year    = referenceDate.Year;
                var hasYear = false;
                var yearNum = match.Groups["year"].Value;
                var yearChs = match.Groups["yearchs"].Value;
                var yearRel = match.Groups["yearrel"].Value;

                if (!string.IsNullOrEmpty(yearNum))
                {
                    hasYear = true;
                    if (yearNum.EndsWith("年"))
                    {
                        yearNum = yearNum.Substring(0, yearNum.Length - 1);
                    }
                    year = int.Parse(yearNum);
                }
                else if (!string.IsNullOrEmpty(yearChs))
                {
                    hasYear = true;
                    if (yearChs.EndsWith("年"))
                    {
                        yearChs = yearChs.Substring(0, yearChs.Length - 1);
                    }
                    year = ConvertChineseToInteger(yearChs);
                }
                else if (!string.IsNullOrEmpty(yearRel))
                {
                    hasYear = true;
                    if (yearRel.EndsWith("去年"))
                    {
                        year--;
                    }
                    else if (yearRel.EndsWith("明年"))
                    {
                        year++;
                    }
                }

                if (year < 100 && year >= 90)
                {
                    year += 1900;
                }
                else if (year < 100 && year < 20)
                {
                    year += 2000;
                }

                // parse season
                var seasonStr = match.Groups["season"].Value;
                ret.Timex = this.config.SeasonMap[seasonStr];
                if (hasYear)
                {
                    ret.Timex = year.ToString("D4") + "-" + ret.Timex;
                }
                ret.Success = true;
                return(ret);
            }
            return(ret);
        }
コード例 #12
0
        public DateTimeParseResult Parse(ExtractResult er, DateObject refDate)
        {
            var referenceTime = refDate;

            // handle cases like "三年半"
            var hasHalfSuffix = false;

            if (er.Text.EndsWith("半", StringComparison.Ordinal))
            {
                er.Length    -= 1;
                er.Text       = er.Text.Substring(0, er.Text.Length - 1);
                hasHalfSuffix = true;
            }

            var parseResult = InternalParser.Parse(er);
            var unitResult  = parseResult.Value as UnitValue;

            if (unitResult == null)
            {
                return(null);
            }

            var dateTimeParseResult = new DateTimeResolutionResult();
            var unitStr             = unitResult.Unit;
            var numStr = unitResult.Number;

            if (hasHalfSuffix)
            {
                numStr = (double.Parse(numStr) + 0.5).ToString(CultureInfo.InvariantCulture);
            }

            dateTimeParseResult.Timex       = "P" + (BaseDurationParser.IsLessThanDay(unitStr) ? "T" : string.Empty) + numStr + unitStr[0];
            dateTimeParseResult.FutureValue = dateTimeParseResult.PastValue = double.Parse(numStr) * UnitValueMap[unitStr];
            dateTimeParseResult.Success     = true;

            if (dateTimeParseResult.Success)
            {
                dateTimeParseResult.FutureResolution = new Dictionary <string, string>
                {
                    { TimeTypeConstants.DURATION, dateTimeParseResult.FutureValue.ToString() },
                };

                dateTimeParseResult.PastResolution = new Dictionary <string, string>
                {
                    { TimeTypeConstants.DURATION, dateTimeParseResult.PastValue.ToString() },
                };
            }

            var ret = new DateTimeParseResult
            {
                Text          = er.Text,
                Start         = er.Start,
                Length        = er.Length,
                Type          = er.Type,
                Data          = er.Data,
                Value         = dateTimeParseResult,
                TimexStr      = dateTimeParseResult.Timex,
                ResolutionStr = string.Empty,
            };

            return(ret);
        }
コード例 #13
0
        protected override DateTimeResolutionResult ParseSpecificTimeOfDay(string text, DateObject referenceTime)
        {
            var ret         = new DateTimeResolutionResult();
            var trimmedText = text.Trim();

            // handle morning, afternoon..
            if (!this.Config.GetMatchedTimeRange(trimmedText, out string timeStr, out int beginHour, out int endHour, out int endMin))
            {
                return(ret);
            }

            var exactMatch = this.Config.SpecificTimeOfDayRegex.MatchExact(trimmedText, trim: true);

            if (!exactMatch.Success)
            {
                exactMatch = this.Config.PeriodTimeOfDayWithDateRegex.MatchExact(trimmedText, trim: true);
            }

            if (exactMatch.Success)
            {
                // Extract early/late prefix from text if any
                bool hasEarly = false;
                if (!string.IsNullOrEmpty(exactMatch.Groups["early"].Value))
                {
                    hasEarly    = true;
                    ret.Comment = Constants.Comment_Early;
                    ret.Mod     = Constants.EARLY_MOD;
                    endHour     = beginHour + 2;

                    // Handling special case: night ends with 23:59 due to C# issues.
                    if (endMin == 59)
                    {
                        endMin = 0;
                    }
                }

                if (!hasEarly && !string.IsNullOrEmpty(exactMatch.Groups["late"].Value))
                {
                    ret.Comment = Constants.Comment_Late;
                    ret.Mod     = Constants.LATE_MOD;
                    beginHour   = beginHour + 2;
                }

                var swift = this.Config.GetSwiftPrefix(trimmedText);

                var date = referenceTime.AddDays(swift).Date;
                int day = date.Day, month = date.Month, year = date.Year;

                ret.Timex         = DateTimeFormatUtil.FormatDate(date) + timeStr;
                ret.FutureValue   =
                    ret.PastValue =
                        new Tuple <DateObject, DateObject>(
                            DateObject.MinValue.SafeCreateFromValue(year, month, day, beginHour, 0, 0),
                            DateObject.MinValue.SafeCreateFromValue(year, month, day, endHour, endMin, endMin));
                ret.Success = true;
                return(ret);
            }

            var startIndex = trimmedText.IndexOf(DateTimeDefinitions.Tomorrow, StringComparison.Ordinal) == 0 ? DateTimeDefinitions.Tomorrow.Length : 0;

            // handle Date preceded/followed by morning, afternoon
            // @TODO Add handling code to handle early/late morning, afternoon
            var match = this.Config.TimeOfDayRegex.Match(trimmedText.Substring(startIndex));

            if (match.Success)
            {
                var subStr = match.Index > 0 ? trimmedText.Substring(0, match.Index + startIndex).Trim() : trimmedText.Substring(match.Index + match.Length).Trim();
                var ers    = this.Config.DateExtractor.Extract(subStr, referenceTime);

                if (ers.Count == 0)
                {
                    return(ret);
                }

                // Check if Date and TimeOfDay are contiguous
                var middleStr = match.Index > 0 ? subStr.Substring((int)ers[0].Start + (int)ers[0].Length).Trim() : subStr.Substring(0, (int)ers[0].Start).Trim();
                if (!(string.IsNullOrWhiteSpace(middleStr) || ConnectorRegex.IsMatch(middleStr)))
                {
                    return(ret);
                }

                var pr         = this.Config.DateParser.Parse(ers[0], referenceTime);
                var futureDate = (DateObject)((DateTimeResolutionResult)pr.Value).FutureValue;
                var pastDate   = (DateObject)((DateTimeResolutionResult)pr.Value).PastValue;

                ret.Timex = pr.TimexStr + timeStr;

                ret.FutureValue =
                    new Tuple <DateObject, DateObject>(
                        DateObject.MinValue.SafeCreateFromValue(futureDate.Year, futureDate.Month, futureDate.Day, beginHour, 0, 0),
                        DateObject.MinValue.SafeCreateFromValue(futureDate.Year, futureDate.Month, futureDate.Day, endHour, endMin, endMin));

                ret.PastValue =
                    new Tuple <DateObject, DateObject>(
                        DateObject.MinValue.SafeCreateFromValue(pastDate.Year, pastDate.Month, pastDate.Day, beginHour, 0, 0),
                        DateObject.MinValue.SafeCreateFromValue(pastDate.Year, pastDate.Month, pastDate.Day, endHour, endMin, endMin));

                ret.Success = true;

                return(ret);
            }

            return(ret);
        }
コード例 #14
0
        protected override DateTimeResolutionResult ParseSpecificTimeOfDay(string text, DateObject referenceTime)
        {
            var ret         = new DateTimeResolutionResult();
            var trimmedText = text.Trim().ToLowerInvariant();

            // Handle morning, afternoon..
            if (!this.Config.GetMatchedTimeRange(trimmedText, out string timeStr, out int beginHour, out int endHour, out int endMin))
            {
                return(ret);
            }

            var match = this.Config.SpecificTimeOfDayRegex.Match(trimmedText);

            if (match.Success && match.Index == 0 && match.Length == trimmedText.Length)
            {
                var swift = this.Config.GetSwiftPrefix(trimmedText);

                var date = referenceTime.AddDays(swift).Date;
                int day = date.Day, month = date.Month, year = date.Year;

                ret.Timex         = FormatUtil.FormatDate(date) + timeStr;
                ret.FutureValue   =
                    ret.PastValue =
                        new Tuple <DateObject, DateObject>(DateObject.MinValue.SafeCreateFromValue(year, month, day, beginHour, 0, 0),
                                                           DateObject.MinValue.SafeCreateFromValue(year, month, day, endHour, endMin, endMin));
                ret.Success = true;
                return(ret);
            }

            var startIndex = trimmedText.IndexOf(DateTimeDefinitions.Tomorrow, StringComparison.Ordinal) == 0 ? DateTimeDefinitions.Tomorrow.Length : 0;

            // Handle Date followed by morning, afternoon, ...
            // Add handling code to handle morning, afternoon followed by Date
            // Add handling code to handle early/late morning, afternoon
            match = this.Config.TimeOfDayRegex.Match(trimmedText.Substring(startIndex));
            if (match.Success)
            {
                var beforeStr = trimmedText.Substring(0, match.Index + startIndex).Trim();
                var ers       = this.Config.DateExtractor.Extract(beforeStr, referenceTime);
                if (ers.Count == 0)
                {
                    return(ret);
                }

                var pr         = this.Config.DateParser.Parse(ers[0], referenceTime);
                var futureDate = (DateObject)((DateTimeResolutionResult)pr.Value).FutureValue;
                var pastDate   = (DateObject)((DateTimeResolutionResult)pr.Value).PastValue;

                ret.Timex = pr.TimexStr + timeStr;

                ret.FutureValue =
                    new Tuple <DateObject, DateObject>(
                        DateObject.MinValue.SafeCreateFromValue(futureDate.Year, futureDate.Month, futureDate.Day, beginHour, 0, 0),
                        DateObject.MinValue.SafeCreateFromValue(futureDate.Year, futureDate.Month, futureDate.Day, endHour, endMin, endMin));

                ret.PastValue =
                    new Tuple <DateObject, DateObject>(
                        DateObject.MinValue.SafeCreateFromValue(pastDate.Year, pastDate.Month, pastDate.Day, beginHour, 0, 0),
                        DateObject.MinValue.SafeCreateFromValue(pastDate.Year, pastDate.Month, pastDate.Day, endHour, endMin, endMin));

                ret.Success = true;

                return(ret);
            }

            return(ret);
        }
コード例 #15
0
        // merge a Date entity and a Time entity
        private DateTimeResolutionResult MergeDateAndTime(string text, DateObject referenceTime)
        {
            var ret = new DateTimeResolutionResult();

            var er1 = SingleDateExtractor.Extract(text, referenceTime);

            if (er1.Count == 0)
            {
                return(ret);
            }

            var er2 = SingleTimeExtractor.Extract(text, referenceTime);

            if (er2.Count == 0)
            {
                return(ret);
            }

            // TODO: Add reference time
            var pr1 = this.config.DateParser.Parse(er1[0], referenceTime.Date);
            var pr2 = this.config.TimeParser.Parse(er2[0], referenceTime);

            if (pr1.Value == null || pr2.Value == null)
            {
                return(ret);
            }

            var futureDate = (DateObject)((DateTimeResolutionResult)pr1.Value).FutureValue;
            var pastDate   = (DateObject)((DateTimeResolutionResult)pr1.Value).PastValue;
            var time       = (DateObject)((DateTimeResolutionResult)pr2.Value).FutureValue;

            var hour = time.Hour;
            var min  = time.Minute;
            var sec  = time.Second;

            // handle morning, afternoon
            if (SimplePmRegex.IsMatch(text) && hour < Constants.HalfDayHourCount)
            {
                hour += Constants.HalfDayHourCount;
            }
            else if (SimpleAmRegex.IsMatch(text) && hour >= Constants.HalfDayHourCount)
            {
                hour -= Constants.HalfDayHourCount;
            }

            var timeStr = pr2.TimexStr;

            if (timeStr.EndsWith(Constants.Comment_AmPm, StringComparison.Ordinal))
            {
                timeStr = timeStr.Substring(0, timeStr.Length - 4);
            }

            timeStr   = "T" + hour.ToString("D2") + timeStr.Substring(3);
            ret.Timex = pr1.TimexStr + timeStr;

            var val = (DateTimeResolutionResult)pr2.Value;

            if (hour <= Constants.HalfDayHourCount && !SimplePmRegex.IsMatch(text) && !SimpleAmRegex.IsMatch(text) &&
                !string.IsNullOrEmpty(val.Comment))
            {
                // ret.Timex += "ampm";
                ret.Comment = Constants.Comment_AmPm;
            }

            ret.FutureValue = DateObject.MinValue.SafeCreateFromValue(futureDate.Year, futureDate.Month, futureDate.Day, hour, min, sec);
            ret.PastValue   = DateObject.MinValue.SafeCreateFromValue(pastDate.Year, pastDate.Month, pastDate.Day, hour, min, sec);
            ret.Success     = true;

            return(ret);
        }
コード例 #16
0
        // handle like "2016年到2017年"
        private static DateTimeResolutionResult ParseYearToYear(string text, DateObject referenceDate)
        {
            var ret   = new DateTimeResolutionResult();
            var match = DatePeriodExtractorChs.YearToYear.Match(text);

            if (match.Success)
            {
                var yearMatch          = DatePeriodExtractorChs.YearRegex.Matches(text);
                var yearInChineseMatch = DatePeriodExtractorChs.YearInChineseRegex.Matches(text);
                var beginYear          = 0;
                var endYear            = 0;
                if (yearMatch.Count == 2)
                {
                    var yearFrom = yearMatch[0].Groups["year"].Value;
                    var yearTo   = yearMatch[1].Groups["year"].Value;
                    beginYear = int.Parse(yearFrom);
                    endYear   = int.Parse(yearTo);
                }
                else if (yearInChineseMatch.Count == 2)
                {
                    var yearFrom = yearInChineseMatch[0].Groups["yearchs"].Value;
                    var yearTo   = yearInChineseMatch[1].Groups["yearchs"].Value;
                    beginYear = ConvertChineseToInteger(yearFrom);
                    endYear   = ConvertChineseToInteger(yearTo);
                }
                else if (yearInChineseMatch.Count == 1 && yearMatch.Count == 1)
                {
                    if (yearMatch[0].Index < yearInChineseMatch[0].Index)
                    {
                        var yearFrom = yearMatch[0].Groups["year"].Value;
                        var yearTo   = yearInChineseMatch[0].Groups["yearch"].Value;
                        beginYear = int.Parse(yearFrom);
                        endYear   = ConvertChineseToInteger(yearTo);
                    }
                    else
                    {
                        var yearFrom = yearInChineseMatch[0].Groups["yearch"].Value;
                        var yearTo   = yearMatch[0].Groups["year"].Value;
                        beginYear = ConvertChineseToInteger(yearFrom);
                        endYear   = int.Parse(yearTo);
                    }
                }

                if (beginYear < 100 && beginYear >= 90)
                {
                    beginYear += 1900;
                }
                else if (beginYear < 100 && beginYear < 20)
                {
                    beginYear += 2000;
                }

                if (endYear < 100 && endYear >= 90)
                {
                    endYear += 1900;
                }
                else if (endYear < 100 && endYear < 20)
                {
                    endYear += 2000;
                }

                var beginDay   = DateObject.MinValue.SafeCreateFromValue(beginYear, 1, 1);
                var endDay     = DateObject.MinValue.SafeCreateFromValue(endYear, 12, 31);
                var beginTimex = beginYear.ToString("D4");
                var endTimex   = endYear.ToString("D4");
                ret.Timex       = $"({beginTimex},{endTimex},P{endYear - beginYear}Y)";
                ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginDay, endDay);
                ret.Success     = true;
                return(ret);
            }
            return(ret);
        }
コード例 #17
0
        private DateTimeResolutionResult ParseTimeOfToday(string text, DateObject referenceTime)
        {
            var ret = new DateTimeResolutionResult();
            var ers = SingleTimeExtractor.Extract(text, referenceTime);

            if (ers.Count != 1)
            {
                return(ret);
            }

            // TODO: Add reference time
            var pr = this.config.TimeParser.Parse(ers[0], referenceTime);

            if (pr.Value == null)
            {
                return(ret);
            }

            var time = (DateObject)((DateTimeResolutionResult)pr.Value).FutureValue;

            var hour = time.Hour;
            var min  = time.Minute;
            var sec  = time.Second;

            var match = ChineseDateTimeExtractorConfiguration.TimeOfTodayRegex.Match(text);

            if (match.Success)
            {
                var matchStr = match.Value;

                var swift = 0;
                switch (matchStr)
                {
                case "今晚":
                    if (hour < Constants.HalfDayHourCount)
                    {
                        hour += Constants.HalfDayHourCount;
                    }

                    break;

                case "今早":
                case "今晨":
                    if (hour >= Constants.HalfDayHourCount)
                    {
                        hour -= Constants.HalfDayHourCount;
                    }

                    break;

                case "明晚":
                    swift = 1;
                    if (hour < Constants.HalfDayHourCount)
                    {
                        hour += Constants.HalfDayHourCount;
                    }

                    break;

                case "明早":
                case "明晨":
                    swift = 1;
                    if (hour >= Constants.HalfDayHourCount)
                    {
                        hour -= Constants.HalfDayHourCount;
                    }

                    break;

                case "昨晚":
                    swift = -1;
                    if (hour < Constants.HalfDayHourCount)
                    {
                        hour += Constants.HalfDayHourCount;
                    }

                    break;

                default:
                    break;
                }

                var date = referenceTime.AddDays(swift).Date;

                // in this situation, luisStr cannot end up with "ampm", because we always have a "morning" or "night"
                var timeStr = pr.TimexStr;
                if (timeStr.EndsWith(Constants.Comment_AmPm, StringComparison.Ordinal))
                {
                    timeStr = timeStr.Substring(0, timeStr.Length - 4);
                }

                timeStr = "T" + hour.ToString("D2") + timeStr.Substring(3);

                ret.Timex       = DateTimeFormatUtil.FormatDate(date) + timeStr;
                ret.FutureValue = ret.PastValue = DateObject.MinValue.SafeCreateFromValue(date.Year, date.Month, date.Day, hour, min, sec);
                ret.Success     = true;
                return(ret);
            }

            return(ret);
        }
コード例 #18
0
        // for case "2016年5月"
        private DateTimeResolutionResult ParseYearAndMonth(string text, DateObject referenceDate)
        {
            var ret   = new DateTimeResolutionResult();
            var match = DatePeriodExtractorChs.YearAndMonth.Match(text);

            if (!(match.Success && match.Length == text.Length))
            {
                match = DatePeriodExtractorChs.PureNumYearAndMonth.Match(text);
            }

            if (!(match.Success && match.Length == text.Length))
            {
                return(ret);
            }

            // parse year
            var year    = referenceDate.Year;
            var yearNum = match.Groups["year"].Value;
            var yearChs = match.Groups["yearchs"].Value;
            var yearRel = match.Groups["yearrel"].Value;

            if (!string.IsNullOrEmpty(yearNum))
            {
                if (yearNum.EndsWith("年"))
                {
                    yearNum = yearNum.Substring(0, yearNum.Length - 1);
                }
                year = int.Parse(yearNum);
            }
            else if (!string.IsNullOrEmpty(yearChs))
            {
                if (yearChs.EndsWith("年"))
                {
                    yearChs = yearChs.Substring(0, yearChs.Length - 1);
                }
                year = ConvertChineseToInteger(yearChs);
            }
            else if (!string.IsNullOrEmpty(yearRel))
            {
                if (yearRel.EndsWith("去年"))
                {
                    year--;
                }
                else if (yearRel.EndsWith("明年"))
                {
                    year++;
                }
            }

            if (year < 100 && year >= 90)
            {
                year += 1900;
            }
            else if (year < 20)
            {
                year += 2000;
            }

            var        monthStr = match.Groups["month"].Value;
            var        month    = this.config.MonthOfYear[monthStr] > 12 ? this.config.MonthOfYear[monthStr] % 12 : this.config.MonthOfYear[monthStr];
            var        beginDay = DateObject.MinValue.SafeCreateFromValue(year, month, 1);
            DateObject endDay;

            if (month == 12)
            {
                endDay = DateObject.MinValue.SafeCreateFromValue(year + 1, 1, 1);
            }
            else
            {
                endDay = DateObject.MinValue.SafeCreateFromValue(year, month + 1, 1);
            }

            ret.Timex       = year.ToString("D4") + "-" + month.ToString("D2");
            ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginDay, endDay);
            ret.Success     = true;
            return(ret);
        }
コード例 #19
0
        // handle cases like "三天前"
        private DateTimeResolutionResult ParserDurationWithBeforeAndAfter(string text, DateObject referenceDate)
        {
            var ret         = new DateTimeResolutionResult();
            var durationRes = durationExtractor.Extract(text, referenceDate);
            var numStr      = string.Empty;
            var unitStr     = string.Empty;

            if (durationRes.Count > 0)
            {
                var match = DateExtractor.UnitRegex.Match(text);
                if (match.Success)
                {
                    var suffix =
                        text.Substring((int)durationRes[0].Start + (int)durationRes[0].Length)
                        .Trim()
                        .ToLowerInvariant();
                    var srcUnit   = match.Groups["unit"].Value.ToLowerInvariant();
                    var numberStr =
                        text.Substring((int)durationRes[0].Start, match.Index - (int)durationRes[0].Start)
                        .Trim()
                        .ToLowerInvariant();
                    var number = ConvertJapaneseToNum(numberStr);
                    if (this.config.UnitMap.ContainsKey(srcUnit))
                    {
                        unitStr = this.config.UnitMap[srcUnit];
                        numStr  = number.ToString();

                        var beforeMatch = DateExtractor.BeforeRegex.Match(suffix);
                        if (beforeMatch.Success && suffix.StartsWith(beforeMatch.Value))
                        {
                            DateObject date;
                            switch (unitStr)
                            {
                            case Constants.TimexDay:
                                date = referenceDate.AddDays(-double.Parse(numStr));
                                break;

                            case Constants.TimexWeek:
                                date = referenceDate.AddDays(-7 * double.Parse(numStr));
                                break;

                            case Constants.TimexMonthFull:
                                date = referenceDate.AddMonths(-Convert.ToInt32(double.Parse(numStr)));
                                break;

                            case Constants.TimexYear:
                                date = referenceDate.AddYears(-Convert.ToInt32(double.Parse(numStr)));
                                break;

                            default:
                                return(ret);
                            }
                            ret.Timex       = $"{DateTimeFormatUtil.LuisDate(date)}";
                            ret.FutureValue = ret.PastValue = date;
                            ret.Success     = true;
                            return(ret);
                        }

                        var afterMatch = DateExtractor.AfterRegex.Match(suffix);
                        if (afterMatch.Success && suffix.StartsWith(afterMatch.Value))
                        {
                            DateObject date;
                            switch (unitStr)
                            {
                            case Constants.TimexDay:
                                date = referenceDate.AddDays(double.Parse(numStr));
                                break;

                            case Constants.TimexWeek:
                                date = referenceDate.AddDays(7 * double.Parse(numStr));
                                break;

                            case Constants.TimexMonthFull:
                                date = referenceDate.AddMonths(Convert.ToInt32(double.Parse(numStr)));
                                break;

                            case Constants.TimexYear:
                                date = referenceDate.AddYears(Convert.ToInt32(double.Parse(numStr)));
                                break;

                            default:
                                return(ret);
                            }

                            ret.Timex       = $"{DateTimeFormatUtil.LuisDate(date)}";
                            ret.FutureValue = ret.PastValue = date;
                            ret.Success     = true;
                            return(ret);
                        }
                    }
                }
            }

            return(ret);
        }
コード例 #20
0
        // case like "今年三月" "这个周末" "五月"
        private DateTimeResolutionResult ParseOneWordPeriod(string text, DateObject referenceDate)
        {
            var ret = new DateTimeResolutionResult();
            int year = referenceDate.Year, month = referenceDate.Month;
            int futureYear = year, pastYear = year;

            var trimedText = text.Trim().ToLower();
            var match      = DatePeriodExtractorChs.OneWordPeriodRegex.Match(trimedText);

            if (match.Success && match.Index == 0 && match.Length == trimedText.Length)
            {
                var monthStr = match.Groups["month"].Value;
                if (trimedText.Equals("今年"))
                {
                    ret.Timex         = referenceDate.Year.ToString("D4");
                    ret.FutureValue   =
                        ret.PastValue =
                            new Tuple <DateObject, DateObject>(DateObject.MinValue.SafeCreateFromValue(referenceDate.Year, 1, 1), referenceDate);
                    ret.Success = true;
                    return(ret);
                }

                var thismatch = DatePeriodExtractorChs.ThisRegex.Match(trimedText);
                var nextmatch = DatePeriodExtractorChs.NextRegex.Match(trimedText);
                var lastmatch = DatePeriodExtractorChs.LastRegex.Match(trimedText);

                if (!string.IsNullOrEmpty(monthStr))
                {
                    var swift = -10;

                    if (trimedText.StartsWith("明年"))
                    {
                        swift = 1;
                    }
                    else if (trimedText.StartsWith("去年"))
                    {
                        swift = -1;
                    }
                    else if (trimedText.StartsWith("今年"))
                    {
                        swift = 0;
                    }

                    month = this.config.MonthOfYear[monthStr.ToLower()];

                    if (swift >= -1)
                    {
                        ret.Timex  = (referenceDate.Year + swift).ToString("D4") + "-" + month.ToString("D2");
                        year       = year + swift;
                        futureYear = pastYear = year;
                    }
                    else
                    {
                        ret.Timex = "XXXX-" + month.ToString("D2");
                        if (month < referenceDate.Month)
                        {
                            futureYear++;
                        }

                        if (month >= referenceDate.Month)
                        {
                            pastYear--;
                        }
                    }
                }
                else
                {
                    var swift = 0;
                    if (nextmatch.Success)
                    {
                        swift = 1;
                    }
                    else if (lastmatch.Success)
                    {
                        swift = -1;
                    }

                    if (trimedText.EndsWith("周") | trimedText.EndsWith("星期"))
                    {
                        var monday = referenceDate.This(DayOfWeek.Monday).AddDays(7 * swift);
                        ret.Timex = monday.Year.ToString("D4") + "-W" +
                                    Cal.GetWeekOfYear(monday, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday)
                                    .ToString("D2");
                        ret.FutureValue   =
                            ret.PastValue =
                                new Tuple <DateObject, DateObject>(
                                    referenceDate.This(DayOfWeek.Monday).AddDays(7 * swift),
                                    referenceDate.This(DayOfWeek.Sunday).AddDays(7 * swift).AddDays(1));
                        ret.Success = true;
                        return(ret);
                    }

                    if (trimedText.EndsWith("周末"))
                    {
                        var beginDate = referenceDate.This(DayOfWeek.Saturday).AddDays(7 * swift);
                        var endDate   = referenceDate.This(DayOfWeek.Sunday).AddDays(7 * swift);

                        ret.Timex = beginDate.Year.ToString("D4") + "-W" +
                                    Cal.GetWeekOfYear(beginDate, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday)
                                    .ToString("D2") + "-WE";

                        ret.FutureValue   =
                            ret.PastValue = new Tuple <DateObject, DateObject>(beginDate, endDate.AddDays(1));

                        ret.Success = true;

                        return(ret);
                    }

                    if (trimedText.EndsWith("月"))
                    {
                        month      = referenceDate.AddMonths(swift).Month;
                        year       = referenceDate.AddMonths(swift).Year;
                        ret.Timex  = year.ToString("D4") + "-" + month.ToString("D2");
                        futureYear = pastYear = year;
                    }
                    else if (trimedText.EndsWith("年"))
                    {
                        year = referenceDate.AddYears(swift).Year;
                        if (trimedText.EndsWith("去年"))
                        {
                            year--;
                        }
                        else if (trimedText.EndsWith("明年"))
                        {
                            year++;
                        }
                        else if (trimedText.EndsWith("前年"))
                        {
                            year -= 2;
                        }
                        else if (trimedText.EndsWith("后年"))
                        {
                            year += 2;
                        }

                        ret.Timex         = year.ToString("D4");
                        ret.FutureValue   =
                            ret.PastValue =
                                new Tuple <DateObject, DateObject>(DateObject.MinValue.SafeCreateFromValue(year, 1, 1),
                                                                   DateObject.MinValue.SafeCreateFromValue(year, 12, 31).AddDays(1));
                        ret.Success = true;
                        return(ret);
                    }
                }
            }
            else
            {
                return(ret);
            }

            // only "month" will come to here
            ret.FutureValue = new Tuple <DateObject, DateObject>(
                DateObject.MinValue.SafeCreateFromValue(futureYear, month, 1),
                DateObject.MinValue.SafeCreateFromValue(futureYear, month, 1).AddMonths(1));

            ret.PastValue = new Tuple <DateObject, DateObject>(
                DateObject.MinValue.SafeCreateFromValue(pastYear, month, 1),
                DateObject.MinValue.SafeCreateFromValue(pastYear, month, 1).AddMonths(1));

            ret.Success = true;

            return(ret);
        }
コード例 #21
0
        private static DateTimeResolutionResult Match2Date(Match match, DateObject referenceDate)
        {
            var ret        = new DateTimeResolutionResult();
            var holidayStr = match.Groups["holiday"].Value.ToLower();

            var year    = referenceDate.Year;
            var hasYear = false;
            var yearNum = match.Groups["year"].Value;
            var yearChs = match.Groups["yearchs"].Value;
            var yearRel = match.Groups["yearrel"].Value;

            if (!string.IsNullOrEmpty(yearNum))
            {
                hasYear = true;
                if (yearNum.EndsWith("年"))
                {
                    yearNum = yearNum.Substring(0, yearNum.Length - 1);
                }
                year = int.Parse(yearNum);
            }
            else if (!string.IsNullOrEmpty(yearChs))
            {
                hasYear = true;
                if (yearChs.EndsWith("年"))
                {
                    yearChs = yearChs.Substring(0, yearChs.Length - 1);
                }
                year = ConvertChineseToInteger(yearChs);
            }
            else if (!string.IsNullOrEmpty(yearRel))
            {
                hasYear = true;
                if (yearRel.EndsWith("去年"))
                {
                    year--;
                }
                else if (yearRel.EndsWith("明年"))
                {
                    year++;
                }
            }

            if (year < 100 && year >= 90)
            {
                year += 1900;
            }
            else if (year < 20)
            {
                year += 2000;
            }

            if (!string.IsNullOrEmpty(holidayStr))
            {
                DateObject value;
                string     timexStr;
                if (FixedHolidaysDict.ContainsKey(holidayStr))
                {
                    value    = FixedHolidaysDict[holidayStr](year);
                    timexStr = $"-{value.Month:D2}-{value.Day:D2}";
                }
                else
                {
                    if (HolidayFuncDict.ContainsKey(holidayStr))
                    {
                        value    = HolidayFuncDict[holidayStr](year);
                        timexStr = NoFixedTimex[holidayStr];
                    }
                    else
                    {
                        return(ret);
                    }
                }

                if (hasYear)
                {
                    ret.Timex       = year.ToString("D4") + timexStr;
                    ret.FutureValue = ret.PastValue = DateObject.MinValue.SafeCreateFromValue(year, value.Month, value.Day);
                    ret.Success     = true;
                    return(ret);
                }

                ret.Timex       = "XXXX" + timexStr;
                ret.FutureValue = GetFutureValue(value, referenceDate, holidayStr);
                ret.PastValue   = GetPastValue(value, referenceDate, holidayStr);
                ret.Success     = true;
                return(ret);
            }

            return(ret);
        }
コード例 #22
0
        // only contains year like "2016年"
        private static DateTimeResolutionResult ParseYear(string text, DateObject referenceDate)
        {
            var ret   = new DateTimeResolutionResult();
            var match = DatePeriodExtractorChs.YearRegex.Match(text);

            if (match.Success && match.Length == text.Length)
            {
                var tmp = match.Value;
                if (tmp.EndsWith("年"))
                {
                    tmp = tmp.Substring(0, tmp.Length - 1);
                }

                var num  = 0;
                var year = 0;
                if (tmp.Length == 2)
                {
                    num = int.Parse(tmp);
                    if (num < 100 && num >= 20)
                    {
                        num += 1900;
                    }
                    else if (num < 20)
                    {
                        num += 2000;
                    }
                    year = num;
                }
                else
                {
                    year = int.Parse(tmp);
                }

                var beginDay = DateObject.MinValue.SafeCreateFromValue(year, 1, 1);
                var endDay   = DateObject.MinValue.SafeCreateFromValue(year + 1, 1, 1);
                ret.Timex       = year.ToString("D4");
                ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginDay, endDay);
                ret.Success     = true;
                return(ret);
            }

            match = DatePeriodExtractorChs.YearInChineseRegex.Match(text);
            if (match.Success && match.Length == text.Length)
            {
                var tmp = match.Value;
                if (tmp.EndsWith("年"))
                {
                    tmp = tmp.Substring(0, tmp.Length - 1);
                }

                if (tmp.Length == 1)
                {
                    return(ret);
                }

                var re   = ConvertChineseToInteger(tmp);
                var year = re;

                if (year < 100 && year >= 90)
                {
                    year += 1900;
                }
                else if (year < 100 && year < 20)
                {
                    year += 2000;
                }

                var beginDay = DateObject.MinValue.SafeCreateFromValue(year, 1, 1);
                var endDay   = DateObject.MinValue.SafeCreateFromValue(year + 1, 1, 1);
                ret.Timex       = year.ToString("D4");
                ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginDay, endDay);
                ret.Success     = true;
                return(ret);
            }

            return(ret);
        }
コード例 #23
0
        // parse "this night"
        private DateTimeResolutionResult ParseSpecificNight(string text, DateObject referenceTime)
        {
            var    ret = new DateTimeResolutionResult();
            var    trimmedText = text.Trim().ToLowerInvariant();
            int    beginHour, endHour, endMin = 0;
            string timeStr;

            // handle 昨晚,今晨
            var exactMatch = DateTimePeriodExtractor.SpecificTimeOfDayRegex.MatchExact(trimmedText, trim: true);

            if (exactMatch.Success)
            {
                var swift = 0;
                switch (trimmedText)
                {
                case "今晚":
                    swift     = 0;
                    timeStr   = "TEV";
                    beginHour = 16;
                    endHour   = 20;
                    break;

                case "今早":
                case "今晨":
                    swift     = 0;
                    timeStr   = "TMO";
                    beginHour = 8;
                    endHour   = Constants.HalfDayHourCount;
                    break;

                case "明晚":
                    swift     = 1;
                    timeStr   = "TEV";
                    beginHour = 16;
                    endHour   = 20;
                    break;

                case "明早":
                case "明晨":
                    swift     = 1;
                    timeStr   = "TMO";
                    beginHour = 8;
                    endHour   = Constants.HalfDayHourCount;
                    break;

                case "昨晚":
                    swift     = -1;
                    timeStr   = "TEV";
                    beginHour = 16;
                    endHour   = 20;
                    break;

                default:
                    return(ret);
                }

                var date = referenceTime.AddDays(swift).Date;
                int day = date.Day, month = date.Month, year = date.Year;

                ret.Timex         = DateTimeFormatUtil.FormatDate(date) + timeStr;
                ret.FutureValue   =
                    ret.PastValue =
                        new Tuple <DateObject, DateObject>(DateObject.MinValue.SafeCreateFromValue(year, month, day, beginHour, 0, 0),
                                                           DateObject.MinValue.SafeCreateFromValue(year, month, day, endHour, endMin, endMin));
                ret.Success = true;
                return(ret);
            }

            // handle morning, afternoon..
            if (MORegex.IsMatch(trimmedText))
            {
                timeStr   = "TMO";
                beginHour = 8;
                endHour   = Constants.HalfDayHourCount;
            }
            else if (AFRegex.IsMatch(trimmedText))
            {
                timeStr   = "TAF";
                beginHour = Constants.HalfDayHourCount;
                endHour   = 16;
            }
            else if (EVRegex.IsMatch(trimmedText))
            {
                timeStr   = "TEV";
                beginHour = 16;
                endHour   = 20;
            }
            else if (NIRegex.IsMatch(trimmedText))
            {
                timeStr   = "TNI";
                beginHour = 20;
                endHour   = 23;
                endMin    = 59;
            }
            else
            {
                return(ret);
            }

            exactMatch = DateTimePeriodExtractor.SpecificTimeOfDayRegex.MatchExact(trimmedText, trim: true);

            if (exactMatch.Success)
            {
                var swift = 0;
                if (DateTimePeriodExtractor.NextRegex.IsMatch(trimmedText))
                {
                    swift = 1;
                }
                else if (DateTimePeriodExtractor.LastRegex.IsMatch(trimmedText))
                {
                    swift = -1;
                }

                var date = referenceTime.AddDays(swift).Date;
                int day = date.Day, month = date.Month, year = date.Year;

                ret.Timex         = DateTimeFormatUtil.FormatDate(date) + timeStr;
                ret.FutureValue   =
                    ret.PastValue =
                        new Tuple <DateObject, DateObject>(DateObject.MinValue.SafeCreateFromValue(year, month, day, beginHour, 0, 0),
                                                           DateObject.MinValue.SafeCreateFromValue(year, month, day, endHour, endMin, endMin));
                ret.Success = true;
                return(ret);
            }


            // handle Date followed by morning, afternoon
            var match = DateTimePeriodExtractor.TimeOfDayRegex.Match(trimmedText);

            if (match.Success)
            {
                var beforeStr = trimmedText.Substring(0, match.Index).Trim();
                var ers       = SingleDateExtractor.Extract(beforeStr, referenceTime);
                if (ers.Count == 0 || ers[0].Length != beforeStr.Length)
                {
                    return(ret);
                }

                var pr         = this.config.DateParser.Parse(ers[0], referenceTime);
                var futureDate = (DateObject)((DateTimeResolutionResult)pr.Value).FutureValue;
                var pastDate   = (DateObject)((DateTimeResolutionResult)pr.Value).PastValue;

                ret.Timex = pr.TimexStr + timeStr;

                ret.FutureValue =
                    new Tuple <DateObject, DateObject>(
                        DateObject.MinValue.SafeCreateFromValue(futureDate.Year, futureDate.Month, futureDate.Day, beginHour, 0, 0),
                        DateObject.MinValue.SafeCreateFromValue(futureDate.Year, futureDate.Month, futureDate.Day, endHour, endMin, endMin));

                ret.PastValue =
                    new Tuple <DateObject, DateObject>(
                        DateObject.MinValue.SafeCreateFromValue(pastDate.Year, pastDate.Month, pastDate.Day, beginHour, 0, 0),
                        DateObject.MinValue.SafeCreateFromValue(pastDate.Year, pastDate.Month, pastDate.Day, endHour, endMin, endMin));

                ret.Success = true;

                return(ret);
            }

            return(ret);
        }
コード例 #24
0
        // handle like "前两年" "前三个月"
        private DateTimeResolutionResult ParseNumberWithUnit(string text, DateObject referenceDate)
        {
            var ret = new DateTimeResolutionResult();

            string numStr, unitStr;

            // if there are NO spaces between number and unit
            var match = DatePeriodExtractorChs.NumberCombinedWithUnit.Match(text);

            if (match.Success)
            {
                var srcUnit   = match.Groups["unit"].Value.ToLowerInvariant();
                var beforeStr = text.Substring(0, match.Index).Trim().ToLowerInvariant();
                if (this.config.UnitMap.ContainsKey(srcUnit))
                {
                    unitStr = this.config.UnitMap[srcUnit];
                    numStr  = match.Groups["num"].Value;

                    var prefixMatch = DatePeriodExtractorChs.PastRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "D":
                            beginDate = referenceDate.AddDays(-double.Parse(numStr));
                            endDate   = referenceDate;
                            break;

                        case "W":
                            beginDate = referenceDate.AddDays(-7 * double.Parse(numStr));
                            endDate   = referenceDate;
                            break;

                        case "MON":
                            beginDate = referenceDate.AddMonths(-Convert.ToInt32(double.Parse(numStr)));
                            endDate   = referenceDate;
                            break;

                        case "Y":
                            beginDate = referenceDate.AddYears(-Convert.ToInt32(double.Parse(numStr)));
                            endDate   = referenceDate;
                            break;

                        default:
                            return(ret);
                        }

                        ret.Timex       = $"({FormatUtil.LuisDate(beginDate)},{FormatUtil.LuisDate(endDate)},P{numStr}{unitStr[0]})";
                        ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginDate, endDate);
                        ret.Success     = true;
                        return(ret);
                    }

                    prefixMatch = DatePeriodExtractorChs.FutureRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "D":
                            beginDate = referenceDate;
                            endDate   = referenceDate.AddDays(double.Parse(numStr));
                            break;

                        case "W":
                            beginDate = referenceDate;
                            endDate   = referenceDate.AddDays(7 * double.Parse(numStr));
                            break;

                        case "MON":
                            beginDate = referenceDate;
                            endDate   = referenceDate.AddMonths(Convert.ToInt32(double.Parse(numStr)));
                            break;

                        case "Y":
                            beginDate = referenceDate;
                            endDate   = referenceDate.AddYears(Convert.ToInt32(double.Parse(numStr)));
                            break;

                        default:
                            return(ret);
                        }

                        ret.Timex =
                            $"({FormatUtil.LuisDate(beginDate.AddDays(1))},{FormatUtil.LuisDate(endDate.AddDays(1))},P{numStr}{unitStr[0]})";
                        ret.FutureValue   =
                            ret.PastValue = new Tuple <DateObject, DateObject>(beginDate.AddDays(1), endDate.AddDays(1));
                        ret.Success       = true;
                        return(ret);
                    }
                }
            }

            // for case "前两年" "后三年"
            var durationRes = Durationextractor.Extract(text, referenceDate);

            if (durationRes.Count > 0)
            {
                var beforeStr = text.Substring(0, (int)durationRes[0].Start).Trim().ToLowerInvariant();
                match = DatePeriodExtractorChs.UnitRegex.Match(durationRes[0].Text);
                if (match.Success)
                {
                    var srcUnit   = match.Groups["unit"].Value.ToLowerInvariant();
                    var numberStr = durationRes[0].Text.Substring(0, match.Index).Trim().ToLowerInvariant();
                    var number    = ConvertChineseToNum(numberStr);
                    if (this.config.UnitMap.ContainsKey(srcUnit))
                    {
                        unitStr = this.config.UnitMap[srcUnit];
                        numStr  = number.ToString();
                        var prefixMatch = DatePeriodExtractorChs.PastRegex.Match(beforeStr);
                        if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                        {
                            DateObject beginDate, endDate;
                            switch (unitStr)
                            {
                            case "D":
                                beginDate = referenceDate.AddDays(-double.Parse(numStr));
                                endDate   = referenceDate;
                                break;

                            case "W":
                                beginDate = referenceDate.AddDays(-7 * double.Parse(numStr));
                                endDate   = referenceDate;
                                break;

                            case "MON":
                                beginDate = referenceDate.AddMonths(-Convert.ToInt32(double.Parse(numStr)));
                                endDate   = referenceDate;
                                break;

                            case "Y":
                                beginDate = referenceDate.AddYears(-Convert.ToInt32(double.Parse(numStr)));
                                endDate   = referenceDate;
                                break;

                            default:
                                return(ret);
                            }

                            ret.Timex       = $"({FormatUtil.LuisDate(beginDate)},{FormatUtil.LuisDate(endDate)},P{numStr}{unitStr[0]})";
                            ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginDate, endDate);
                            ret.Success     = true;
                            return(ret);
                        }

                        prefixMatch = DatePeriodExtractorChs.FutureRegex.Match(beforeStr);
                        if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                        {
                            DateObject beginDate, endDate;
                            switch (unitStr)
                            {
                            case "D":
                                beginDate = referenceDate;
                                endDate   = referenceDate.AddDays(double.Parse(numStr));
                                break;

                            case "W":
                                beginDate = referenceDate;
                                endDate   = referenceDate.AddDays(7 * double.Parse(numStr));
                                break;

                            case "MON":
                                beginDate = referenceDate;
                                endDate   = referenceDate.AddMonths(Convert.ToInt32(double.Parse(numStr)));
                                break;

                            case "Y":
                                beginDate = referenceDate;
                                endDate   = referenceDate.AddYears(Convert.ToInt32(double.Parse(numStr)));
                                break;

                            default:
                                return(ret);
                            }

                            ret.Timex =
                                $"({FormatUtil.LuisDate(beginDate.AddDays(1))},{FormatUtil.LuisDate(endDate.AddDays(1))},P{numStr}{unitStr[0]})";
                            ret.FutureValue   =
                                ret.PastValue =
                                    new Tuple <DateObject, DateObject>(beginDate.AddDays(1), endDate.AddDays(1));
                            ret.Success = true;
                            return(ret);
                        }
                    }
                }
            }
            return(ret);
        }
コード例 #25
0
        // match several other cases
        // including '今天', '后天', '十三日'
        protected DateTimeResolutionResult ParseImplicitDate(string text, DateObject referenceDate)
        {
            var trimedText = text.Trim();

            var ret = new DateTimeResolutionResult();

            int[] containsDay = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

            // handle "十二日" "明年这个月三日" "本月十一日"
            var match = DateExtractorChs.SpecialDate.Match(trimedText);

            if (match.Success && match.Length == trimedText.Length)
            {
                int day = 0, month = referenceDate.Month, year = referenceDate.Year;
                var yearStr  = match.Groups["thisyear"].Value.ToLower();
                var monthStr = match.Groups["thismonth"].Value.ToLower();
                var dayStr   = match.Groups["day"].Value.ToLower();
                day = this.config.DayOfMonth[dayStr];
                bool hasYear = false, hasMonth = false;

                if (!string.IsNullOrEmpty(monthStr))
                {
                    hasMonth = true;
                    if (DateExtractorChs.NextRe.Match(monthStr).Success)
                    {
                        month++;
                        if (month == 13)
                        {
                            month = 1;
                            year++;
                        }
                    }
                    else if (DateExtractorChs.LastRe.Match(monthStr).Success)
                    {
                        month--;
                        if (month == 0)
                        {
                            month = 12;
                            year--;
                        }
                    }

                    if (!string.IsNullOrEmpty(yearStr))
                    {
                        hasYear = true;
                        if (DateExtractorChs.NextRe.Match(yearStr).Success)
                        {
                            ++year;
                        }
                        else if (DateExtractorChs.LastRe.Match(yearStr).Success)
                        {
                            --year;
                        }
                    }
                }

                ret.Timex = FormatUtil.LuisDate(hasYear ? year : -1, hasMonth ? month : -1, day);

                var futureDate = DateObject.MinValue;
                var pastDate   = DateObject.MinValue;
                if (day > containsDay[month - 1])
                {
                    futureDate = new DateObject(year, month + 1, day);
                    pastDate   = new DateObject(year, month - 1, day);
                }
                else
                {
                    futureDate = new DateObject(year, month, day);
                    pastDate   = new DateObject(year, month, day);
                    if (!hasMonth)
                    {
                        if (futureDate < referenceDate)
                        {
                            futureDate = futureDate.AddMonths(+1);
                        }

                        if (pastDate >= referenceDate)
                        {
                            pastDate = pastDate.AddMonths(-1);
                        }
                    }
                    else if (hasMonth && !hasYear)
                    {
                        if (futureDate < referenceDate)
                        {
                            futureDate = futureDate.AddYears(+1);
                        }

                        if (pastDate >= referenceDate)
                        {
                            pastDate = pastDate.AddYears(-1);
                        }
                    }
                }

                ret.FutureValue = futureDate;
                ret.PastValue   = pastDate;
                ret.Success     = true;

                return(ret);
            }

            // handle "today", "the day before yesterday"
            match = DateExtractorChs.SpecialDayRegex.Match(trimedText);
            if (match.Success && match.Index == 0 && match.Length == trimedText.Length)
            {
                var value = referenceDate;
                if (match.Value.ToLower().Equals("今天") || match.Value.ToLower().Equals("今日") ||
                    match.Value.ToLower().Equals("最近"))
                {
                    value = referenceDate;
                }
                else if (match.Value.ToLower().Equals("明天") || match.Value.ToLower().Equals("明日"))
                {
                    value = referenceDate.AddDays(1);
                }
                else if (match.Value.ToLower().Equals("昨天"))
                {
                    value = referenceDate.AddDays(-1);
                }
                else if (match.Value.ToLower().EndsWith("后天"))
                {
                    value = referenceDate.AddDays(2);
                }
                else if (match.Value.ToLower().EndsWith("前天"))
                {
                    value = referenceDate.AddDays(-2);
                }

                ret.Timex       = FormatUtil.LuisDate(value);
                ret.FutureValue = ret.PastValue = value;
                ret.Success     = true;

                return(ret);
            }

            if (!ret.Success)
            {
                ret = MatchThisWeekday(text, referenceDate);
            }

            if (!ret.Success)
            {
                ret = MatchLastWeekday(text, referenceDate);
            }

            if (!ret.Success)
            {
                ret = MatchWeekdayAlone(text, referenceDate);
            }

            return(ret);
        }
コード例 #26
0
        // case like "三月的第一周"
        private DateTimeResolutionResult ParseWeekOfMonth(string text, DateObject referenceDate)
        {
            var ret        = new DateTimeResolutionResult();
            var trimedText = text.Trim().ToLowerInvariant();
            var match      = DatePeriodExtractorChs.WeekOfMonthRegex.Match(text);

            if (!match.Success)
            {
                return(ret);
            }

            var cardinalStr = match.Groups["cardinal"].Value;
            var monthStr    = match.Groups["month"].Value;
            var noYear      = false;
            int year;

            int cardinal;

            if (cardinalStr.Equals("最后一"))
            {
                cardinal = 5;
            }
            else
            {
                cardinal = this.config.CardinalMap[cardinalStr];
            }

            int month;

            if (string.IsNullOrEmpty(monthStr))
            {
                var swift = 0;
                if (trimedText.StartsWith("下个"))
                {
                    swift = 1;
                }
                else if (trimedText.StartsWith("上个"))
                {
                    swift = -1;
                }
                month     = referenceDate.AddMonths(swift).Month;
                year      = referenceDate.AddMonths(swift).Year;
                ret.Timex = referenceDate.Year.ToString("D4") + "-" + month.ToString("D2");
            }
            else
            {
                month     = this.config.MonthOfYear[monthStr];
                ret.Timex = "XXXX" + "-" + month.ToString("D2");
                year      = referenceDate.Year;
                noYear    = true;
            }

            var value = ComputeDate(cardinal, 1, month, year);

            var futureDate = value;
            var pastDate   = value;

            if (noYear && futureDate < referenceDate)
            {
                futureDate = ComputeDate(cardinal, 1, month, year + 1);
                if (futureDate.Month != month)
                {
                    futureDate = futureDate.AddDays(-7);
                }
            }

            if (noYear && pastDate >= referenceDate)
            {
                pastDate = ComputeDate(cardinal, 1, month, year - 1);
                if (pastDate.Month != month)
                {
                    pastDate = pastDate.AddDays(-7);
                }
            }

            ret.Timex      += "-W" + cardinal.ToString("D2");
            ret.FutureValue = new Tuple <DateObject, DateObject>(futureDate, futureDate.AddDays(7));
            ret.PastValue   = new Tuple <DateObject, DateObject>(pastDate, pastDate.AddDays(7));
            ret.Success     = true;

            return(ret);
        }
コード例 #27
0
ファイル: DateParser.cs プロジェクト: warnov/Recognizers-Text
        protected virtual DateTimeResolutionResult ParseWeekdayOfMonth(string text, DateObject referenceDate)
        {
            var ret = new DateTimeResolutionResult();

            var trimedText = text.Trim().ToLowerInvariant();
            var match      = this.config.WeekDayOfMonthRegex.Match(trimedText);

            if (!match.Success)
            {
                return(ret);
            }

            var cardinalStr = match.Groups["cardinal"].Value;
            var weekdayStr  = match.Groups["weekday"].Value;
            var monthStr    = match.Groups["month"].Value;
            var noYear      = false;
            int year;

            int cardinal;

            if (cardinalStr.Equals(this.config.LastWeekDayToken))
            {
                cardinal = 5;
            }
            else
            {
                cardinal = this.config.CardinalMap[cardinalStr];
            }

            var weekday = this.config.DayOfWeek[weekdayStr];
            int month;

            if (string.IsNullOrEmpty(monthStr))
            {
                var swift = 0;
                if (trimedText.StartsWith(this.config.NextMonthToken))
                {
                    swift = 1;
                }
                else if (trimedText.StartsWith(this.config.LastMonthToken))
                {
                    swift = -1;
                }
                month = referenceDate.AddMonths(swift).Month;
                year  = referenceDate.AddMonths(swift).Year;
            }
            else
            {
                month  = this.config.MonthOfYear[monthStr];
                year   = referenceDate.Year;
                noYear = true;
            }

            var value = ComputeDate(cardinal, weekday, month, year);

            if (value.Month != month)
            {
                cardinal -= 1;
                value     = value.AddDays(-7);
            }

            var futureDate = value;
            var pastDate   = value;

            if (noYear && futureDate < referenceDate)
            {
                futureDate = ComputeDate(cardinal, weekday, month, year + 1);
                if (futureDate.Month != month)
                {
                    futureDate = futureDate.AddDays(-7);
                }
            }

            if (noYear && pastDate >= referenceDate)
            {
                pastDate = ComputeDate(cardinal, weekday, month, year - 1);
                if (pastDate.Month != month)
                {
                    pastDate = pastDate.AddDays(-7);
                }
            }

            // here is a very special case, timeX followe future date
            ret.Timex       = $@"XXXX-{month:D2}-WXX-{weekday}-#{cardinal}";
            ret.FutureValue = futureDate;
            ret.PastValue   = pastDate;
            ret.Success     = true;

            return(ret);
        }
コード例 #28
0
        private DateTimeResolutionResult Match2Date(Match match, DateObject referenceDate)
        {
            var ret        = new DateTimeResolutionResult();
            var holidayStr = this.config.SanitizeHolidayToken(match.Groups["holiday"].Value);

            // get year (if exist)
            var yearStr  = match.Groups["year"].Value;
            var orderStr = match.Groups["order"].Value;
            int year;
            var hasYear = false;

            if (!string.IsNullOrEmpty(yearStr))
            {
                year    = int.Parse(yearStr);
                hasYear = true;
            }
            else if (!string.IsNullOrEmpty(orderStr))
            {
                var swift = this.config.GetSwiftYear(orderStr);
                if (swift < -1)
                {
                    return(ret);
                }

                year    = referenceDate.Year + swift;
                hasYear = true;
            }
            else
            {
                year = referenceDate.Year;
            }

            string holidayKey = string.Empty;

            foreach (var holidayPair in this.config.HolidayNames)
            {
                if (holidayPair.Value.Contains(holidayStr))
                {
                    holidayKey = holidayPair.Key;
                    break;
                }
            }

            var timexStr = string.Empty;

            if (!string.IsNullOrEmpty(holidayKey))
            {
                DateObject value;
                if (FixedHolidaysDict.ContainsKey(holidayKey))
                {
                    value    = FixedHolidaysDict[holidayKey](year);
                    timexStr = $"-{value.Month:D2}-{value.Day:D2}";
                }
                else
                {
                    if (HolidayFuncDict.ContainsKey(holidayKey))
                    {
                        value = HolidayFuncDict[holidayKey](year);
                        if (hasYear)
                        {
                            timexStr = $"-{value.Month:D2}-{value.Day:D2}";
                        }
                    }
                    else
                    {
                        return(ret);
                    }
                }

                if (hasYear)
                {
                    ret.Timex       = year.ToString("D4") + timexStr;
                    ret.FutureValue = ret.PastValue = DateObject.MinValue.SafeCreateFromValue(year, value.Month, value.Day);
                    ret.Success     = true;
                    return(ret);
                }

                ret.Timex       = "XXXX" + timexStr;
                ret.FutureValue = GetFutureValue(value, referenceDate, holidayKey);
                ret.PastValue   = GetPastValue(value, referenceDate, holidayKey);
                ret.Success     = true;
                return(ret);
            }

            return(ret);
        }
コード例 #29
0
ファイル: DateParser.cs プロジェクト: warnov/Recognizers-Text
        // parse a regex match which includes 'day', 'month' and 'year' (optional) group
        protected DateTimeResolutionResult Match2Date(Match match, DateObject referenceDate)
        {
            var ret = new DateTimeResolutionResult();

            var monthStr = match.Groups["month"].Value.ToLower();
            var dayStr = match.Groups["day"].Value.ToLower();
            var yearStr = match.Groups["year"].Value.ToLower();
            var yearChsStr = match.Groups["yearchs"].Value.ToLower();
            int month = 0, day = 0, year = 0;

            var tmp = ConvertChineseYearToInteger(yearChsStr);

            year = tmp == -1 ? 0 : tmp;

            if (this.config.MonthOfYear.ContainsKey(monthStr) && this.config.DayOfMonth.ContainsKey(dayStr))
            {
                month = this.config.MonthOfYear[monthStr] > 12 ? this.config.MonthOfYear[monthStr] % 12 : this.config.MonthOfYear[monthStr];
                day   = this.config.DayOfMonth[dayStr] > 31 ? this.config.DayOfMonth[dayStr] % 31 : this.config.DayOfMonth[dayStr];
                if (!string.IsNullOrEmpty(yearStr))
                {
                    year = int.Parse(yearStr);
                    if (year < 100 && year >= Constants.MinTwoDigitYearPastNum)
                    {
                        year += 1900;
                    }
                    else if (year >= 0 && year < Constants.MaxTwoDigitYearFutureNum)
                    {
                        year += 2000;
                    }
                }
            }

            var noYear = false;

            if (year == 0)
            {
                year      = referenceDate.Year;
                ret.Timex = FormatUtil.LuisDate(-1, month, day);
                noYear    = true;
            }
            else
            {
                ret.Timex = FormatUtil.LuisDate(year, month, day);
            }

            var futureDate = DateObject.MinValue.SafeCreateFromValue(year, month, day);
            var pastDate   = DateObject.MinValue.SafeCreateFromValue(year, month, day);

            if (noYear && futureDate < referenceDate)
            {
                futureDate = futureDate.AddYears(+1);
            }

            if (noYear && pastDate >= referenceDate)
            {
                pastDate = pastDate.AddYears(-1);
            }

            ret.FutureValue = futureDate;
            ret.PastValue   = pastDate;
            ret.Success     = true;

            return(ret);
        }
コード例 #30
0
        public static DateTimeResolutionResult Handle(IDateTimeParser timeParser, DateTimeExtra <PeriodType> extra, DateObject refTime)
        {
            //Left is a time
            var        left = extra.NamedEntity["left"];
            TimeResult leftResult, rightResult = null;

            // 下午四点十分到五点十分
            if (extra.Type == PeriodType.FullTime)
            {
                var leftExtract = new ExtractResult
                {
                    Start  = left.Index,
                    Length = left.Length,
                    Text   = left.Value,
                    Type   = Constants.SYS_DATETIME_TIME
                };
                leftResult = timeParser.Parse(leftExtract, refTime).Data as TimeResult;
            }
            else
            {
                // 下午四到五点
                leftResult = TimeFunctions.GetShortLeft(left.Value);
            }

            //Right is a time
            var right        = extra.NamedEntity["right"];
            var rightExtract = new ExtractResult
            {
                Start  = right.Index,
                Length = right.Length,
                Text   = right.Value,
                Type   = Constants.SYS_DATETIME_TIME
            };

            rightResult = timeParser.Parse(rightExtract, refTime).Data as TimeResult;

            var ret = new DateTimeResolutionResult()
            {
                Success = true
            };

            //the right side doesn't contain desc while the left side does
            if (rightResult.LowBound == -1 && leftResult.LowBound != -1 && rightResult.Hour <= leftResult.LowBound)
            {
                rightResult.Hour += 12;
            }

            int day   = refTime.Day,
                month = refTime.Month,
                year  = refTime.Year;

            //determine if the right side time is smaller than the left side, if yes, add one day
            int hour   = leftResult.Hour > 0 ? leftResult.Hour : 0,
                min    = leftResult.Minute > 0 ? leftResult.Minute : 0,
                second = leftResult.Second > 0 ? leftResult.Second : 0;

            var leftTime = DateObject.MinValue.SafeCreateFromValue(year, month, day, hour, min, second);

            hour   = rightResult.Hour > 0 ? rightResult.Hour : 0;
            min    = rightResult.Minute > 0 ? rightResult.Minute : 0;
            second = rightResult.Second > 0 ? rightResult.Second : 0;

            var rightTime = DateObject.MinValue.SafeCreateFromValue(year, month, day, hour, min, second);

            if (rightTime.Hour < leftTime.Hour)
            {
                rightTime = rightTime.AddDays(1);
            }

            ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(leftTime, rightTime);

            var leftTimex  = BuildTimex(leftResult);
            var rightTimex = BuildTimex(rightResult);

            ret.Timex = $"({leftTimex},{rightTimex},{BuildSpan(leftResult, rightResult)})";
            return(ret);
        }