Example #1
0
        private DateTimeResolutionResult ParseDuration(string text, DateObject referenceTime)
        {
            var ret = new DateTimeResolutionResult();
            var ers = config.DurationExtractor.Extract(text, referenceTime);

            if (ers.Count == 1)
            {
                var pr       = config.DurationParser.Parse(ers[0]);
                var afterStr = text.Substring((pr.Start ?? 0) + (pr.Length ?? 0)).Trim();

                if (pr.Value != null)
                {
                    var swiftSeconds   = 0;
                    var mod            = string.Empty;
                    var durationResult = (DateTimeResolutionResult)pr.Value;
                    if (durationResult.PastValue is double && durationResult.FutureValue is double)
                    {
                        swiftSeconds = (int)((double)durationResult.FutureValue);
                    }

                    DateObject beginTime;
                    var        endTime = beginTime = referenceTime;
                    var        match   = config.FutureRegex.Match(afterStr);

                    if (match.Groups[Constants.WithinGroupName].Success)
                    {
                        endTime = beginTime.AddSeconds(swiftSeconds);

                        ret.Timex = TimexUtility.GenerateDateTimePeriodTimex(beginTime, endTime, durationResult.Timex);

                        ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginTime, endTime);
                        ret.Success     = true;

                        if (!string.IsNullOrEmpty(mod))
                        {
                            ((DateTimeResolutionResult)pr.Value).Mod = mod;
                        }

                        ret.SubDateTimeEntities = new List <object> {
                            pr
                        };
                        return(ret);
                    }
                }
            }

            return(ret);
        }
        // Handle cases like "Monday 7-9", where "7-9" can't be extracted by the TimePeriodExtractor
        private DateTimeResolutionResult ParsePureNumberCases(string text, DateObject referenceTime)
        {
            var ret         = new DateTimeResolutionResult();
            var trimmedText = text.Trim().ToLower();

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

            if (!match.Success)
            {
                match = this.Config.PureNumberBetweenAndRegex.Match(trimmedText);
            }

            if (match.Success && (match.Index == 0 || match.Index + match.Length == trimmedText.Length))
            {
                int beginHour, endHour;
                ret.Comment = ParseTimePeriod(match, out beginHour, out endHour);

                var dateStr = string.Empty;

                // Parse following date
                var dateExtractResult = this.Config.DateExtractor.Extract(trimmedText.Replace(match.Value, ""), referenceTime);

                DateObject futureDate, pastDate;
                if (dateExtractResult.Count > 0)
                {
                    var pr = this.Config.DateParser.Parse(dateExtractResult[0], referenceTime);
                    if (pr.Value != null)
                    {
                        futureDate = (DateObject)((DateTimeResolutionResult)pr.Value).FutureValue;
                        pastDate   = (DateObject)((DateTimeResolutionResult)pr.Value).PastValue;

                        dateStr = pr.TimexStr;

                        if (((DateTimeResolutionResult)pr.Value).TimeZoneResolution != null)
                        {
                            ret.TimeZoneResolution = ((DateTimeResolutionResult)pr.Value).TimeZoneResolution;
                        }
                    }
                    else
                    {
                        return(ret);
                    }
                }
                else
                {
                    return(ret);
                }

                var pastHours     = endHour - beginHour;
                var beginTimex    = TimexUtility.CombineDateAndTimeTimex(dateStr, DateTimeFormatUtil.ShortTime(beginHour));
                var endTimex      = TimexUtility.CombineDateAndTimeTimex(dateStr, DateTimeFormatUtil.ShortTime(endHour));
                var durationTimex = TimexUtility.GenerateDurationTimex(endHour - beginHour, Constants.TimexHour, isLessThanDay: true);

                ret.Timex = TimexUtility.GenerateDateTimePeriodTimex(beginTimex, endTimex, durationTimex);

                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, 0, 0));

                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, 0, 0));

                ret.Success = true;
            }

            return(ret);
        }
        private DateTimeResolutionResult MergeDateWithSingleTimePeriod(string text, DateObject referenceTime)
        {
            var ret         = new DateTimeResolutionResult();
            var trimmedText = text.Trim().ToLower();

            var ers = Config.TimePeriodExtractor.Extract(trimmedText, referenceTime);

            if (ers.Count == 0)
            {
                return(ParsePureNumberCases(text, referenceTime));
            }
            else if (ers.Count == 1)
            {
                var timePeriodParseResult      = Config.TimePeriodParser.Parse(ers[0]);
                var timePeriodResolutionResult = (DateTimeResolutionResult)timePeriodParseResult.Value;

                if (timePeriodResolutionResult == null)
                {
                    return(ParsePureNumberCases(text, referenceTime));
                }

                if (timePeriodResolutionResult.TimeZoneResolution != null)
                {
                    ret.TimeZoneResolution = timePeriodResolutionResult.TimeZoneResolution;
                }

                var timePeriodTimex = timePeriodResolutionResult.Timex;

                // If it is a range type timex
                if (TimexUtility.IsRangeTimex(timePeriodTimex))
                {
                    var dateResult = this.Config.DateExtractor.Extract(trimmedText.Replace(ers[0].Text, ""), referenceTime);

                    var dateText = trimmedText.Replace(ers[0].Text, "").Replace(Config.TokenBeforeDate, "").Trim();

                    // If only one Date is extracted and the Date text equals to the rest part of source text
                    if (dateResult.Count == 1 && dateText.Equals(dateResult[0].Text))
                    {
                        string     dateTimex;
                        DateObject futureTime;
                        DateObject pastTime;

                        var pr = this.Config.DateParser.Parse(dateResult[0], referenceTime);

                        if (pr.Value != null)
                        {
                            futureTime = (DateObject)((DateTimeResolutionResult)pr.Value).FutureValue;
                            pastTime   = (DateObject)((DateTimeResolutionResult)pr.Value).PastValue;

                            dateTimex = pr.TimexStr;
                        }
                        else
                        {
                            return(ParsePureNumberCases(text, referenceTime));
                        }

                        var rangeTimexComponents = TimexUtility.GetRangeTimexComponents(timePeriodTimex);

                        if (rangeTimexComponents.IsValid)
                        {
                            var beginTimex = TimexUtility.CombineDateAndTimeTimex(dateTimex, rangeTimexComponents.BeginTimex);
                            var endTimex   = TimexUtility.CombineDateAndTimeTimex(dateTimex, rangeTimexComponents.EndTimex);
                            ret.Timex = TimexUtility.GenerateDateTimePeriodTimex(beginTimex, endTimex, rangeTimexComponents.DurationTimex);

                            var timePeriodFutureValue = (Tuple <DateObject, DateObject>)timePeriodResolutionResult.FutureValue;
                            var beginTime             = timePeriodFutureValue.Item1;
                            var endTime = timePeriodFutureValue.Item2;

                            ret.FutureValue = new Tuple <DateObject, DateObject>(
                                DateObject.MinValue.SafeCreateFromValue(futureTime.Year, futureTime.Month, futureTime.Day,
                                                                        beginTime.Hour, beginTime.Minute, beginTime.Second),
                                DateObject.MinValue.SafeCreateFromValue(futureTime.Year, futureTime.Month, futureTime.Day,
                                                                        endTime.Hour, endTime.Minute, endTime.Second)
                                );

                            ret.PastValue = new Tuple <DateObject, DateObject>(
                                DateObject.MinValue.SafeCreateFromValue(pastTime.Year, pastTime.Month, pastTime.Day,
                                                                        beginTime.Hour, beginTime.Minute, beginTime.Second),
                                DateObject.MinValue.SafeCreateFromValue(pastTime.Year, pastTime.Month, pastTime.Day,
                                                                        endTime.Hour, endTime.Minute, endTime.Second)
                                );

                            if (!string.IsNullOrEmpty(timePeriodResolutionResult.Comment) &&
                                timePeriodResolutionResult.Comment.Equals(Constants.Comment_AmPm))
                            {
                                // AmPm comment is used for later SetParserResult to judge whether this parse result should have two parsing results
                                // Cases like "from 10:30 to 11 on 1/1/2015" should have AmPm comment, as it can be parsed to "10:30am to 11am" and also be parsed to "10:30pm to 11pm"
                                // Cases like "from 10:30 to 3 on 1/1/2015" should not have AmPm comment
                                if (beginTime.Hour < Constants.HalfDayHourCount && endTime.Hour < Constants.HalfDayHourCount)
                                {
                                    ret.Comment = Constants.Comment_AmPm;
                                }
                            }

                            ret.Success             = true;
                            ret.SubDateTimeEntities = new List <object> {
                                pr, timePeriodParseResult
                            };

                            return(ret);
                        }
                    }

                    return(ParsePureNumberCases(text, referenceTime));
                }
            }

            return(ret);
        }
