示例#1
0
        protected virtual DTParseResult ParseWeekdayOfMonth(string text, DateObject referenceDate)
        {
            var ret = new DTParseResult();

            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.ToString("D2")}-WXX-{weekday}-#{cardinal}";
            ret.FutureValue = futureDate;
            ret.PastValue   = pastDate;
            ret.Success     = true;

            return(ret);
        }
示例#2
0
        // handle like "三天前"
        private DTParseResult ParserDurationWithBeforeAndAfter(string text, DateObject referenceDate)
        {
            var ret          = new DTParseResult();
            var duration_res = durationExtractor.Extract(text);
            var numStr       = string.Empty;
            var unitStr      = string.Empty;

            if (duration_res.Count > 0)
            {
                var match = DateExtractorChs.UnitRegex.Match(text);
                if (match.Success)
                {
                    var AfterStr =
                        text.Substring((int)duration_res[0].Start + (int)duration_res[0].Length, 1)
                        .Trim()
                        .ToLowerInvariant();
                    var srcUnit   = match.Groups["unit"].Value.ToLowerInvariant();
                    var numberStr =
                        text.Substring((int)duration_res[0].Start, match.Index - (int)duration_res[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       = $"{Util.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 =
                                $"{Util.LuisDate(Date)}";
                            ret.FutureValue   =
                                ret.PastValue = Date;
                            ret.Success       = true;
                            return(ret);
                        }
                    }
                }
            }
            return(ret);
        }
        protected override DTParseResult ParseSpecificNight(string text, DateObject referenceTime)
        {
            var ret        = new DTParseResult();
            var trimedText = text.Trim().ToLowerInvariant();
            // handle morning, afternoon..
            int beginHour, endHour, endMin = 0;
            var timeStr = string.Empty;

            if (!this.config.GetMatchedTimeRange(trimedText, out timeStr, out beginHour, out endHour, out endMin))
            {
                return(ret);
            }

            var match = this.config.SpecificNightRegex.Match(trimedText);

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

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

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

            var startIndex = trimedText.IndexOf("mañana") == 0 ? 6 : 0;

            // handle Date followed by morning, afternoon
            match = this.config.NightRegex.Match(trimedText.Substring(startIndex));
            if (match.Success)
            {
                var beforeStr = trimedText.Substring(0, match.Index + startIndex).Trim();
                var ers       = this.config.DateExtractor.Extract(beforeStr);
                if (ers.Count == 0)
                {
                    return(ret);
                }
                var pr         = this.config.DateParser.Parse(ers[0], referenceTime);
                var futureDate = (DateObject)((DTParseResult)pr.Value).FutureValue;
                var pastDate   = (DateObject)((DTParseResult)pr.Value).PastValue;
                ret.Timex       = pr.TimexStr + timeStr;
                ret.FutureValue =
                    new Tuple <DateObject, DateObject>(
                        new DateObject(futureDate.Year, futureDate.Month, futureDate.Day, beginHour, 0, 0),
                        new DateObject(futureDate.Year, futureDate.Month, futureDate.Day, endHour, endMin, endMin));
                ret.PastValue =
                    new Tuple <DateObject, DateObject>(
                        new DateObject(pastDate.Year, pastDate.Month, pastDate.Day, beginHour, 0, 0),
                        new DateObject(pastDate.Year, pastDate.Month, pastDate.Day, endHour, endMin, endMin));
                ret.Success = true;
                return(ret);
            }

            return(ret);
        }
示例#4
0
        // match several other cases
        // including '今天', '后天', '十三日'
        protected DTParseResult ParseImplicitDate(string text, DateObject referenceDate)
        {
            var trimedText = text.Trim();

            var ret = new DTParseResult();

            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 = Util.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       = Util.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);
        }
示例#5
0
        // case like "三月的第一周"
        private DTParseResult ParseWeekOfMonth(string text, DateObject referenceDate)
        {
            var ret        = new DTParseResult();
            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);
        }
