Пример #1
0
        // Cases like "from 3:30 to 5" or "between 3:30am to 6pm", at least one of the time point contains colon
        private DateTimeResolutionResult ParseSpecificTimeCases(string text, DateObject referenceTime)
        {
            var ret = new DateTimeResolutionResult();
            int year = referenceTime.Year, month = referenceTime.Month, day = referenceTime.Day;
            var trimmedText = text.Trim().ToLower();

            // Handle cases like "from 4:30 to 5"
            var match = config.SpecificTimeFromToRegex.Match(text);

            if (!match.Success)
            {
                // Handle cases like "between 5:10 and 7"
                match = config.SpecificTimeBetweenAndRegex.Match(text);
            }

            if (match.Success && match.Index == 0 && match.Index + match.Length == trimmedText.Length)
            {
                // Cases like "half past seven" are not handled here
                if (match.Groups[Constants.PrefixGroupName].Success)
                {
                    return(ret);
                }

                // Cases like "4" is different with "4:00" as the Timex is different "T04H" vs "T04H00M"
                int beginHour;
                int beginMinute = Constants.InvalidMinute;
                int beginSecond = Constants.InvalidSecond;
                int endHour;
                int endMinute = Constants.InvalidMinute;
                int endSecond = Constants.InvalidSecond;

                // Get time1 and time2
                var hourGroup = match.Groups[Constants.HourGroupName];

                var hourStr = hourGroup.Captures[0].Value;

                if (config.Numbers.ContainsKey(hourStr))
                {
                    beginHour = config.Numbers[hourStr];
                }
                else
                {
                    beginHour = int.Parse(hourStr);
                }


                hourStr = hourGroup.Captures[1].Value;

                if (config.Numbers.ContainsKey(hourStr))
                {
                    endHour = config.Numbers[hourStr];
                }
                else
                {
                    endHour = int.Parse(hourStr);
                }

                var time1StartIndex = match.Groups["time1"].Index;
                var time1EndIndex   = time1StartIndex + match.Groups["time1"].Length;
                var time2StartIndex = match.Groups["time2"].Index;
                var time2EndIndex   = time2StartIndex + match.Groups["time2"].Length;

                // Get beginMinute (if exists) and endMinute (if exists)
                for (int i = 0; i < match.Groups[Constants.MinuteGroupName].Captures.Count; i++)
                {
                    var minuteCapture = match.Groups[Constants.MinuteGroupName].Captures[i];
                    if (minuteCapture.Index >= time1StartIndex && minuteCapture.Index + minuteCapture.Length <= time1EndIndex)
                    {
                        beginMinute = int.Parse(minuteCapture.Value);
                    }
                    else if (minuteCapture.Index >= time2StartIndex && minuteCapture.Index + minuteCapture.Length <= time2EndIndex)
                    {
                        endMinute = int.Parse(minuteCapture.Value);
                    }
                }

                // Get beginSecond (if exists) and endSecond (if exists)
                for (int i = 0; i < match.Groups[Constants.SecondGroupName].Captures.Count; i++)
                {
                    var secondCapture = match.Groups[Constants.SecondGroupName].Captures[i];
                    if (secondCapture.Index >= time1StartIndex && secondCapture.Index + secondCapture.Length <= time1EndIndex)
                    {
                        beginSecond = int.Parse(secondCapture.Value);
                    }
                    else if (secondCapture.Index >= time2StartIndex && secondCapture.Index + secondCapture.Length <= time2EndIndex)
                    {
                        endSecond = int.Parse(secondCapture.Value);
                    }
                }

                // Desc here means descriptions like "am / pm / o'clock"
                // Get leftDesc (if exists) and rightDesc (if exists)
                var leftDesc  = match.Groups["leftDesc"].Value;
                var rightDesc = match.Groups["rightDesc"].Value;

                for (int i = 0; i < match.Groups[Constants.DescGroupName].Captures.Count; i++)
                {
                    var descCapture = match.Groups[Constants.DescGroupName].Captures[i];
                    if (descCapture.Index >= time1StartIndex && descCapture.Index + descCapture.Length <= time1EndIndex && string.IsNullOrEmpty(leftDesc))
                    {
                        leftDesc = descCapture.Value;
                    }
                    else if (descCapture.Index >= time2StartIndex && descCapture.Index + descCapture.Length <= time2EndIndex && string.IsNullOrEmpty(rightDesc))
                    {
                        rightDesc = descCapture.Value;
                    }
                }

                var beginDateTime = DateObject.MinValue.SafeCreateFromValue(year, month, day, beginHour, beginMinute >= 0 ? beginMinute : 0, beginSecond >= 0 ? beginSecond : 0);
                var endDateTime   = DateObject.MinValue.SafeCreateFromValue(year, month, day, endHour, endMinute >= 0 ? endMinute : 0, endSecond >= 0 ? endSecond : 0);

                var hasLeftAm  = !string.IsNullOrEmpty(leftDesc) && leftDesc.ToLower().StartsWith("a");
                var hasLeftPm  = !string.IsNullOrEmpty(leftDesc) && leftDesc.ToLower().StartsWith("p");
                var hasRightAm = !string.IsNullOrEmpty(rightDesc) && rightDesc.ToLower().StartsWith("a");
                var hasRightPm = !string.IsNullOrEmpty(rightDesc) && rightDesc.ToLower().StartsWith("p");
                var hasLeft    = hasLeftAm || hasLeftPm;
                var hasRight   = hasRightAm || hasRightPm;

                // Both time point has description like 'am' or 'pm'
                if (hasLeft && hasRight)
                {
                    if (hasLeftAm)
                    {
                        if (beginHour >= Constants.HalfDayHourCount)
                        {
                            beginDateTime = beginDateTime.AddHours(-Constants.HalfDayHourCount);
                        }
                    }
                    else
                    {
                        if (beginHour < Constants.HalfDayHourCount)
                        {
                            beginDateTime = beginDateTime.AddHours(Constants.HalfDayHourCount);
                        }
                    }

                    if (hasRightAm)
                    {
                        if (endHour > Constants.HalfDayHourCount)
                        {
                            endDateTime = endDateTime.AddHours(-Constants.HalfDayHourCount);
                        }
                    }
                    else
                    {
                        if (endHour < Constants.HalfDayHourCount)
                        {
                            endDateTime = endDateTime.AddHours(Constants.HalfDayHourCount);
                        }
                    }
                }
                else if (hasLeft || hasRight)
                {
                    // one of the time point has description like 'am' or 'pm'
                    if (hasLeftAm)
                    {
                        if (beginHour >= Constants.HalfDayHourCount)
                        {
                            beginDateTime = beginDateTime.AddHours(-Constants.HalfDayHourCount);
                        }

                        if (endHour < Constants.HalfDayHourCount)
                        {
                            if (endDateTime < beginDateTime)
                            {
                                endDateTime = endDateTime.AddHours(Constants.HalfDayHourCount);
                            }
                        }
                    }
                    else if (hasLeftPm)
                    {
                        if (beginHour < Constants.HalfDayHourCount)
                        {
                            beginDateTime = beginDateTime.AddHours(Constants.HalfDayHourCount);
                        }

                        if (endHour < Constants.HalfDayHourCount)
                        {
                            if (endDateTime < beginDateTime)
                            {
                                var span = beginDateTime - endDateTime;
                                endDateTime = endDateTime.AddHours(span.TotalHours >= Constants.HalfDayHourCount ?
                                                                   24 :
                                                                   Constants.HalfDayHourCount);
                            }
                        }
                    }

                    if (hasRightAm)
                    {
                        if (endHour >= Constants.HalfDayHourCount)
                        {
                            endDateTime = endDateTime.AddHours(-Constants.HalfDayHourCount);
                        }

                        if (beginHour < Constants.HalfDayHourCount)
                        {
                            if (endDateTime < beginDateTime)
                            {
                                beginDateTime = beginDateTime.AddHours(-Constants.HalfDayHourCount);
                            }
                        }
                    }
                    else if (hasRightPm)
                    {
                        if (endHour < Constants.HalfDayHourCount)
                        {
                            endDateTime = endDateTime.AddHours(Constants.HalfDayHourCount);
                        }

                        if (beginHour < Constants.HalfDayHourCount)
                        {
                            if (endDateTime < beginDateTime)
                            {
                                beginDateTime = beginDateTime.AddHours(-Constants.HalfDayHourCount);
                            }
                            else
                            {
                                var span = endDateTime - beginDateTime;
                                if (span.TotalHours > Constants.HalfDayHourCount)
                                {
                                    beginDateTime = beginDateTime.AddHours(Constants.HalfDayHourCount);
                                }
                            }
                        }
                    }
                }

                // No 'am' or 'pm' indicator
                else if (beginHour <= Constants.HalfDayHourCount && endHour <= Constants.HalfDayHourCount)
                {
                    if (beginHour > endHour)
                    {
                        if (beginHour == Constants.HalfDayHourCount)
                        {
                            beginDateTime = beginDateTime.AddHours(-Constants.HalfDayHourCount);
                        }
                        else
                        {
                            endDateTime = endDateTime.AddHours(Constants.HalfDayHourCount);
                        }
                    }
                    ret.Comment = Constants.Comment_AmPm;
                }

                if (endDateTime < beginDateTime)
                {
                    endDateTime = endDateTime.AddHours(24);
                }

                var beginStr = DateTimeFormatUtil.ShortTime(beginDateTime.Hour, beginMinute, beginSecond);
                var endStr   = DateTimeFormatUtil.ShortTime(endDateTime.Hour, endMinute, endSecond);

                ret.Success = true;

                ret.Timex = $"({beginStr},{endStr},{DateTimeFormatUtil.LuisTimeSpan(endDateTime - beginDateTime)})";

                ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(
                    beginDateTime,
                    endDateTime);

                ret.SubDateTimeEntities = new List <object>();

                // In SplitDateAndTime mode, time points will be get from these SubDateTimeEntities
                // Cases like "from 4 to 5pm", "4" should not be treated as SubDateTimeEntity
                if (hasLeft || beginMinute != Constants.InvalidMinute || beginSecond != Constants.InvalidSecond)
                {
                    var er = new ExtractResult()
                    {
                        Start  = time1StartIndex,
                        Length = time1EndIndex - time1StartIndex,
                        Text   = text.Substring(time1StartIndex, time1EndIndex - time1StartIndex),
                        Type   = $"{Constants.SYS_DATETIME_TIME}"
                    };

                    var pr = this.config.TimeParser.Parse(er, referenceTime);
                    ret.SubDateTimeEntities.Add(pr);
                }

                // Cases like "from 4am to 5", "5" should not be treated as SubDateTimeEntity
                if (hasRight || endMinute != Constants.InvalidMinute || endSecond != Constants.InvalidSecond)
                {
                    var er = new ExtractResult
                    {
                        Start  = time2StartIndex,
                        Length = time2EndIndex - time2StartIndex,
                        Text   = text.Substring(time2StartIndex, time2EndIndex - time2StartIndex),
                        Type   = $"{Constants.SYS_DATETIME_TIME}"
                    };

                    var pr = this.config.TimeParser.Parse(er, referenceTime);
                    ret.SubDateTimeEntities.Add(pr);
                }

                ret.Success = true;
            }

            return(ret);
        }
        private DateTimeResolutionResult MergeTwoTimePoints(string text, DateObject referenceTime)
        {
            var ret = new DateTimeResolutionResult();
            DateTimeParseResult pr1 = null, pr2 = null;
            bool bothHaveDates = false, beginHasDate = false, endHasDate = false;

            var timeExtractResults     = this.Config.TimeExtractor.Extract(text, referenceTime);
            var dateTimeExtractResults = this.Config.DateTimeExtractor.Extract(text, referenceTime);

            if (dateTimeExtractResults.Count == 2)
            {
                pr1           = this.Config.DateTimeParser.Parse(dateTimeExtractResults[0], referenceTime);
                pr2           = this.Config.DateTimeParser.Parse(dateTimeExtractResults[1], referenceTime);
                bothHaveDates = true;
            }
            else if (dateTimeExtractResults.Count == 1 && timeExtractResults.Count == 2)
            {
                if (!dateTimeExtractResults[0].IsOverlap(timeExtractResults[0]))
                {
                    pr1        = this.Config.TimeParser.Parse(timeExtractResults[0], referenceTime);
                    pr2        = this.Config.DateTimeParser.Parse(dateTimeExtractResults[0], referenceTime);
                    endHasDate = true;
                }
                else
                {
                    pr1          = this.Config.DateTimeParser.Parse(dateTimeExtractResults[0], referenceTime);
                    pr2          = this.Config.TimeParser.Parse(timeExtractResults[1], referenceTime);
                    beginHasDate = true;
                }
            }
            else if (dateTimeExtractResults.Count == 1 && timeExtractResults.Count == 1)
            {
                if (timeExtractResults[0].Start < dateTimeExtractResults[0].Start)
                {
                    pr1        = this.Config.TimeParser.Parse(timeExtractResults[0], referenceTime);
                    pr2        = this.Config.DateTimeParser.Parse(dateTimeExtractResults[0], referenceTime);
                    endHasDate = true;
                }
                else if (timeExtractResults[0].Start >= dateTimeExtractResults[0].Start + dateTimeExtractResults[0].Length)
                {
                    pr1          = this.Config.DateTimeParser.Parse(dateTimeExtractResults[0], referenceTime);
                    pr2          = this.Config.TimeParser.Parse(timeExtractResults[0], referenceTime);
                    beginHasDate = true;
                }
                else
                {
                    // If the only TimeExtractResult is part of DateTimeExtractResult, then it should not be handled in this method
                    return(ret);
                }
            }
            else if (timeExtractResults.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 (bothHaveDates)
            {
                if (futureBegin > futureEnd)
                {
                    futureBegin = pastBegin;
                }

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

            if (bothHaveDates)
            {
                ret.Timex = $"({pr1.TimexStr},{pr2.TimexStr},PT{Convert.ToInt32((futureEnd - futureBegin).TotalHours)}H)";

                // Do nothing
            }
            else if (beginHasDate)
            {
                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);

                var dateStr     = pr1.TimexStr.Split('T')[0];
                var durationStr = DateTimeFormatUtil.LuisTimeSpan(futureEnd - futureBegin);
                ret.Timex = $"({pr1.TimexStr},{dateStr + pr2.TimexStr},{durationStr}";
            }
            else if (endHasDate)
            {
                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);

                var dateStr     = pr2.TimexStr.Split('T')[0];
                var durationStr = DateTimeFormatUtil.LuisTimeSpan(pastEnd - pastBegin);
                ret.Timex = $"({dateStr + pr1.TimexStr},{pr2.TimexStr},{durationStr})";
            }

            var ampmStr1 = ((DateTimeResolutionResult)pr1.Value).Comment;
            var ampmStr2 = ((DateTimeResolutionResult)pr2.Value).Comment;

            if (!string.IsNullOrEmpty(ampmStr1) && ampmStr1.EndsWith(Constants.Comment_AmPm) &&
                !string.IsNullOrEmpty(ampmStr2) && ampmStr2.EndsWith(Constants.Comment_AmPm))
            {
                ret.Comment = Constants.Comment_AmPm;
            }

            if ((this.Config.Options & DateTimeOptions.EnablePreview) != 0)
            {
                if (((DateTimeResolutionResult)pr1.Value).TimeZoneResolution != null)
                {
                    ret.TimeZoneResolution = ((DateTimeResolutionResult)pr1.Value).TimeZoneResolution;
                }
                else if (((DateTimeResolutionResult)pr2.Value).TimeZoneResolution != null)
                {
                    ret.TimeZoneResolution = ((DateTimeResolutionResult)pr2.Value).TimeZoneResolution;
                }
            }

            ret.FutureValue = new Tuple <DateObject, DateObject>(futureBegin, futureEnd);
            ret.PastValue   = new Tuple <DateObject, DateObject>(pastBegin, pastEnd);
            ret.Success     = true;

            ret.SubDateTimeEntities = new List <object> {
                pr1, pr2
            };

            return(ret);
        }