Example #4
0
        // Parse cases like "this night"
        private DateTimeResolutionResult ParseSpecificNight(string text, DateObject referenceTime)
        {
            var    ret = new DateTimeResolutionResult();
            var    trimmedText = text.Trim();
            int    beginHour, endHour, endMin = 0;
            string timeStr;

            // Handle 昨晚 (last night),今晨 (this morning)
            if (this.config.SpecificTimeOfDayRegex.IsExactMatch(trimmedText, trim: true))
            {
                // handle the ambiguous case "ぎりぎり" [the latest possible time]
                var latest = this.config.SpecificTimeOfDayRegex.Match(text);
                if (latest.Groups[Constants.LatestGroupName].Success)
                {
                    DateObject beginDate, endDate;
                    beginDate = referenceTime.AddMinutes(-1);
                    endDate   = referenceTime;
                    var diff = endDate - beginDate;
                    ret.Timex       = TimexUtility.GenerateDateTimePeriodTimex(beginDate, endDate);
                    ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginDate, endDate);
                    ret.Success     = true;
                    return(ret);
                }

                if (!this.config.GetMatchedTimeRangeAndSwift(trimmedText, out timeStr, out beginHour, out endHour, out endMin, out int swift))
                {
                    return(ret);
                }

                if (this.config.NextRegex.IsMatch(trimmedText))
                {
                    swift = 1;
                }
                else if (this.config.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 cases like morning, afternoon
            if (!this.config.GetMatchedTimeRange(trimmedText, out timeStr, out beginHour, out endHour, out endMin))
            {
                return(ret);
            }

            if (this.config.SpecificTimeOfDayRegex.IsExactMatch(trimmedText, trim: true))
            {
                var swift = 0;
                if (this.config.NextRegex.IsMatch(trimmedText))
                {
                    swift = 1;
                }
                else if (this.config.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 = this.config.TimeOfDayRegex.Match(trimmedText);

            if (match.Success)
            {
                var beforeStr = trimmedText.Substring(0, match.Index).Trim();
                var ers       = this.config.DateExtractor.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);
        }
Example #5
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 = this.config.TimeExtractor.Extract(text, referenceTime);
            var er2 = this.config.DateTimeExtractor.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);

            var match = config.FutureRegex.Match(text);

            // cases including 'within' are processed in ParseDuration
            if (match.Groups[Constants.WithinGroupName].Success)
            {
                return(ParseDuration(text, referenceTime));
            }

            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;

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

            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)
            {
                leftTime = DateObject.MinValue.SafeCreateFromValue(futureBegin.Year, futureBegin.Month, futureBegin.Day);
            }
            else if (endHasDate)
            {
                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;

            // 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).AddMinutes(min).AddSeconds(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).AddMinutes(min).AddSeconds(second);

            // the right side time contains "ampm", while the left side doesn't
            if (rightResult.Comment is 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  = pr1.TimexStr;
            var rightTimex = pr2.TimexStr;

            if (beginHasDate)
            {
                rightTimex = DateTimeFormatUtil.LuisDateShortTime(rightTime, pr2.TimexStr);
            }
            else if (endHasDate)
            {
                leftTimex = DateTimeFormatUtil.LuisDateShortTime(leftTime, pr1.TimexStr);
            }

            ret.Timex   = TimexUtility.GenerateDateTimePeriodTimex(leftTimex, rightTimex, rightTime - leftTime);
            ret.Success = true;
            return(ret);
        }