示例#6
0
        // parse "今年夏天"
        private DTParseResult ParseSeason(string text, DateObject referenceDate)
        {
            var ret   = new DTParseResult();
            var match = DatePeriodExtractorChs.SeasonWithYear.Match(text);

            if (match.Success && match.Length == text.Length)
            {
                // pare 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);
        }
示例#7
0
        // only contains year like "2016年"
        private static DTParseResult ParseYear(string text, DateObject referenceDate)
        {
            var ret   = new DTParseResult();
            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 = new DateObject(year, 1, 1);
                var endDay   = new DateObject(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 = new DateObject(year, 1, 1);
                var endDay   = new DateObject(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);
        }
        private static DTParseResult Match2Date(Match match, DateObject referenceDate)
        {
            var ret        = new DTParseResult();
            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;
            }

            var timexStr = string.Empty;

            if (!string.IsNullOrEmpty(holidayStr))
            {
                DateObject value;
                if (FixedHolidaysDict.ContainsKey(holidayStr))
                {
                    value    = FixedHolidaysDict[holidayStr];
                    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 = new DateObject(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);
        }
示例#9
0
        // for case "2016年5月"
        private DTParseResult ParseYearAndMonth(string text, DateObject referenceDate)
        {
            var ret   = new DTParseResult();
            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 = new DateObject(year, month, 1);
            var endDay   = new DateObject();

            if (month == 12)
            {
                endDay = new DateObject(year + 1, 1, 1);
            }
            else
            {
                endDay = new DateObject(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);
        }
示例#10
0
        // case like "今年三月" "这个周末" "五月"
        private DTParseResult ParseOneWordPeriod(string text, DateObject referenceDate)
        {
            var ret = new DTParseResult();
            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>(new DateObject(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.FirstDay, 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("周末"))
                    {
                        DateObject beginDate, endDate;
                        beginDate = referenceDate.This(DayOfWeek.Saturday).AddDays(7 * swift);
                        endDate   = referenceDate.This(DayOfWeek.Sunday).AddDays(7 * swift);

                        ret.Timex = beginDate.Year.ToString("D4") + "-W" +
                                    _cal.GetWeekOfYear(beginDate, CalendarWeekRule.FirstDay, 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>(new DateObject(year, 1, 1),
                                                                   new DateObject(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>(
                new DateObject(futureYear, month, 1),
                new DateObject(futureYear, month, 1).AddMonths(1));
            ret.PastValue = new Tuple <DateObject, DateObject>(
                new DateObject(pastYear, month, 1),
                new DateObject(pastYear, month, 1).AddMonths(1));
            ret.Success = true;
            return(ret);
        }
示例#11
0
        // handle like "2016年到2017年"
        private static DTParseResult ParseYearToYear(string text, DateObject referenceDate)
        {
            var ret   = new DTParseResult();
            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   = new DateObject(BeginYear, 1, 1);
                var endDay     = new DateObject(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);
        }
示例#12
0
        private DTParseResult ParseSimpleCases(string text, DateObject referenceDate)
        {
            var ret = new DTParseResult();
            int year = referenceDate.Year, month = referenceDate.Month;
            int beginDay = referenceDate.Day, endDay = referenceDate.Day;
            var noYear    = false;
            var inputYear = false;

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

            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 = Util.LuisDate(year, month, beginDay);
                    endLuisStr   = Util.LuisDate(year, month, endDay);
                }
                else
                {
                    beginLuisStr = Util.LuisDate(-1, month, beginDay);
                    endLuisStr   = Util.LuisDate(-1, month, endDay);
                }
            }
            else
            {
                return(ret);
            }

            int futureYear = year, pastYear = year;
            var startDate = new DateObject(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>(
                new DateObject(futureYear, month, beginDay),
                new DateObject(futureYear, month, endDay));
            ret.PastValue = new Tuple <DateObject, DateObject>(
                new DateObject(pastYear, month, beginDay),
                new DateObject(pastYear, month, endDay));
            ret.Success = true;

            return(ret);
        }
示例#13
0
        private DTParseResult ParseQuarter(string text, DateObject referenceDate)
        {
            var ret   = new DTParseResult();
            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 = new DateObject(year, quarterNum * 3 - 2, 1);
            var endDate   = new DateObject(year, quarterNum * 3 + 1, 1);

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

            return(ret);
        }
示例#14
0
        // parse a regex match which includes 'day', 'month' and 'year' (optional) group
        protected DTParseResult Match2Date(Match match, DateObject referenceDate)
        {
            var ret = new DTParseResult();

            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 >= 90)
                    {
                        year += 1900;
                    }
                    else if (year < 100 && year < 20)
                    {
                        year += 2000;
                    }
                }
            }

            var noYear = false;

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

            var futureDate = new DateObject(year, month, day);
            var pastDate   = new DateObject(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);
        }
示例#15
0
        // handle like "前两年" "前三个月"
        private DTParseResult ParseNumberWithUnit(string text, DateObject referenceDate)
        {
            var ret = new DTParseResult();

            var numStr  = string.Empty;
            var unitStr = string.Empty;

            // 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       = $"({Util.LuisDate(beginDate)},{Util.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 =
                            $"({Util.LuisDate(beginDate.AddDays(1))},{Util.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 duration_res = durationextractor.Extract(text);

            if (duration_res.Count > 0)
            {
                var beforeStr = text.Substring(0, (int)duration_res[0].Start).Trim().ToLowerInvariant();
                match = DatePeriodExtractorChs.UnitRegex.Match(duration_res[0].Text);
                if (match.Success)
                {
                    var srcUnit   = match.Groups["unit"].Value.ToLowerInvariant();
                    var numberStr = duration_res[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       = $"({Util.LuisDate(beginDate)},{Util.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 =
                                $"({Util.LuisDate(beginDate.AddDays(1))},{Util.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);
        }
示例#16
0
        // merge a Date entity and a Time entity
        private DTParseResult MergeDateAndTime(string text, DateObject referenceTime)
        {
            var ret = new DTParseResult();

            var er1 = _singleDateExtractor.Extract(text);

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

            var er2 = _singleTimeExtractor.Extract(text);

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


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

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

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

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

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

            var timeStr = pr2.TimexStr;

            if (timeStr.EndsWith("ampm"))
            {
                timeStr = timeStr.Substring(0, timeStr.Length - 4);
            }
            timeStr   = "T" + hour.ToString("D2") + timeStr.Substring(3);
            ret.Timex = pr1.TimexStr + timeStr;
            var Val = (DTParseResult)pr2.Value;

            if (hour <= 12 && !SimplePmRegex.IsMatch(text) && !SimpleAmRegex.IsMatch(text) &&
                !string.IsNullOrEmpty(Val.comment))
            {
                //ret.Timex += "ampm";
                ret.comment = "ampm";
            }
            ret.FutureValue = new DateObject(futureDate.Year, futureDate.Month, futureDate.Day, hour, min, sec);
            ret.PastValue   = new DateObject(pastDate.Year, pastDate.Month, pastDate.Day, hour, min, sec);
            ret.Success     = true;

            return(ret);
        }
        public static DTParseResult 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 DTParseResult()
            {
                Success = true
            };

            //右侧没有Desc,左侧有
            if (rightResult.LowBound == -1 && leftResult.LowBound != -1 && rightResult.Hour <= leftResult.LowBound)
            {
                rightResult.Hour += 12;
            }
            int day   = refTime.Day,
                month = refTime.Month,
                year  = refTime.Year;
            //判断右侧是否比小测的小,如果比左侧的小,则增加一天
            int hour   = leftResult.Hour > 0 ? leftResult.Hour : 0,
                min    = leftResult.Minute > 0 ? leftResult.Minute : 0,
                second = leftResult.Second > 0 ? leftResult.Second : 0;

            var leftTime = new DateObject(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 = new DateObject(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);
        }