Пример #3
0
        // Cases like "between 0730 to 0930", only this case is handled in this method
        private DateTimeResolutionResult ParsePureDigitNumCases(string text, DateObject referenceTime)
        {
            var ret = new DateTimeResolutionResult();
            int year = referenceTime.Year, month = referenceTime.Month, day = referenceTime.Day;
            var trimmedText = text.Trim().ToLower();

            var match = this.config.PureNumberBetweenAndRegex.MatchBegin(trimmedText, trim: true);

            if (match.Success)
            {
                // get hours
                var hourGroup   = match.Groups[Constants.HourGroupName];
                var minuteGroup = match.Groups[Constants.MinuteGroupName];

                if (hourGroup.Captures.Count == 2 && minuteGroup.Captures.Count == 2)
                {
                    var beginHourEndIndex     = hourGroup.Captures[0].Index + hourGroup.Captures[0].Length;
                    var beginMinuteStartIndex = minuteGroup.Captures[0].Index;
                    var endHourEndIndex       = hourGroup.Captures[1].Index + hourGroup.Captures[1].Length;
                    var endMinuteStartIndex   = minuteGroup.Captures[1].Index;

                    // falls into the case "between 0730 to 0930"
                    if (beginHourEndIndex == beginMinuteStartIndex && endHourEndIndex == endMinuteStartIndex)
                    {
                        var startHourStr   = hourGroup.Captures[0].Value;
                        var startMinuteStr = minuteGroup.Captures[0].Value;
                        var endHourStr     = hourGroup.Captures[1].Value;
                        var endMinuteStr   = minuteGroup.Captures[1].Value;

                        if (!this.config.Numbers.TryGetValue(startHourStr, out int beginHour))
                        {
                            beginHour = int.Parse(startHourStr);
                        }

                        if (!this.config.Numbers.TryGetValue(startMinuteStr, out int beginMinute))
                        {
                            beginMinute = int.Parse(startMinuteStr);
                        }

                        if (!this.config.Numbers.TryGetValue(endHourStr, out int endHour))
                        {
                            endHour = int.Parse(endHourStr);
                        }

                        if (!this.config.Numbers.TryGetValue(endMinuteStr, out int endMinute))
                        {
                            endMinute = int.Parse(endMinuteStr);
                        }

                        var beginDateTime = DateObject.MinValue.SafeCreateFromValue(year, month, day, beginHour, beginMinute, 0);
                        var endDateTime   = DateObject.MinValue.SafeCreateFromValue(year, month, day, endHour, endMinute, 0);

                        if (beginHour <= Constants.HalfDayHourCount && endHour <= Constants.HalfDayHourCount)
                        {
                            if (beginHour > endHour)
                            {
                                if (beginHour == Constants.HalfDayHourCount)
                                {
                                    beginDateTime = beginDateTime.AddHours(-Constants.HalfDayHourCount);
                                }
                                else
                                {
                                    endDateTime = endDateTime.AddHours(Constants.HalfDayHourCount);
                                }
                            }

                            ret.Comment = Constants.Comment_AmPm;
                        }

                        if (endDateTime < beginDateTime)
                        {
                            endDateTime = endDateTime.AddHours(24);
                        }

                        var beginStr = DateTimeFormatUtil.ShortTime(beginDateTime.Hour, beginMinute);
                        var endStr   = DateTimeFormatUtil.ShortTime(endDateTime.Hour, endMinute);

                        ret.Timex = $"({beginStr},{endStr},{DateTimeFormatUtil.LuisTimeSpan(endDateTime - beginDateTime)})";

                        ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(
                            beginDateTime,
                            endDateTime);

                        ret.Success = true;
                    }
                }
            }

            return(ret);
        }
Пример #4
0
        public static string GenerateDateTimePeriodTimex(string beginTimex, string endTimex, TimeSpan duration)
        {
            var durationTimex = DateTimeFormatUtil.LuisTimeSpan(duration);

            return(GenerateDateTimePeriodTimex(beginTimex, endTimex, durationTimex));
        }