예제 #1
0
        public DateTimeParseResult Parse(ExtractResult er, DateObject refTime)
        {
            var referenceTime      = refTime;
            DateTimeParseResult pr = null;

            // push, save teh MOD string
            bool hasBefore = false, hasAfter = false;
            var  modStr = string.Empty;

            if (this.Config.BeforeRegex.IsMatch(er.Text))
            {
                hasBefore = true;
                var match = this.Config.BeforeRegex.Match(er.Text);
                er.Start  += match.Length;
                er.Length -= match.Length;
                er.Text    = er.Text.Substring(match.Length);
                modStr     = match.Value;
            }
            else if (this.Config.AfterRegex.IsMatch(er.Text))
            {
                hasAfter = true;
                var match = this.Config.AfterRegex.Match(er.Text);
                er.Start  += match.Length;
                er.Length -= match.Length;
                er.Text    = er.Text.Substring(match.Length);
                modStr     = match.Value;
            }

            if (er.Type.Equals(Constants.SYS_DATETIME_DATE))
            {
                pr = this.Config.DateParser.Parse(er, referenceTime);
                if (pr.Value == null)
                {
                    pr = Config.HolidayParser.Parse(er, referenceTime);
                }
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_TIME))
            {
                pr = this.Config.TimeParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATETIME))
            {
                pr = this.Config.DateTimeParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATEPERIOD))
            {
                pr = this.Config.DatePeriodParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_TIMEPERIOD))
            {
                pr = this.Config.TimePeriodParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATETIMEPERIOD))
            {
                pr = this.Config.DateTimePeriodParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DURATION))
            {
                pr = this.Config.DurationParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_SET))
            {
                pr = this.Config.GetParser.Parse(er, referenceTime);
            }
            else
            {
                return(null);
            }

            // pop, restore the MOD string
            if (hasBefore)
            {
                pr.Length += modStr.Length;
                pr.Start  -= modStr.Length;
                pr.Text    = modStr + pr.Text;
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod  = TimeTypeConstants.beforeMod;
                pr.Value = val;
            }

            if (hasAfter)
            {
                pr.Length += modStr.Length;
                pr.Start  -= modStr.Length;
                pr.Text    = modStr + pr.Text;
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod  = TimeTypeConstants.afterMod;
                pr.Value = val;
            }

            pr.Value = DateTimeResolution(pr, hasBefore, hasAfter);

            //change the type at last for the after or before mode
            pr.Type = $"{ParserTypeName}.{DetermineDateTimeType(er.Type, hasBefore, hasAfter)}";

            return(pr);
        }
        public DateTimeParseResult Parse(ExtractResult er, DateObject refTime)
        {
            var referenceTime = refTime;

            object value = null;

            if (er.Type.Equals(ParserName, StringComparison.Ordinal))
            {
                DateTimeResolutionResult innerResult;

                if (TimeZoneUtility.ShouldResolveTimeZone(er, config.Options))
                {
                    var metadata   = er.Data as Dictionary <string, object>;
                    var timezoneEr = metadata[Constants.SYS_DATETIME_TIMEZONE] as ExtractResult;
                    var timezonePr = config.TimeZoneParser.Parse(timezoneEr);

                    innerResult = InternalParse(
                        er.Text.Substring(0, (int)(er.Length - timezoneEr.Length)),
                        referenceTime);

                    if (timezonePr != null && timezonePr.Value != null)
                    {
                        innerResult.TimeZoneResolution = ((DateTimeResolutionResult)timezonePr.Value).TimeZoneResolution;
                    }
                }
                else
                {
                    innerResult = InternalParse(er.Text, referenceTime);
                }

                if (innerResult.Success)
                {
                    innerResult.FutureResolution = new Dictionary <string, string>
                    {
                        {
                            TimeTypeConstants.START_TIME,
                            DateTimeFormatUtil.FormatTime(((Tuple <DateObject, DateObject>)innerResult.FutureValue).Item1)
                        },
                        {
                            TimeTypeConstants.END_TIME,
                            DateTimeFormatUtil.FormatTime(((Tuple <DateObject, DateObject>)innerResult.FutureValue).Item2)
                        },
                    };

                    innerResult.PastResolution = new Dictionary <string, string>
                    {
                        {
                            TimeTypeConstants.START_TIME,
                            DateTimeFormatUtil.FormatTime(((Tuple <DateObject, DateObject>)innerResult.PastValue).Item1)
                        },
                        {
                            TimeTypeConstants.END_TIME,
                            DateTimeFormatUtil.FormatTime(((Tuple <DateObject, DateObject>)innerResult.PastValue).Item2)
                        },
                    };

                    value = innerResult;
                }
            }

            var ret = new DateTimeParseResult
            {
                Text          = er.Text,
                Start         = er.Start,
                Length        = er.Length,
                Type          = er.Type,
                Data          = er.Data,
                Value         = value,
                TimexStr      = value == null ? string.Empty : ((DateTimeResolutionResult)value).Timex,
                ResolutionStr = string.Empty,
            };

            return(ret);
        }
        public DateTimeParseResult Parse(ExtractResult er, DateObject refTime)
        {
            var referenceTime = refTime;

            object value = null;

            if (er.Type.Equals(ParserName))
            {
                var innerResult = ParseSimpleCases(er.Text, referenceTime);
                if (!innerResult.Success)
                {
                    innerResult = MergeTwoTimePoints(er.Text, referenceTime);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseTimeOfDay(er.Text, referenceTime);
                }

                if (innerResult.Success)
                {
                    innerResult.FutureResolution = new Dictionary <string, string>
                    {
                        {
                            TimeTypeConstants.START_TIME,
                            FormatUtil.FormatTime(((Tuple <DateObject, DateObject>)innerResult.FutureValue).Item1)
                        },
                        {
                            TimeTypeConstants.END_TIME,
                            FormatUtil.FormatTime(((Tuple <DateObject, DateObject>)innerResult.FutureValue).Item2)
                        }
                    };

                    innerResult.PastResolution = new Dictionary <string, string>
                    {
                        {
                            TimeTypeConstants.START_TIME,
                            FormatUtil.FormatTime(((Tuple <DateObject, DateObject>)innerResult.PastValue).Item1)
                        },
                        {
                            TimeTypeConstants.END_TIME,
                            FormatUtil.FormatTime(((Tuple <DateObject, DateObject>)innerResult.PastValue).Item2)
                        }
                    };

                    value = innerResult;
                }
            }

            var ret = new DateTimeParseResult
            {
                Text          = er.Text,
                Start         = er.Start,
                Length        = er.Length,
                Type          = er.Type,
                Data          = er.Data,
                Value         = value,
                TimexStr      = value == null ? "" : ((DateTimeResolutionResult)value).Timex,
                ResolutionStr = ""
            };

            return(ret);
        }
예제 #4
0
        public SortedDictionary <string, object> DateTimeResolution(DateTimeParseResult slot)
        {
            if (slot == null)
            {
                return(null);
            }

            var resolutions = new List <Dictionary <string, string> >();
            var res         = new Dictionary <string, object>();

            var type  = slot.Type;
            var timex = slot.TimexStr;

            var val = (DateTimeResolutionResult)slot.Value;

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

            var    isLunar = val.IsLunar;
            var    mod     = val.Mod;
            string list    = null;

            // Resolve dates list for date periods
            if (slot.Type.Equals(Constants.SYS_DATETIME_DATEPERIOD, StringComparison.Ordinal) && val.List != null)
            {
                list = string.Join(",", val.List.Select(o => DateTimeFormatUtil.LuisDate((DateObject)o)).ToArray());
            }

            // With modifier, output Type might not be the same with type in resolution result
            // For example, if the resolution type is "date", with modifier the output type should be "daterange"
            var typeOutput = DetermineDateTimeType(slot.Type, hasMod: !string.IsNullOrEmpty(mod));

            var sourceEntity = DetermineSourceEntityType(slot.Type, typeOutput, val.HasRangeChangingMod);

            var comment = val.Comment;

            // The following should be added to res first, since ResolveAmPm requires these fields.
            AddResolutionFields(res, DateTimeResolutionKey.Timex, timex);
            AddResolutionFields(res, Constants.Comment, comment);
            AddResolutionFields(res, DateTimeResolutionKey.Mod, mod);
            AddResolutionFields(res, ResolutionKey.Type, typeOutput);
            AddResolutionFields(res, DateTimeResolutionKey.IsLunar, isLunar ? isLunar.ToString() : string.Empty);

            var hasTimeZone = false;

            // For standalone timezone entity recognition, we generate TimeZoneResolution for each entity we extracted.
            // We also merge time entity with timezone entity and add the information in TimeZoneResolution to every DateTime resolutions.
            if (val.TimeZoneResolution != null)
            {
                if (slot.Type.Equals(Constants.SYS_DATETIME_TIMEZONE, StringComparison.Ordinal))
                {
                    // single timezone
                    AddResolutionFields(res, Constants.ResolveTimeZone, new Dictionary <string, string>
                    {
                        { ResolutionKey.Value, val.TimeZoneResolution.Value },
                        { Constants.UtcOffsetMinsKey, val.TimeZoneResolution.UtcOffsetMins.ToString() },
                    });
                }
                else
                {
                    // timezone as clarification of datetime
                    hasTimeZone = true;
                    AddResolutionFields(res, Constants.TimeZone, val.TimeZoneResolution.Value);
                    AddResolutionFields(res, Constants.TimeZoneText, val.TimeZoneResolution.TimeZoneText);
                    AddResolutionFields(res, Constants.UtcOffsetMinsKey, val.TimeZoneResolution.UtcOffsetMins.ToString());
                }
            }

            var pastResolutionStr   = ((DateTimeResolutionResult)slot.Value).PastResolution;
            var futureResolutionStr = ((DateTimeResolutionResult)slot.Value).FutureResolution;

            if (typeOutput == Constants.SYS_DATETIME_DATETIMEALT && pastResolutionStr.Count > 0)
            {
                typeOutput = DetermineResolutionDateTimeType(pastResolutionStr);
            }

            var resolutionPast   = GenerateResolution(type, pastResolutionStr, mod);
            var resolutionFuture = GenerateResolution(type, futureResolutionStr, mod);

            // If past and future are same, keep only one
            if (resolutionFuture.OrderBy(t => t.Key).Select(t => t.Value)
                .SequenceEqual(resolutionPast.OrderBy(t => t.Key).Select(t => t.Value)))
            {
                if (resolutionPast.Count > 0)
                {
                    AddResolutionFields(res, Constants.Resolve, resolutionPast);
                }
            }
            else
            {
                if (resolutionPast.Count > 0)
                {
                    AddResolutionFields(res, Constants.ResolveToPast, resolutionPast);
                }

                if (resolutionFuture.Count > 0)
                {
                    AddResolutionFields(res, Constants.ResolveToFuture, resolutionFuture);
                }
            }

            // If 'ampm', double our resolution accordingly
            if (!string.IsNullOrEmpty(comment) && comment.Equals(Constants.Comment_AmPm, StringComparison.Ordinal))
            {
                if (res.ContainsKey(Constants.Resolve))
                {
                    ResolveAmpm(res, Constants.Resolve);
                }
                else
                {
                    ResolveAmpm(res, Constants.ResolveToPast);
                    ResolveAmpm(res, Constants.ResolveToFuture);
                }
            }

            // If WeekOf and in CalendarMode, modify the past part of our resolution
            if ((Config.Options & DateTimeOptions.CalendarMode) != 0 &&
                !string.IsNullOrEmpty(comment) && comment.Equals(Constants.Comment_WeekOf, StringComparison.Ordinal))
            {
                ResolveWeekOf(res, Constants.ResolveToPast);
            }

            foreach (var p in res)
            {
                if (p.Value is Dictionary <string, string> dictionary)
                {
                    var value = new Dictionary <string, string>();

                    AddResolutionFields(value, DateTimeResolutionKey.Timex, timex);
                    AddResolutionFields(value, DateTimeResolutionKey.Mod, mod);
                    AddResolutionFields(value, ResolutionKey.Type, typeOutput);
                    AddResolutionFields(value, DateTimeResolutionKey.IsLunar, isLunar ? isLunar.ToString() : string.Empty);
                    AddResolutionFields(value, DateTimeResolutionKey.List, list);
                    AddResolutionFields(value, DateTimeResolutionKey.SourceEntity, sourceEntity);

                    if (hasTimeZone)
                    {
                        AddResolutionFields(value, Constants.TimeZone, val.TimeZoneResolution.Value);
                        AddResolutionFields(value, Constants.TimeZoneText, val.TimeZoneResolution.TimeZoneText);
                        AddResolutionFields(value, Constants.UtcOffsetMinsKey, val.TimeZoneResolution.UtcOffsetMins.ToString());
                    }

                    foreach (var q in dictionary)
                    {
                        if (value.ContainsKey(q.Key))
                        {
                            value[q.Key] = q.Value;
                        }
                        else
                        {
                            value.Add(q.Key, q.Value);
                        }
                    }

                    resolutions.Add(value);
                }
            }

            if (resolutionPast.Count == 0 && resolutionFuture.Count == 0 && val.TimeZoneResolution == null)
            {
                var notResolved = new Dictionary <string, string>
                {
                    {
                        DateTimeResolutionKey.Timex, timex
                    },
                    {
                        ResolutionKey.Type, typeOutput
                    },
                    {
                        ResolutionKey.Value, "not resolved"
                    },
                };

                resolutions.Add(notResolved);
            }

            return(new SortedDictionary <string, object> {
                { ResolutionKey.ValueSet, resolutions }
            });
        }
        public DateTimeParseResult Parse(ExtractResult er, DateObject referenceTime)
        {
            DateTimeParseResult pr = null;

            // push, save teh MOD string
            bool   hasBefore = false, hasAfter = false, hasUntil = false, hasSince = false;
            string modStr = string.Empty, modStrPrefix = string.Empty, modStrSuffix = string.Empty;
            var    beforeMatch      = config.BeforeRegex.MatchEnd(er.Text, trim: true);
            var    afterMatch       = config.AfterRegex.MatchEnd(er.Text, trim: true);
            var    untilMatch       = config.UntilRegex.MatchBegin(er.Text, trim: true);
            var    sinceMatchPrefix = config.SincePrefixRegex.MatchBegin(er.Text, trim: true);
            var    sinceMatchSuffix = config.SinceSuffixRegex.MatchEnd(er.Text, trim: true);

            if (beforeMatch.Success && !IsDurationWithBeforeAndAfter(er))
            {
                hasBefore  = true;
                er.Length -= beforeMatch.Length;
                er.Text    = er.Text.Substring(0, er.Length ?? 0);
                modStr     = beforeMatch.Value;
            }
            else if (afterMatch.Success && !IsDurationWithBeforeAndAfter(er))
            {
                hasAfter   = true;
                er.Length -= afterMatch.Length;
                er.Text    = er.Text.Substring(0, er.Length ?? 0);
                modStr     = afterMatch.Value;
            }
            else if (untilMatch.Success)
            {
                hasUntil   = true;
                er.Start  += untilMatch.Length;
                er.Length -= untilMatch.Length;
                er.Text    = er.Text.Substring(untilMatch.Length);
                modStr     = untilMatch.Value;
            }
            else
            {
                if (sinceMatchPrefix.Success)
                {
                    hasSince     = true;
                    er.Start    += sinceMatchPrefix.Length;
                    er.Length   -= sinceMatchPrefix.Length;
                    er.Text      = er.Text.Substring(sinceMatchPrefix.Length);
                    modStrPrefix = sinceMatchPrefix.Value;
                }

                if (sinceMatchSuffix.Success)
                {
                    hasSince     = true;
                    er.Length   -= sinceMatchSuffix.Length;
                    er.Text      = er.Text.Substring(0, er.Length ?? 0);
                    modStrSuffix = sinceMatchSuffix.Value;
                }
            }

            if (er.Type.Equals(Constants.SYS_DATETIME_DATE))
            {
                pr = config.DateParser.Parse(er, referenceTime);
                if (pr.Value == null)
                {
                    pr = config.HolidayParser.Parse(er, referenceTime);
                }
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_TIME))
            {
                pr = config.TimeParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATETIME))
            {
                pr = config.DateTimeParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATEPERIOD))
            {
                pr = config.DatePeriodParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_TIMEPERIOD))
            {
                pr = config.TimePeriodParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATETIMEPERIOD))
            {
                pr = config.DateTimePeriodParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DURATION))
            {
                pr = config.DurationParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_SET))
            {
                pr = config.GetParser.Parse(er, referenceTime);
            }
            else
            {
                return(null);
            }

            // pop, restore the MOD string
            if (hasBefore)
            {
                pr.Length += modStr.Length;
                pr.Text    = pr.Text + modStr;
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod  = Constants.BEFORE_MOD;
                pr.Value = val;
            }

            if (hasAfter)
            {
                pr.Length += modStr.Length;
                pr.Text    = pr.Text + modStr;
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod  = Constants.AFTER_MOD;
                pr.Value = val;
            }

            if (hasUntil)
            {
                pr.Length += modStr.Length;
                pr.Start  -= modStr.Length;
                pr.Text    = modStr + pr.Text;
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod   = Constants.BEFORE_MOD;
                pr.Value  = val;
                hasBefore = true;
            }

            if (hasSince)
            {
                pr.Length += modStrPrefix.Length + modStrSuffix.Length;
                pr.Start  -= modStrPrefix.Length;
                pr.Text    = modStrPrefix + pr.Text + modStrSuffix;
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod  = Constants.SINCE_MOD;
                pr.Value = val;
            }

            pr.Value = DateTimeResolution(pr, hasBefore, hasAfter, hasSince);

            // change the type at last for the after or before mode
            pr.Type = $"{ParserTypeName}.{DetermineDateTimeType(er.Type, hasBefore, hasAfter, hasSince)}";

            return(pr);
        }
예제 #6
0
        public DateTimeParseResult Parse(ExtractResult er, DateObject refDate)
        {
            var referenceTime = refDate;
            var extra         = er.Data as DateTimeExtra <PeriodType>;

            if (extra == null)
            {
                var result = this.config.TimeExtractor.Extract(er.Text, refDate);
                extra = result[0]?.Data as DateTimeExtra <PeriodType>;
            }

            if (extra != null)
            {
                // Handle special case like '上午' (morning), '下午' (afternoon)
                var parseResult = ParseTimeOfDay(er.Text, referenceTime);

                if (!parseResult.Success)
                {
                    parseResult = TimePeriodFunctions.Handle(this.config.TimeParser, extra, referenceTime, this.config.TimeFunc);
                }

                if (parseResult.Success)
                {
                    parseResult.FutureResolution = new Dictionary <string, string>
                    {
                        {
                            TimeTypeConstants.START_TIME,
                            DateTimeFormatUtil.FormatTime(((Tuple <DateObject, DateObject>)parseResult.FutureValue).Item1)
                        },
                        {
                            TimeTypeConstants.END_TIME,
                            DateTimeFormatUtil.FormatTime(((Tuple <DateObject, DateObject>)parseResult.FutureValue).Item2)
                        },
                    };

                    parseResult.PastResolution = new Dictionary <string, string>
                    {
                        {
                            TimeTypeConstants.START_TIME,
                            DateTimeFormatUtil.FormatTime(((Tuple <DateObject, DateObject>)parseResult.PastValue).Item1)
                        },
                        {
                            TimeTypeConstants.END_TIME,
                            DateTimeFormatUtil.FormatTime(((Tuple <DateObject, DateObject>)parseResult.PastValue).Item2)
                        },
                    };
                }

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

                return(ret);
            }

            return(null);
        }
예제 #7
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);

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

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

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

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

            if (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];
                ret.Timex = $"({pr1.TimexStr},{dateStr + pr2.TimexStr},PT{Convert.ToInt32((futureEnd - futureBegin).TotalHours)}H)";
            }
            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];
                ret.Timex = $"({dateStr + pr1.TimexStr},{pr2.TimexStr},PT{Convert.ToInt32((futureEnd - futureBegin).TotalHours)}H)";
            }

            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;
            }

            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);
        }
예제 #8
0
        // This will parse to a date ranging between the holiday and the closest weekend
        // cases: "Thanksgiving weekend", "weekend of Halloween"
        private DateTimeParseResult ParseHolidayWeekend(ExtractResult er, DateObject referenceDate)
        {
            var dateTimeRes = new DateTimeResolutionResult();

            if (!string.IsNullOrEmpty(er.Metadata?.HolidayName))
            {
                var holidayName = er.Metadata.HolidayName;

                // resolve holiday
                var holidayEr = new ExtractResult
                {
                    Start    = 0,
                    Length   = holidayName.Length,
                    Text     = holidayName,
                    Type     = Constants.SYS_DATETIME_DATE,
                    Data     = null,
                    Metadata = new Metadata {
                        IsHoliday = true
                    },
                };
                var result = (DateTimeResolutionResult)this.Parse(holidayEr, referenceDate).Value;

                if (!result.Success)
                {
                    dateTimeRes.FutureResolution = dateTimeRes.PastResolution = new Dictionary <string, string>();
                }
                else
                {
                    // get closest weekend to the holiday(s)
                    var futureWeekend = GetClosestHolidayWeekend((DateObject)result.FutureValue);
                    var pastWeekend   = futureWeekend;

                    if (result.FutureValue == result.PastValue)
                    {
                        dateTimeRes.Timex = TimexUtility.GenerateWeekendTimex(futureWeekend.Item1);
                    }
                    else
                    {
                        dateTimeRes.Timex = result.Timex;
                        pastWeekend       = GetClosestHolidayWeekend((DateObject)result.PastValue);
                    }

                    dateTimeRes.Success     = true;
                    dateTimeRes.FutureValue = futureWeekend;
                    dateTimeRes.PastValue   = pastWeekend;

                    dateTimeRes.FutureResolution = new Dictionary <string, string>
                    {
                        {
                            TimeTypeConstants.START_DATE,
                            DateTimeFormatUtil.FormatDate(((Tuple <DateObject, DateObject>)dateTimeRes.FutureValue).Item1)
                        },
                        {
                            TimeTypeConstants.END_DATE,
                            DateTimeFormatUtil.FormatDate(((Tuple <DateObject, DateObject>)dateTimeRes.FutureValue).Item2)
                        },
                        {
                            DateTimeResolutionKey.Timex,
                            TimexUtility.GenerateWeekendTimex(futureWeekend.Item1)
                        },
                    };

                    dateTimeRes.PastResolution = new Dictionary <string, string>
                    {
                        {
                            TimeTypeConstants.START_DATE,
                            DateTimeFormatUtil.FormatDate(((Tuple <DateObject, DateObject>)dateTimeRes.PastValue).Item1)
                        },
                        {
                            TimeTypeConstants.END_DATE,
                            DateTimeFormatUtil.FormatDate(((Tuple <DateObject, DateObject>)dateTimeRes.PastValue).Item2)
                        },
                        {
                            DateTimeResolutionKey.Timex,
                            TimexUtility.GenerateWeekendTimex(pastWeekend.Item1)
                        },
                    };
                }
            }
            else
            {
                dateTimeRes.FutureResolution = dateTimeRes.PastResolution = new Dictionary <string, string>();
            }

            var ret = new DateTimeParseResult
            {
                Text          = er.Text,
                Start         = er.Start,
                Length        = er.Length,
                Type          = er.Type,
                Data          = er.Data,
                Metadata      = er.Metadata,
                Value         = dateTimeRes,
                TimexStr      = dateTimeRes == null ? string.Empty : ((DateTimeResolutionResult)dateTimeRes).Timex,
                ResolutionStr = string.Empty,
            };

            return(ret);
        }
        public DateTimeParseResult Parse(ExtractResult er, DateObject refTime)
        {
            var referenceTime      = refTime;
            DateTimeParseResult pr = null;

            var originText = er.Text;

            if ((this.Config.Options & DateTimeOptions.EnablePreview) != 0)
            {
                er.Text    = MatchingUtil.PreProcessTextRemoveSuperfluousWords(er.Text, Config.SuperfluousWordMatcher, out var _);
                er.Length += er.Text.Length - originText.Length;
            }

            // Push, save the MOD string
            bool hasBefore = false, hasAfter = false, hasSince = false, hasYearAfter = false;

            // "InclusieModifier" means MOD should include the start/end time
            // For example, cases like "on or later than", "earlier than or in" have inclusive modifier
            bool hasInclusiveModifier = false;
            var  modStr      = string.Empty;
            var  beforeMatch = Config.BeforeRegex.Match(er.Text);
            var  afterMatch  = Config.AfterRegex.Match(er.Text);
            var  sinceMatch  = Config.SinceRegex.Match(er.Text);

            if (beforeMatch.Success && beforeMatch.Index == 0)
            {
                hasBefore  = true;
                er.Start  += beforeMatch.Length;
                er.Length -= beforeMatch.Length;
                er.Text    = er.Text.Substring(beforeMatch.Length);
                modStr     = beforeMatch.Value;

                if (!string.IsNullOrEmpty(beforeMatch.Groups["include"].Value))
                {
                    hasInclusiveModifier = true;
                }
            }
            else if (afterMatch.Success && afterMatch.Index == 0)
            {
                hasAfter   = true;
                er.Start  += afterMatch.Length;
                er.Length -= afterMatch.Length;
                er.Text    = er.Text.Substring(afterMatch.Length);
                modStr     = afterMatch.Value;

                if (!string.IsNullOrEmpty(afterMatch.Groups["include"].Value))
                {
                    hasInclusiveModifier = true;
                }
            }
            else if (sinceMatch.Success && sinceMatch.Index == 0)
            {
                hasSince   = true;
                er.Start  += sinceMatch.Length;
                er.Length -= sinceMatch.Length;
                er.Text    = er.Text.Substring(sinceMatch.Length);
                modStr     = sinceMatch.Value;
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATEPERIOD) && Config.YearRegex.Match(er.Text).Success)
            {
                // This has to be put at the end of the if, or cases like "before 2012" and "after 2012" would fall into this
                // 2012 or after/above
                var match = Config.YearAfterRegex.Match(er.Text);
                if (match.Success && er.Text.EndsWith(match.Value))
                {
                    hasYearAfter = true;
                    er.Length   -= match.Length;
                    er.Text      = er.Text.Substring(0, er.Length ?? 0);
                    modStr       = match.Value;
                }
            }

            if (er.Type.Equals(Constants.SYS_DATETIME_DATE))
            {
                pr = this.Config.DateParser.Parse(er, referenceTime);
                if (pr.Value == null)
                {
                    pr = Config.HolidayParser.Parse(er, referenceTime);
                }
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_TIME))
            {
                pr = this.Config.TimeParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATETIME))
            {
                pr = this.Config.DateTimeParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATEPERIOD))
            {
                pr = this.Config.DatePeriodParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_TIMEPERIOD))
            {
                pr = this.Config.TimePeriodParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATETIMEPERIOD))
            {
                pr = this.Config.DateTimePeriodParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DURATION))
            {
                pr = this.Config.DurationParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_SET))
            {
                pr = this.Config.SetParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATETIMEALT))
            {
                pr = this.Config.DateTimeAltParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_TIMEZONE))
            {
                if ((Config.Options & DateTimeOptions.EnablePreview) != 0)
                {
                    pr = this.Config.TimeZoneParser.Parse(er, referenceTime);
                }
            }
            else
            {
                return(null);
            }

            // Pop, restore the MOD string
            if (hasBefore && pr.Value != null)
            {
                pr.Length += modStr.Length;
                pr.Start  -= modStr.Length;
                pr.Text    = modStr + pr.Text;
                var val = (DateTimeResolutionResult)pr.Value;

                if (!hasInclusiveModifier)
                {
                    val.Mod = Constants.BEFORE_MOD;
                }
                else
                {
                    val.Mod = Constants.UNTIL_MOD;
                }

                pr.Value = val;
            }

            if (hasAfter && pr.Value != null)
            {
                pr.Length += modStr.Length;
                pr.Start  -= modStr.Length;
                pr.Text    = modStr + pr.Text;
                var val = (DateTimeResolutionResult)pr.Value;

                if (!hasInclusiveModifier)
                {
                    val.Mod = Constants.AFTER_MOD;
                }
                else
                {
                    val.Mod = Constants.SINCE_MOD;
                }

                pr.Value = val;
            }

            if (hasSince && pr.Value != null)
            {
                pr.Length += modStr.Length;
                pr.Start  -= modStr.Length;
                pr.Text    = modStr + pr.Text;
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod  = Constants.SINCE_MOD;
                pr.Value = val;
            }

            if (hasYearAfter && pr.Value != null)
            {
                pr.Length += modStr.Length;
                pr.Text    = pr.Text + modStr;
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod  = Constants.SINCE_MOD;
                pr.Value = val;
                hasSince = true;
            }

            if ((Config.Options & DateTimeOptions.SplitDateAndTime) != 0 &&
                ((DateTimeResolutionResult)pr.Value)?.SubDateTimeEntities != null)
            {
                pr.Value = DateTimeResolutionForSplit(pr);
            }
            else
            {
                var hasModifier = hasBefore || hasAfter || hasSince;
                pr = SetParseResult(pr, hasModifier);
            }

            // In this version, ExperimentalMode only cope with the "IncludePeriodEnd" case
            if ((this.Config.Options & DateTimeOptions.ExperimentalMode) != 0)
            {
                if (pr.Metadata != null && pr.Metadata.PossiblyIncludePeriodEnd)
                {
                    pr = SetInclusivePeriodEnd(pr);
                }
            }

            if ((this.Config.Options & DateTimeOptions.EnablePreview) != 0)
            {
                pr.Length += originText.Length - pr.Text.Length;
                pr.Text    = originText;
            }

            return(pr);
        }
예제 #10
0
        public DateTimeParseResult Parse(ExtractResult er, DateObject refTime)
        {
            var referenceTime = refTime;

            object value = null;

            if (er.Type.Equals(ParserName))
            {
                var innerResult = InternalParse(er.Text, referenceTime);

                // Handling timeZone
                if (innerResult.Success && TimeZoneUtility.ShouldResolveTimeZone(er, this.Config.Options))
                {
                    var metadata   = er.Data as Dictionary <string, object>;
                    var timezoneEr = metadata[Constants.SYS_DATETIME_TIMEZONE] as ExtractResult;
                    var timezonePr = this.Config.TimeZoneParser.Parse(timezoneEr);
                    if (timezonePr != null && timezonePr.Value != null)
                    {
                        innerResult.TimeZoneResolution = ((DateTimeResolutionResult)timezonePr.Value).TimeZoneResolution;
                    }
                }

                if (innerResult.Success)
                {
                    if (!IsBeforeOrAfterMod(innerResult.Mod))
                    {
                        innerResult.FutureResolution = new Dictionary <string, string>
                        {
                            {
                                TimeTypeConstants.START_DATETIME,
                                DateTimeFormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)innerResult.FutureValue).Item1)
                            },
                            {
                                TimeTypeConstants.END_DATETIME,
                                DateTimeFormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)innerResult.FutureValue).Item2)
                            },
                        };

                        innerResult.PastResolution = new Dictionary <string, string>
                        {
                            {
                                TimeTypeConstants.START_DATETIME,
                                DateTimeFormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)innerResult.PastValue).Item1)
                            },
                            {
                                TimeTypeConstants.END_DATETIME,
                                DateTimeFormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)innerResult.PastValue).Item2)
                            },
                        };
                    }
                    else
                    {
                        if (innerResult.Mod == Constants.AFTER_MOD)
                        {
                            // Cases like "1/1/2015 after 2:00" there is no EndTime
                            innerResult.FutureResolution = new Dictionary <string, string>
                            {
                                {
                                    TimeTypeConstants.START_DATETIME,
                                    DateTimeFormatUtil.FormatDateTime((DateObject)innerResult.FutureValue)
                                },
                            };

                            innerResult.PastResolution = new Dictionary <string, string>
                            {
                                {
                                    TimeTypeConstants.START_DATETIME,
                                    DateTimeFormatUtil.FormatDateTime((DateObject)innerResult.PastValue)
                                },
                            };
                        }
                        else
                        {
                            // Cases like "1/1/2015 before 5:00 in the afternoon" there is no StartTime
                            innerResult.FutureResolution = new Dictionary <string, string>
                            {
                                {
                                    TimeTypeConstants.END_DATETIME,
                                    DateTimeFormatUtil.FormatDateTime((DateObject)innerResult.FutureValue)
                                },
                            };

                            innerResult.PastResolution = new Dictionary <string, string>
                            {
                                {
                                    TimeTypeConstants.END_DATETIME,
                                    DateTimeFormatUtil.FormatDateTime((DateObject)innerResult.PastValue)
                                },
                            };
                        }
                    }

                    value = innerResult;
                }
            }

            var ret = new DateTimeParseResult
            {
                Text          = er.Text,
                Start         = er.Start,
                Length        = er.Length,
                Type          = er.Type,
                Data          = er.Data,
                Value         = value,
                TimexStr      = value == null ? string.Empty : ((DateTimeResolutionResult)value).Timex,
                ResolutionStr = string.Empty,
            };

            return(ret);
        }
예제 #11
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 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},PT{Convert.ToInt32((pastEnd - pastBegin).TotalHours)}H)";
            }

            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);
        }
        public DateTimeParseResult Parse(ExtractResult er, DateObject refTime)
        {
            var referenceTime      = refTime;
            DateTimeParseResult pr = null;

            // Push, save the MOD string
            bool hasBefore = false, hasAfter = false, hasSince = false, hasYearAfter = false;
            var  modStr      = string.Empty;
            var  beforeMatch = Config.BeforeRegex.Match(er.Text);
            var  afterMatch  = Config.AfterRegex.Match(er.Text);
            var  sinceMatch  = Config.SinceRegex.Match(er.Text);

            if (beforeMatch.Success && beforeMatch.Index == 0)
            {
                hasBefore  = true;
                er.Start  += beforeMatch.Length;
                er.Length -= beforeMatch.Length;
                er.Text    = er.Text.Substring(beforeMatch.Length);
                modStr     = beforeMatch.Value;
            }
            else if (afterMatch.Success && afterMatch.Index == 0)
            {
                hasAfter   = true;
                er.Start  += afterMatch.Length;
                er.Length -= afterMatch.Length;
                er.Text    = er.Text.Substring(afterMatch.Length);
                modStr     = afterMatch.Value;
            }
            else if (sinceMatch.Success && sinceMatch.Index == 0)
            {
                hasSince   = true;
                er.Start  += sinceMatch.Length;
                er.Length -= sinceMatch.Length;
                er.Text    = er.Text.Substring(sinceMatch.Length);
                modStr     = sinceMatch.Value;
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATEPERIOD) && Config.YearRegex.Match(er.Text).Success)
            {
                // This has to be put at the end of the if, or cases like "before 2012" and "after 2012" would fall into this
                // 2012 or after/above
                var match = Config.YearAfterRegex.Match(er.Text);
                if (match.Success && er.Text.EndsWith(match.Value))
                {
                    hasYearAfter = true;
                    er.Length   -= match.Length;
                    er.Text      = er.Text.Substring(0, er.Length ?? 0);
                    modStr       = match.Value;
                }
            }

            if (er.Type.Equals(Constants.SYS_DATETIME_DATE))
            {
                pr = this.Config.DateParser.Parse(er, referenceTime);
                if (pr.Value == null)
                {
                    pr = Config.HolidayParser.Parse(er, referenceTime);
                }
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_TIME))
            {
                pr = this.Config.TimeParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATETIME))
            {
                pr = this.Config.DateTimeParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATEPERIOD))
            {
                pr = this.Config.DatePeriodParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_TIMEPERIOD))
            {
                pr = this.Config.TimePeriodParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATETIMEPERIOD))
            {
                pr = this.Config.DateTimePeriodParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DURATION))
            {
                pr = this.Config.DurationParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_SET))
            {
                pr = this.Config.GetParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_DATETIMEALT))
            {
                pr = this.Config.DateTimeAltParser.Parse(er, referenceTime);
            }
            else if (er.Type.Equals(Constants.SYS_DATETIME_TIMEZONE))
            {
                if ((Config.Options & DateTimeOptions.EnablePreview) != 0)
                {
                    pr = this.Config.TimeZoneParser.Parse(er, referenceTime);
                }
            }
            else
            {
                return(null);
            }

            // Pop, restore the MOD string
            if (hasBefore && pr.Value != null)
            {
                pr.Length += modStr.Length;
                pr.Start  -= modStr.Length;
                pr.Text    = modStr + pr.Text;
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod  = Constants.BEFORE_MOD;
                pr.Value = val;
            }

            if (hasAfter && pr.Value != null)
            {
                pr.Length += modStr.Length;
                pr.Start  -= modStr.Length;
                pr.Text    = modStr + pr.Text;
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod  = Constants.AFTER_MOD;
                pr.Value = val;
            }

            if (hasSince && pr.Value != null)
            {
                pr.Length += modStr.Length;
                pr.Start  -= modStr.Length;
                pr.Text    = modStr + pr.Text;
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod  = Constants.SINCE_MOD;
                pr.Value = val;
            }

            if (hasYearAfter && pr.Value != null)
            {
                pr.Length += modStr.Length;
                pr.Text    = pr.Text + modStr;
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod  = Constants.SINCE_MOD;
                pr.Value = val;
                hasSince = true;
            }

            if ((Config.Options & DateTimeOptions.SplitDateAndTime) != 0 &&
                ((DateTimeResolutionResult)pr.Value)?.SubDateTimeEntities != null)
            {
                pr.Value = DateTimeResolutionForSplit(pr);
            }
            else
            {
                pr = SetParseResult(pr, hasBefore, hasAfter, hasSince);
            }

            return(pr);
        }
        public SortedDictionary <string, object> DateTimeResolution(DateTimeParseResult slot, bool hasBefore, bool hasAfter, bool hasSince)
        {
            if (slot == null)
            {
                return(null);
            }

            var resolutions = new List <Dictionary <string, string> >();
            var res         = new Dictionary <string, object>();

            var type       = slot.Type;
            var typeOutput = DetermineDateTimeType(slot.Type, hasBefore, hasAfter, hasSince);
            var timex      = slot.TimexStr;

            var val = (DateTimeResolutionResult)slot.Value;

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

            var islunar = val.IsLunar;
            var mod     = val.Mod;
            var comment = val.Comment;

            // The following should be added to res first, since ResolveAmPm requires these fields.
            AddResolutionFields(res, DateTimeResolutionKey.Timex, timex);
            AddResolutionFields(res, Constants.Comment, comment);
            AddResolutionFields(res, DateTimeResolutionKey.Mod, mod);
            AddResolutionFields(res, ResolutionKey.Type, typeOutput);
            AddResolutionFields(res, DateTimeResolutionKey.IsLunar, islunar? islunar.ToString():string.Empty);

            var pastResolutionStr   = ((DateTimeResolutionResult)slot.Value).PastResolution;
            var futureResolutionStr = ((DateTimeResolutionResult)slot.Value).FutureResolution;

            if (typeOutput == Constants.SYS_DATETIME_DATETIMEALT && pastResolutionStr.Count > 0)
            {
                typeOutput = DetermineResolutionDateTimeType(pastResolutionStr);
            }

            var resolutionPast   = GenerateResolution(type, pastResolutionStr, mod);
            var resolutionFuture = GenerateResolution(type, futureResolutionStr, mod);

            // If past and future are same, keep only one
            if (resolutionFuture.OrderBy(t => t.Key).Select(t => t.Value)
                .SequenceEqual(resolutionPast.OrderBy(t => t.Key).Select(t => t.Value)))
            {
                if (resolutionPast.Count > 0)
                {
                    AddResolutionFields(res, Constants.Resolve, resolutionPast);
                }
            }
            else
            {
                if (resolutionPast.Count > 0)
                {
                    AddResolutionFields(res, Constants.ResolveToPast, resolutionPast);
                }

                if (resolutionFuture.Count > 0)
                {
                    AddResolutionFields(res, Constants.ResolveToFuture, resolutionFuture);
                }
            }

            // If 'ampm', double our resolution accordingly
            if (!string.IsNullOrEmpty(comment) && comment.Equals(Constants.Comment_AmPm))
            {
                if (res.ContainsKey(Constants.Resolve))
                {
                    ResolveAmpm(res, Constants.Resolve);
                }
                else
                {
                    ResolveAmpm(res, Constants.ResolveToPast);
                    ResolveAmpm(res, Constants.ResolveToFuture);
                }
            }

            // If WeekOf and in CalendarMode, modify the past part of our resolution
            if ((Config.Options & DateTimeOptions.CalendarMode) != 0 &&
                !string.IsNullOrEmpty(comment) && comment.Equals(Constants.Comment_WeekOf))
            {
                ResolveWeekOf(res, Constants.ResolveToPast);
            }

            if (val.TimeZoneResolution != null)
            {
                var timeZoneResolution = new Dictionary <string, string>();
                timeZoneResolution.Add(ResolutionKey.Value, val.TimeZoneResolution.Value);
                timeZoneResolution.Add(Constants.UtcOffsetMinsKey, val.TimeZoneResolution.UtcOffsetMins.ToString());

                AddResolutionFields(res, Constants.ResolveTimeZone, timeZoneResolution);
            }

            foreach (var p in res)
            {
                if (p.Value is Dictionary <string, string> )
                {
                    var value = new Dictionary <string, string>();

                    AddResolutionFields(value, DateTimeResolutionKey.Timex, timex);
                    AddResolutionFields(value, DateTimeResolutionKey.Mod, mod);
                    AddResolutionFields(value, ResolutionKey.Type, typeOutput);
                    AddResolutionFields(value, DateTimeResolutionKey.IsLunar, islunar ? islunar.ToString() : string.Empty);

                    foreach (var q in (Dictionary <string, string>)p.Value)
                    {
                        if (value.ContainsKey(q.Key))
                        {
                            value[q.Key] = q.Value;
                        }
                        else
                        {
                            value.Add(q.Key, q.Value);
                        }
                    }

                    resolutions.Add(value);
                }
            }

            if (resolutionPast.Count == 0 && resolutionFuture.Count == 0 && val.TimeZoneResolution == null)
            {
                var notResolved = new Dictionary <string, string> {
                    {
                        DateTimeResolutionKey.Timex, timex
                    },
                    {
                        ResolutionKey.Type, typeOutput
                    },
                    {
                        ResolutionKey.Value, "not resolved"
                    }
                };

                resolutions.Add(notResolved);
            }

            return(new SortedDictionary <string, object> {
                { ResolutionKey.ValueSet, resolutions }
            });
        }
        // 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 trimedText = 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 == trimedText.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"
                // Uses this invalidFlag to differentiate
                int beginHour;
                int invalidFlag = -1;
                int beginMinute = invalidFlag;
                int beginSecond = invalidFlag;
                int endHour;
                int endMinute = invalidFlag;
                int endSecond = invalidFlag;

                // 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 timepoint has description like 'am' or 'pm'
                if (hasLeft && hasRight)
                {
                    if (hasLeftAm)
                    {
                        if (beginHour >= Constants.HalfDayHourCount)
                        {
                            beginDateTime = beginDateTime.AddHours(-Constants.HalfDayHourCount);
                        }
                    }
                    else if (hasLeftPm)
                    {
                        if (beginHour < Constants.HalfDayHourCount)
                        {
                            beginDateTime = beginDateTime.AddHours(Constants.HalfDayHourCount);
                        }
                    }

                    if (hasRightAm)
                    {
                        if (endHour >= Constants.HalfDayHourCount)
                        {
                            endDateTime = endDateTime.AddHours(-Constants.HalfDayHourCount);
                        }
                    }
                    else if (hasRightPm)
                    {
                        if (endHour < Constants.HalfDayHourCount)
                        {
                            endDateTime = endDateTime.AddHours(Constants.HalfDayHourCount);
                        }
                    }
                }
                // one of the timepoint has description like 'am' or 'pm'
                else if (hasLeft || hasRight)
                {
                    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;
                                if (span.TotalHours >= Constants.HalfDayHourCount)
                                {
                                    endDateTime = endDateTime.AddHours(24);
                                }
                                else
                                {
                                    endDateTime = endDateTime.AddHours(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 (!hasLeft && !hasRight && 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 = FormatUtil.ShortTime(beginDateTime.Hour, beginMinute, beginSecond);
                var endStr   = FormatUtil.ShortTime(endDateTime.Hour, endMinute, endSecond);

                ret.Success = true;

                ret.Timex = $"({beginStr},{endStr},{FormatUtil.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 != invalidFlag || beginSecond != invalidFlag)
                {
                    var er = new ExtractResult()
                    {
                        Start  = time1StartIndex,
                        Length = time1EndIndex - time1StartIndex,
                        Text   = text.Substring(time1StartIndex, time1EndIndex - time1StartIndex),
                        Type   = $"{Constants.SYS_DATETIME_TIME}"
                    };

                    DateTimeParseResult 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 != invalidFlag || endSecond != invalidFlag)
                {
                    var er = new ExtractResult()
                    {
                        Start  = time2StartIndex,
                        Length = time2EndIndex - time2StartIndex,
                        Text   = text.Substring(time2StartIndex, time2EndIndex - time2StartIndex),
                        Type   = $"{Constants.SYS_DATETIME_TIME}"
                    };

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

                ret.Success = true;
            }

            return(ret);
        }
예제 #15
0
        public DateTimeParseResult Parse(ExtractResult er, DateObject refDate)
        {
            var referenceTime = refDate;

            object value = null;

            if (er.Type.Equals(ParserName, StringComparison.Ordinal))
            {
                var innerResult = MergeDateAndTimePeriod(er.Text, referenceTime);
                if (!innerResult.Success)
                {
                    innerResult = MergeTwoTimePoints(er.Text, referenceTime);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseSpecificNight(er.Text, referenceTime);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseNumberWithUnit(er.Text, referenceTime);
                }

                if (innerResult.Success)
                {
                    innerResult.FutureResolution = new Dictionary <string, string>
                    {
                        {
                            TimeTypeConstants.START_DATETIME,
                            DateTimeFormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)innerResult.FutureValue).Item1)
                        },
                        {
                            TimeTypeConstants.END_DATETIME,
                            DateTimeFormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)innerResult.FutureValue).Item2)
                        },
                    };

                    innerResult.PastResolution = new Dictionary <string, string>
                    {
                        {
                            TimeTypeConstants.START_DATETIME,
                            DateTimeFormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)innerResult.PastValue).Item1)
                        },
                        {
                            TimeTypeConstants.END_DATETIME,
                            DateTimeFormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)innerResult.PastValue).Item2)
                        },
                    };

                    value = innerResult;
                }
            }

            var ret = new DateTimeParseResult
            {
                Text          = er.Text,
                Start         = er.Start,
                Length        = er.Length,
                Type          = er.Type,
                Data          = er.Data,
                Value         = value,
                TimexStr      = value == null ? string.Empty : ((DateTimeResolutionResult)value).Timex,
                ResolutionStr = string.Empty,
            };

            return(ret);
        }
예제 #16
0
        private static DateTimeResolutionResult GetAgoLaterResult(
            DateTimeParseResult durationParseResult,
            string afterStr,
            string beforeStr,
            DateObject referenceTime,
            IParser numberParser,
            IDateTimeUtilityConfiguration utilityConfiguration,
            AgoLaterMode mode,
            SwiftDayDelegate swiftDay)
        {
            var ret            = new DateTimeResolutionResult();
            var resultDateTime = referenceTime;
            var timex          = durationParseResult.TimexStr;

            if (((DateTimeResolutionResult)durationParseResult.Value).Mod == Constants.MORE_THAN_MOD)
            {
                ret.Mod = Constants.MORE_THAN_MOD;
            }
            else if (((DateTimeResolutionResult)durationParseResult.Value).Mod == Constants.LESS_THAN_MOD)
            {
                ret.Mod = Constants.LESS_THAN_MOD;
            }

            int    swift = 0;
            bool   isMatch = false, isLater = false;
            string dayStr = null;

            // Item2 is a label identifying the regex defined in Item1
            var agoLaterRegexTuples = new List <(Regex, string)>
            {
                (utilityConfiguration.AgoRegex, Constants.AGO_LABEL),
                (utilityConfiguration.LaterRegex, Constants.LATER_LABEL),
            };

            // AgoRegex and LaterRegex cases
            foreach (var regex in agoLaterRegexTuples)
            {
                // Match in afterStr
                if (MatchingUtil.ContainsAgoLaterIndex(afterStr, regex.Item1, inSuffix: true))
                {
                    isMatch = true;
                    isLater = regex.Item2 == Constants.LATER_LABEL;
                    var match = regex.Item1.Match(afterStr);
                    dayStr = match.Groups["day"].Value;
                }

                if (utilityConfiguration.CheckBothBeforeAfter)
                {
                    // Match split between beforeStr and afterStr
                    if (string.IsNullOrEmpty(dayStr) && isMatch)
                    {
                        var match = regex.Item1.Match(beforeStr + " " + afterStr);
                        dayStr = match.Groups["day"].Value;
                    }

                    // Match in beforeStr
                    if (string.IsNullOrEmpty(dayStr) && MatchingUtil.ContainsAgoLaterIndex(beforeStr, regex.Item1, inSuffix: false))
                    {
                        isMatch = true;
                        isLater = regex.Item2 == Constants.LATER_LABEL;
                        var match = regex.Item1.Match(beforeStr);
                        dayStr = match.Groups["day"].Value;
                    }
                }

                if (isMatch)
                {
                    break;
                }
            }

            // InConnectorRegex cases
            if (!isMatch)
            {
                if (MatchingUtil.ContainsTermIndex(beforeStr, utilityConfiguration.InConnectorRegex))
                {
                    // Match in afterStr
                    isMatch = isLater = true;
                    var match = utilityConfiguration.LaterRegex.Match(afterStr);
                    dayStr = match.Groups["day"].Value;
                }
                else if (utilityConfiguration.CheckBothBeforeAfter && MatchingUtil.ContainsAgoLaterIndex(afterStr, utilityConfiguration.InConnectorRegex, inSuffix: true))
                {
                    // Match in beforeStr
                    isMatch = isLater = true;
                    var match = utilityConfiguration.LaterRegex.Match(beforeStr);
                    dayStr = match.Groups["day"].Value;
                }
            }

            if (isMatch)
            {
                // Handle cases like "3 days before yesterday", "3 days after tomorrow"
                if (!string.IsNullOrEmpty(dayStr))
                {
                    swift = swiftDay(dayStr);
                }

                if (isLater)
                {
                    var yearMatch = utilityConfiguration.SinceYearSuffixRegex.Match(afterStr);
                    if (yearMatch.Success)
                    {
                        var yearString = yearMatch.Groups[Constants.YearGroupName].Value;
                        var yearEr     = new ExtractResult {
                            Text = yearString
                        };
                        var year = Convert.ToInt32((double)(numberParser.Parse(yearEr).Value ?? 0));
                        referenceTime = DateObject.MinValue.SafeCreateFromValue(year, 1, 1);
                    }
                }

                var isFuture = isLater;
                resultDateTime = DurationParsingUtil.ShiftDateTime(timex, referenceTime.AddDays(swift), future: isFuture);

                ((DateTimeResolutionResult)durationParseResult.Value).Mod = isLater ? Constants.AFTER_MOD : Constants.BEFORE_MOD;
            }

            if (resultDateTime != referenceTime)
            {
                if (mode.Equals(AgoLaterMode.Date))
                {
                    ret.Timex = $"{DateTimeFormatUtil.LuisDate(resultDateTime)}";
                }
                else if (mode.Equals(AgoLaterMode.DateTime))
                {
                    ret.Timex = $"{DateTimeFormatUtil.LuisDateTime(resultDateTime)}";
                }

                ret.FutureValue         = ret.PastValue = resultDateTime;
                ret.SubDateTimeEntities = new List <object> {
                    durationParseResult
                };
                ret.Success = true;
            }

            return(ret);
        }
예제 #17
0
        public DateTimeParseResult Parse(ExtractResult er, DateObject refDate)
        {
            var referenceDate = refDate;

            object value = null;

            if (er.Type.Equals(ParserName))
            {
                var innerResult = ParseMonthWithYear(er.Text, referenceDate);
                if (!innerResult.Success)
                {
                    innerResult = ParseSimpleCases(er.Text, referenceDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseOneWordPeriod(er.Text, referenceDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = MergeTwoTimePoints(er.Text, referenceDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseYear(er.Text, referenceDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseNumberWithUnit(er.Text, referenceDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseWeekOfMonth(er.Text, referenceDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseWeekOfYear(er.Text, referenceDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseQuarter(er.Text, referenceDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseSeason(er.Text, referenceDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseWhichWeek(er.Text, referenceDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseWeekOfDate(er.Text, referenceDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseMonthOfDate(er.Text, referenceDate);
                }

                if (innerResult.Success)
                {
                    if (innerResult.FutureValue != null && innerResult.PastValue != null)
                    {
                        innerResult.FutureResolution = new Dictionary <string, string>
                        {
                            {
                                TimeTypeConstants.START_DATE,
                                FormatUtil.FormatDate(((Tuple <DateObject, DateObject>)innerResult.FutureValue).Item1)
                            },
                            {
                                TimeTypeConstants.END_DATE,
                                FormatUtil.FormatDate(((Tuple <DateObject, DateObject>)innerResult.FutureValue).Item2)
                            }
                        };

                        innerResult.PastResolution = new Dictionary <string, string>
                        {
                            {
                                TimeTypeConstants.START_DATE,
                                FormatUtil.FormatDate(((Tuple <DateObject, DateObject>)innerResult.PastValue).Item1)
                            },
                            {
                                TimeTypeConstants.END_DATE,
                                FormatUtil.FormatDate(((Tuple <DateObject, DateObject>)innerResult.PastValue).Item2)
                            }
                        };
                    }
                    else
                    {
                        innerResult.FutureResolution = innerResult.PastResolution = new Dictionary <string, string>();
                    }
                    value = innerResult;
                }
            }

            var ret = new DateTimeParseResult
            {
                Text          = er.Text,
                Start         = er.Start,
                Length        = er.Length,
                Type          = er.Type,
                Data          = er.Data,
                Value         = value,
                TimexStr      = value == null ? "" : ((DateTimeResolutionResult)value).Timex,
                ResolutionStr = ""
            };

            return(ret);
        }
예제 #18
0
        private DateTimeResolutionResult ParseDateTimeAndTimeAlt(ExtractResult er, DateObject referenceTime)
        {
            var ret = new DateTimeResolutionResult();

            // Original type of the extracted entity
            var subType    = ((Dictionary <string, object>)er.Data)[Constants.SubType].ToString();
            var dateTimeEr = new ExtractResult();

            // e.g. {next week Mon} or {Tue}, former--"next week Mon" doesn't contain "context" key
            var           hasContext = false;
            ExtractResult contextEr  = null;

            if (((Dictionary <string, object>)er.Data).ContainsKey(Constants.Context))
            {
                contextEr = (ExtractResult)((Dictionary <string, object>)er.Data)[Constants.Context];
                if (contextEr.Type.Equals(Constants.ContextType_RelativeSuffix, StringComparison.Ordinal))
                {
                    dateTimeEr.Text = $"{er.Text} {contextEr.Text}";
                }
                else
                {
                    dateTimeEr.Text = $"{contextEr.Text} {er.Text}";
                }

                hasContext = true;
            }
            else
            {
                dateTimeEr.Text = er.Text;
            }

            dateTimeEr.Data = er.Data;
            var dateTimePr = new DateTimeParseResult();

            if (subType == Constants.SYS_DATETIME_DATE)
            {
                dateTimeEr.Type = Constants.SYS_DATETIME_DATE;
                dateTimePr      = this.config.DateParser.Parse(dateTimeEr, referenceTime);
            }
            else if (subType == Constants.SYS_DATETIME_TIME)
            {
                if (!hasContext)
                {
                    dateTimeEr.Type = Constants.SYS_DATETIME_TIME;
                    dateTimePr      = this.config.TimeParser.Parse(dateTimeEr, referenceTime);
                }
                else if (contextEr.Type == Constants.SYS_DATETIME_DATE || contextEr.Type == Constants.ContextType_RelativePrefix)
                {
                    // For cases:
                    //      Monday 9 am or 11 am
                    //      next 9 am or 11 am
                    dateTimeEr.Type = Constants.SYS_DATETIME_DATETIME;
                    dateTimePr      = this.config.DateTimeParser.Parse(dateTimeEr, referenceTime);
                }
                else if (contextEr.Type == Constants.ContextType_AmPm)
                {
                    // For cases: in the afternoon 3 o'clock or 5 o'clock
                    dateTimeEr.Type = Constants.SYS_DATETIME_TIME;
                    dateTimePr      = this.config.TimeParser.Parse(dateTimeEr, referenceTime);
                }
            }
            else if (subType == Constants.SYS_DATETIME_DATETIME)
            {
                // "next week Mon 9 am or Tue 1 pm"
                dateTimeEr.Type = Constants.SYS_DATETIME_DATETIME;
                dateTimePr      = this.config.DateTimeParser.Parse(dateTimeEr, referenceTime);
            }
            else if (subType == Constants.SYS_DATETIME_TIMEPERIOD)
            {
                if (!hasContext)
                {
                    dateTimeEr.Type = Constants.SYS_DATETIME_TIMEPERIOD;
                    dateTimePr      = this.config.TimePeriodParser.Parse(dateTimeEr, referenceTime);
                }
                else if (contextEr.Type == Constants.SYS_DATETIME_DATE || contextEr.Type == Constants.ContextType_RelativePrefix)
                {
                    dateTimeEr.Type = Constants.SYS_DATETIME_DATETIMEPERIOD;
                    dateTimePr      = this.config.DateTimePeriodParser.Parse(dateTimeEr, referenceTime);
                }
            }
            else if (subType == Constants.SYS_DATETIME_DATETIMEPERIOD)
            {
                dateTimeEr.Type = Constants.SYS_DATETIME_DATETIMEPERIOD;
                dateTimePr      = this.config.DateTimePeriodParser.Parse(dateTimeEr, referenceTime);
            }
            else if (subType == Constants.SYS_DATETIME_DATEPERIOD)
            {
                dateTimeEr.Type = Constants.SYS_DATETIME_DATEPERIOD;
                dateTimePr      = this.config.DatePeriodParser.Parse(dateTimeEr, referenceTime);
            }

            if (dateTimePr.Value != null)
            {
                ret.FutureValue = ((DateTimeResolutionResult)dateTimePr.Value).FutureValue;
                ret.PastValue   = ((DateTimeResolutionResult)dateTimePr.Value).PastValue;
                ret.Timex       = dateTimePr.TimexStr;

                // Create resolution
                ret = GetResolution(er, dateTimePr, ret);

                ret.Success = true;
            }

            return(ret);
        }
        public DateTimeParseResult Parse(ExtractResult er, DateObject refTime)
        {
            var referenceTime = refTime;

            object value = null;

            if (er.Type.Equals(ParserName))
            {
                var innerResult = MergeDateWithSingleTimePeriod(er.Text, referenceTime);

                if (!innerResult.Success)
                {
                    innerResult = MergeTwoTimePoints(er.Text, referenceTime);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseSpecificTimeOfDay(er.Text, referenceTime);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseDuration(er.Text, referenceTime);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseRelativeUnit(er.Text, referenceTime);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseDateWithPeriodPrefix(er.Text, referenceTime);
                }

                if (!innerResult.Success)
                {
                    // Cases like "today after 2:00pm", "1/1/2015 before 2:00 in the afternoon"
                    innerResult = ParseDateWithTimePeriodSuffix(er.Text, referenceTime);
                }

                if (innerResult.Success)
                {
                    if (!IsBeforeOrAfterMod(innerResult.Mod))
                    {
                        innerResult.FutureResolution = new Dictionary <string, string>
                        {
                            {
                                TimeTypeConstants.START_DATETIME,
                                DateTimeFormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)innerResult.FutureValue).Item1)
                            },
                            {
                                TimeTypeConstants.END_DATETIME,
                                DateTimeFormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)innerResult.FutureValue).Item2)
                            }
                        };

                        innerResult.PastResolution = new Dictionary <string, string>
                        {
                            {
                                TimeTypeConstants.START_DATETIME,
                                DateTimeFormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)innerResult.PastValue).Item1)
                            },
                            {
                                TimeTypeConstants.END_DATETIME,
                                DateTimeFormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)innerResult.PastValue).Item2)
                            }
                        };
                    }
                    else
                    {
                        if (innerResult.Mod == Constants.AFTER_MOD)
                        {
                            // Cases like "1/1/2015 after 2:00" there is no EndTime
                            innerResult.FutureResolution = new Dictionary <string, string>
                            {
                                {
                                    TimeTypeConstants.START_DATETIME,
                                    DateTimeFormatUtil.FormatDateTime((DateObject)(innerResult.FutureValue))
                                }
                            };

                            innerResult.PastResolution = new Dictionary <string, string>
                            {
                                {
                                    TimeTypeConstants.START_DATETIME,
                                    DateTimeFormatUtil.FormatDateTime((DateObject)(innerResult.PastValue))
                                }
                            };
                        }
                        else
                        {
                            // Cases like "1/1/2015 before 5:00 in the afternoon" there is no StartTime
                            innerResult.FutureResolution = new Dictionary <string, string>
                            {
                                {
                                    TimeTypeConstants.END_DATETIME,
                                    DateTimeFormatUtil.FormatDateTime((DateObject)(innerResult.FutureValue))
                                }
                            };

                            innerResult.PastResolution = new Dictionary <string, string>
                            {
                                {
                                    TimeTypeConstants.END_DATETIME,
                                    DateTimeFormatUtil.FormatDateTime((DateObject)(innerResult.PastValue))
                                }
                            };
                        }
                    }

                    value = innerResult;
                }
            }

            var ret = new DateTimeParseResult
            {
                Text          = er.Text,
                Start         = er.Start,
                Length        = er.Length,
                Type          = er.Type,
                Data          = er.Data,
                Value         = value,
                TimexStr      = value == null ? "" : ((DateTimeResolutionResult)value).Timex,
                ResolutionStr = ""
            };

            return(ret);
        }
예제 #20
0
        // merge the entity with its related contexts and then parse the combine text
        private static DateTimeResolutionResult GetResolution(ExtractResult er, DateTimeParseResult pr, DateTimeResolutionResult ret)
        {
            var parentText = (string)((Dictionary <string, object>)er.Data)[ExtendedModelResult.ParentTextKey];
            var type       = pr.Type;

            var singlePointResolution      = string.Empty;
            var pastStartPointResolution   = string.Empty;
            var pastEndPointResolution     = string.Empty;
            var futureStartPointResolution = string.Empty;
            var futureEndPointResolution   = string.Empty;
            var singlePointType            = string.Empty;
            var startPointType             = string.Empty;
            var endPointType = string.Empty;

            if (type == Constants.SYS_DATETIME_DATEPERIOD || type == Constants.SYS_DATETIME_TIMEPERIOD ||
                type == Constants.SYS_DATETIME_DATETIMEPERIOD)
            {
                switch (type)
                {
                case Constants.SYS_DATETIME_DATEPERIOD:
                    startPointType             = TimeTypeConstants.START_DATE;
                    endPointType               = TimeTypeConstants.END_DATE;
                    pastStartPointResolution   = DateTimeFormatUtil.FormatDate(((Tuple <DateObject, DateObject>)ret.PastValue).Item1);
                    pastEndPointResolution     = DateTimeFormatUtil.FormatDate(((Tuple <DateObject, DateObject>)ret.PastValue).Item2);
                    futureStartPointResolution = DateTimeFormatUtil.FormatDate(((Tuple <DateObject, DateObject>)ret.FutureValue).Item1);
                    futureEndPointResolution   = DateTimeFormatUtil.FormatDate(((Tuple <DateObject, DateObject>)ret.FutureValue).Item2);
                    break;

                case Constants.SYS_DATETIME_DATETIMEPERIOD:
                    startPointType = TimeTypeConstants.START_DATETIME;
                    endPointType   = TimeTypeConstants.END_DATETIME;

                    if (ret.PastValue is Tuple <DateObject, DateObject> tuple)
                    {
                        pastStartPointResolution   = DateTimeFormatUtil.FormatDateTime(tuple.Item1);
                        pastEndPointResolution     = DateTimeFormatUtil.FormatDateTime(tuple.Item2);
                        futureStartPointResolution =
                            DateTimeFormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)ret.FutureValue).Item1);
                        futureEndPointResolution =
                            DateTimeFormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)ret.FutureValue).Item2);
                    }
                    else if (ret.PastValue is DateObject datetime)
                    {
                        pastStartPointResolution   = DateTimeFormatUtil.FormatDateTime(datetime);
                        futureStartPointResolution = DateTimeFormatUtil.FormatDateTime((DateObject)ret.FutureValue);
                    }

                    break;

                case Constants.SYS_DATETIME_TIMEPERIOD:
                    startPointType             = TimeTypeConstants.START_TIME;
                    endPointType               = TimeTypeConstants.END_TIME;
                    pastStartPointResolution   = DateTimeFormatUtil.FormatTime(((Tuple <DateObject, DateObject>)ret.PastValue).Item1);
                    pastEndPointResolution     = DateTimeFormatUtil.FormatTime(((Tuple <DateObject, DateObject>)ret.PastValue).Item2);
                    futureStartPointResolution = DateTimeFormatUtil.FormatTime(((Tuple <DateObject, DateObject>)ret.FutureValue).Item1);
                    futureEndPointResolution   = DateTimeFormatUtil.FormatTime(((Tuple <DateObject, DateObject>)ret.FutureValue).Item2);
                    break;
                }
            }
            else
            {
                switch (type)
                {
                case Constants.SYS_DATETIME_DATE:
                    singlePointType       = TimeTypeConstants.DATE;
                    singlePointResolution = DateTimeFormatUtil.FormatDate((DateObject)ret.FutureValue);
                    break;

                case Constants.SYS_DATETIME_DATETIME:
                    singlePointType       = TimeTypeConstants.DATETIME;
                    singlePointResolution = DateTimeFormatUtil.FormatDateTime((DateObject)ret.FutureValue);
                    break;

                case Constants.SYS_DATETIME_TIME:
                    singlePointType       = TimeTypeConstants.TIME;
                    singlePointResolution = DateTimeFormatUtil.FormatTime((DateObject)ret.FutureValue);
                    break;
                }
            }

            ret.FutureResolution = new Dictionary <string, string>();
            ret.PastResolution   = new Dictionary <string, string>();

            if (!string.IsNullOrEmpty(futureStartPointResolution))
            {
                ret.FutureResolution.Add(startPointType, futureStartPointResolution);
            }

            if (!string.IsNullOrEmpty(futureEndPointResolution))
            {
                ret.FutureResolution.Add(endPointType, futureEndPointResolution);
            }

            if (!string.IsNullOrEmpty(pastStartPointResolution))
            {
                ret.PastResolution.Add(startPointType, pastStartPointResolution);
            }

            if (!string.IsNullOrEmpty(pastEndPointResolution))
            {
                ret.PastResolution.Add(endPointType, pastEndPointResolution);
            }

            if (!string.IsNullOrEmpty(singlePointResolution))
            {
                ret.FutureResolution.Add(singlePointType, singlePointResolution);
                ret.PastResolution.Add(singlePointType, singlePointResolution);
            }

            if (!string.IsNullOrEmpty(parentText))
            {
                ret.FutureResolution.Add(ExtendedModelResult.ParentTextKey, parentText);
                ret.PastResolution.Add(ExtendedModelResult.ParentTextKey, parentText);
            }

            if (((DateTimeResolutionResult)pr.Value).Mod != null)
            {
                ret.Mod = ((DateTimeResolutionResult)pr.Value).Mod;
            }

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

            return(ret);
        }
예제 #21
0
        public DateTimeParseResult Parse(ExtractResult er, DateObject refTime)
        {
            var referenceTime      = refTime;
            DateTimeParseResult pr = null;

            var originText = er.Text;

            if ((this.Config.Options & DateTimeOptions.EnablePreview) != 0)
            {
                er.Text    = MatchingUtil.PreProcessTextRemoveSuperfluousWords(er.Text, Config.SuperfluousWordMatcher, out var _);
                er.Length += er.Text.Length - originText.Length;
            }

            // Push, save the MOD string
            bool hasBefore = false, hasAfter = false, hasSince = false, hasAround = false, hasDateAfter = false;

            // "InclusiveModifier" means MOD should include the start/end time
            // For example, cases like "on or later than", "earlier than or in" have inclusive modifier
            var hasInclusiveModifier = false;
            var modStr      = string.Empty;
            var beforeMatch = Config.BeforeRegex.MatchBegin(er.Text, trim: true);
            var afterMatch  = Config.AfterRegex.MatchBegin(er.Text, trim: true);
            var sinceMatch  = Config.SinceRegex.MatchBegin(er.Text, trim: true);
            var aroundMatch = Config.AroundRegex.MatchBegin(er.Text, trim: true);

            if (beforeMatch.Success)
            {
                hasBefore  = true;
                er.Start  += beforeMatch.Length;
                er.Length -= beforeMatch.Length;
                er.Text    = er.Text.Substring(beforeMatch.Length);
                modStr     = beforeMatch.Value;

                if (!string.IsNullOrEmpty(beforeMatch.Groups["include"].Value))
                {
                    hasInclusiveModifier = true;
                }
            }
            else if (afterMatch.Success)
            {
                hasAfter   = true;
                er.Start  += afterMatch.Length;
                er.Length -= afterMatch.Length;
                er.Text    = er.Text.Substring(afterMatch.Length);
                modStr     = afterMatch.Value;

                if (!string.IsNullOrEmpty(afterMatch.Groups["include"].Value))
                {
                    hasInclusiveModifier = true;
                }
            }
            else if (sinceMatch.Success)
            {
                hasSince   = true;
                er.Start  += sinceMatch.Length;
                er.Length -= sinceMatch.Length;
                er.Text    = er.Text.Substring(sinceMatch.Length);
                modStr     = sinceMatch.Value;
            }
            else if (aroundMatch.Success)
            {
                hasAround  = true;
                er.Start  += aroundMatch.Length;
                er.Length -= aroundMatch.Length;
                er.Text    = er.Text.Substring(aroundMatch.Length);
                modStr     = aroundMatch.Value;
            }
            else if ((er.Type.Equals(Constants.SYS_DATETIME_DATEPERIOD, StringComparison.Ordinal) && Config.YearRegex.Match(er.Text).Success) ||
                     er.Type.Equals(Constants.SYS_DATETIME_DATE, StringComparison.Ordinal) ||
                     er.Type.Equals(Constants.SYS_DATETIME_TIME, StringComparison.Ordinal))
            {
                // This has to be put at the end of the if, or cases like "before 2012" and "after 2012" would fall into this
                // 2012 or after/above
                // 3 pm or later
                var match = Config.SuffixAfter.MatchEnd(er.Text, trim: true);
                if (match.Success)
                {
                    hasDateAfter = true;
                    er.Length   -= match.Length;
                    er.Text      = er.Text.Substring(0, er.Length ?? 0);
                    modStr       = match.Value;
                }
            }

            pr = ParseResult(er, referenceTime);
            if (pr == null)
            {
                return(null);
            }

            // Pop, restore the MOD string
            if (hasBefore && pr.Value != null)
            {
                pr.Length += modStr.Length;
                pr.Start  -= modStr.Length;
                pr.Text    = modStr + pr.Text;
                var val = (DateTimeResolutionResult)pr.Value;

                val.Mod = CombineMod(val.Mod, !hasInclusiveModifier ? Constants.BEFORE_MOD : Constants.UNTIL_MOD);

                pr.Value = val;
            }

            if (hasAfter && pr.Value != null)
            {
                pr.Length += modStr.Length;
                pr.Start  -= modStr.Length;
                pr.Text    = modStr + pr.Text;
                var val = (DateTimeResolutionResult)pr.Value;

                if (!hasInclusiveModifier)
                {
                    val.Mod = CombineMod(val.Mod, Constants.AFTER_MOD);
                }
                else
                {
                    val.Mod = CombineMod(val.Mod, Constants.SINCE_MOD);
                }

                pr.Value = val;
            }

            if (hasSince && pr.Value != null)
            {
                pr.Length += modStr.Length;
                pr.Start  -= modStr.Length;
                pr.Text    = modStr + pr.Text;
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod  = CombineMod(val.Mod, Constants.SINCE_MOD);
                pr.Value = val;
            }

            if (hasAround && pr.Value != null)
            {
                pr.Length += modStr.Length;
                pr.Start  -= modStr.Length;
                pr.Text    = modStr + pr.Text;
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod  = CombineMod(val.Mod, Constants.APPROX_MOD);
                pr.Value = val;
            }

            if (hasDateAfter && pr.Value != null)
            {
                pr.Length += modStr.Length;
                pr.Text    = pr.Text + modStr;
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod  = CombineMod(val.Mod, Constants.SINCE_MOD);
                pr.Value = val;
                hasSince = true;
            }

            // For cases like "3 pm or later on monday"
            if (pr.Value != null && Config.SuffixAfter.Match(pr.Text)?.Index != 0 &&
                pr.Type.Equals(Constants.SYS_DATETIME_DATETIME, StringComparison.Ordinal))
            {
                var val = (DateTimeResolutionResult)pr.Value;
                val.Mod  = CombineMod(val.Mod, Constants.SINCE_MOD);
                pr.Value = val;
                hasSince = true;
            }

            if ((Config.Options & DateTimeOptions.SplitDateAndTime) != 0 &&
                ((DateTimeResolutionResult)pr?.Value)?.SubDateTimeEntities != null)
            {
                pr.Value = DateTimeResolutionForSplit(pr);
            }
            else
            {
                var hasRangeChangingMod = hasBefore || hasAfter || hasSince;
                if (pr.Value != null)
                {
                    ((DateTimeResolutionResult)pr.Value).HasRangeChangingMod = hasRangeChangingMod;
                }

                pr = SetParseResult(pr, hasRangeChangingMod);
            }

            // In this version, ExperimentalMode only cope with the "IncludePeriodEnd" case
            if ((this.Config.Options & DateTimeOptions.ExperimentalMode) != 0)
            {
                if (pr?.Metadata != null && pr.Metadata.PossiblyIncludePeriodEnd)
                {
                    pr = SetInclusivePeriodEnd(pr);
                }
            }

            if ((this.Config.Options & DateTimeOptions.EnablePreview) != 0)
            {
                if (pr != null)
                {
                    pr.Length += originText.Length - pr.Text.Length;
                    pr.Text    = originText;
                }
            }

            return(pr);
        }
예제 #22
0
        public DateTimeParseResult Parse(ExtractResult er, DateObject refTime)
        {
            var referenceTime = refTime;

            object value = null;

            if (er.Type.Equals(ParserName, StringComparison.Ordinal))
            {
                var innerResult = ParseMergedDuration(er.Text, referenceTime);
                if (!innerResult.Success)
                {
                    innerResult = ParseNumberWithUnit(er.Text, referenceTime);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseImplicitDuration(er.Text, referenceTime);
                }

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

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

                    value = innerResult;
                }
            }

            var res = (DateTimeResolutionResult)value;

            if (res != null && er.Data != null)
            {
                if (er.Data.Equals(Constants.MORE_THAN_MOD))
                {
                    res.Mod = Constants.MORE_THAN_MOD;
                }
                else if (er.Data.Equals(Constants.LESS_THAN_MOD))
                {
                    res.Mod = Constants.LESS_THAN_MOD;
                }
            }

            var ret = new DateTimeParseResult
            {
                Text          = er.Text,
                Start         = er.Start,
                Length        = er.Length,
                Type          = er.Type,
                Data          = er.Data,
                Value         = value,
                TimexStr      = value == null ? string.Empty : ((DateTimeResolutionResult)value).Timex,
                ResolutionStr = string.Empty,
            };

            return(ret);
        }
예제 #23
0
        private DateTimeParseResult ParseResult(ExtractResult extractResult, DateObject referenceTime)
        {
            DateTimeParseResult parseResult = null;

            switch (extractResult.Type)
            {
            case Constants.SYS_DATETIME_DATE:
                if (extractResult.Metadata != null && extractResult.Metadata.IsHoliday)
                {
                    parseResult = Config.HolidayParser.Parse(extractResult, referenceTime);
                }
                else
                {
                    parseResult = this.Config.DateParser.Parse(extractResult, referenceTime);
                }

                break;

            case Constants.SYS_DATETIME_TIME:
                parseResult = this.Config.TimeParser.Parse(extractResult, referenceTime);

                break;

            case Constants.SYS_DATETIME_DATETIME:
                parseResult = this.Config.DateTimeParser.Parse(extractResult, referenceTime);

                break;

            case Constants.SYS_DATETIME_DATEPERIOD:
                parseResult = this.Config.DatePeriodParser.Parse(extractResult, referenceTime);

                break;

            case Constants.SYS_DATETIME_TIMEPERIOD:
                parseResult = this.Config.TimePeriodParser.Parse(extractResult, referenceTime);

                break;

            case Constants.SYS_DATETIME_DATETIMEPERIOD:
                parseResult = this.Config.DateTimePeriodParser.Parse(extractResult, referenceTime);

                break;

            case Constants.SYS_DATETIME_DURATION:
                parseResult = this.Config.DurationParser.Parse(extractResult, referenceTime);

                break;

            case Constants.SYS_DATETIME_SET:
                parseResult = this.Config.SetParser.Parse(extractResult, referenceTime);

                break;

            case Constants.SYS_DATETIME_DATETIMEALT:
                parseResult = this.Config.DateTimeAltParser.Parse(extractResult, referenceTime);

                break;

            case Constants.SYS_DATETIME_TIMEZONE:
                if ((Config.Options & DateTimeOptions.EnablePreview) != 0)
                {
                    parseResult = this.Config.TimeZoneParser.Parse(extractResult, referenceTime);
                }

                break;

            default:
                return(null);
            }

            return(parseResult);
        }
예제 #24
0
 private static string GetParentText(DateTimeParseResult parsedDateTime)
 {
     return(((Dictionary <string, object>)parsedDateTime.Data)[ExtendedModelResult.ParentTextKey].ToString());
 }
        public SortedDictionary <string, object> DateTimeResolution(DateTimeParseResult slot, bool hasBefore, bool hasAfter, bool hasSince)
        {
            var resolutions = new List <Dictionary <string, string> >();
            var res         = new Dictionary <string, object>();

            var type       = slot.Type;
            var typeOutput = DetermineDateTimeType(slot.Type, hasBefore, hasAfter, hasSince);
            var timex      = slot.TimexStr;

            var val = (DateTimeResolutionResult)slot.Value;

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

            var isLunar = val.IsLunar;
            var mod     = val.Mod;
            var comment = val.Comment;

            if (!string.IsNullOrEmpty(timex))
            {
                res.Add(DateTimeResolutionKey.Timex, timex);
            }

            if (!string.IsNullOrEmpty(comment))
            {
                res.Add(Constants.Comment, comment);
            }

            if (!string.IsNullOrEmpty(mod))
            {
                res.Add(DateTimeResolutionKey.Mod, mod);
            }

            if (!string.IsNullOrEmpty(type))
            {
                res.Add(ResolutionKey.Type, typeOutput);
            }

            var pastResolutionStr   = ((DateTimeResolutionResult)slot.Value).PastResolution;
            var futureResolutionStr = ((DateTimeResolutionResult)slot.Value).FutureResolution;

            var resolutionPast   = GenerateResolution(type, pastResolutionStr, mod);
            var resolutionFuture = GenerateResolution(type, futureResolutionStr, mod);

            // if past and future are same, keep only one
            if (resolutionFuture.OrderBy(t => t.Key).Select(t => t.Value).SequenceEqual(resolutionPast.OrderBy(t => t.Key).Select(t => t.Value)))
            {
                if (resolutionPast.Count > 0)
                {
                    res.Add(Constants.Resolve, resolutionPast);
                }
            }
            else
            {
                if (resolutionPast.Count > 0)
                {
                    res.Add(Constants.ResolveToPast, resolutionPast);
                }

                if (resolutionFuture.Count > 0)
                {
                    res.Add(Constants.ResolveToFuture, resolutionFuture);
                }
            }

            // if ampm, double our resolution accordingly
            if (!string.IsNullOrEmpty(comment) && comment.Equals(Constants.Comment_AmPm))
            {
                if (res.ContainsKey(Constants.Resolve))
                {
                    ResolveAmpm(res, Constants.Resolve);
                }
                else
                {
                    ResolveAmpm(res, Constants.ResolveToPast);
                    ResolveAmpm(res, Constants.ResolveToFuture);
                }
            }

            if (isLunar)
            {
                res.Add(DateTimeResolutionKey.IsLunar, isLunar);
            }

            foreach (var p in res)
            {
                if (p.Value is Dictionary <string, string> dictionary)
                {
                    var value = new Dictionary <string, string>();

                    if (!string.IsNullOrEmpty(timex))
                    {
                        value.Add(DateTimeResolutionKey.Timex, timex);
                    }

                    if (!string.IsNullOrEmpty(mod))
                    {
                        value.Add(DateTimeResolutionKey.Mod, mod);
                    }

                    if (!string.IsNullOrEmpty(type))
                    {
                        value.Add(ResolutionKey.Type, typeOutput);
                    }

                    foreach (var q in dictionary)
                    {
                        if (value.ContainsKey(q.Key))
                        {
                            value[q.Key] = q.Value;
                        }
                        else
                        {
                            value.Add(q.Key, q.Value);
                        }
                    }

                    resolutions.Add(value);
                }
            }

            if (resolutionPast.Count == 0 && resolutionFuture.Count == 0)
            {
                var notResolved = new Dictionary <string, string>
                {
                    {
                        DateTimeResolutionKey.Timex, timex
                    },
                    {
                        ResolutionKey.Type, typeOutput
                    },
                    {
                        ResolutionKey.Value, "not resolved"
                    },
                };

                resolutions.Add(notResolved);
            }

            return(new SortedDictionary <string, object> {
                { ResolutionKey.ValueSet, resolutions }
            });
        }
예제 #26
0
        public DateTimeParseResult Parse(ExtractResult er, DateObject refDate)
        {
            object value = null;

            if (er.Type.Equals(ParserName))
            {
                var innerResult = ParseEachUnit(er.Text);
                if (!innerResult.Success)
                {
                    innerResult = ParseEachDuration(er.Text, refDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParserTimeEveryday(er.Text, refDate);
                }

                // NOTE: Please do not change the order of following function
                // datetimeperiod>dateperiod>timeperiod>datetime>date>time
                if (!innerResult.Success)
                {
                    innerResult = ParseEach(config.DateTimePeriodExtractor, config.DateTimePeriodParser, er.Text, refDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseEach(config.DatePeriodExtractor, config.DatePeriodParser, er.Text, refDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseEach(config.TimePeriodExtractor, config.TimePeriodParser, er.Text, refDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseEach(config.DateTimeExtractor, config.DateTimeParser, er.Text, refDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseEach(config.DateExtractor, config.DateParser, er.Text, refDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseEach(config.TimeExtractor, config.TimeParser, er.Text, refDate);
                }

                if (innerResult.Success)
                {
                    innerResult.FutureResolution = new Dictionary <string, string>
                    {
                        { TimeTypeConstants.SET, (string)innerResult.FutureValue },
                    };

                    innerResult.PastResolution = new Dictionary <string, string>
                    {
                        { TimeTypeConstants.SET, (string)innerResult.PastValue },
                    };

                    value = innerResult;
                }
            }

            var ret = new DateTimeParseResult
            {
                Text          = er.Text,
                Start         = er.Start,
                Length        = er.Length,
                Type          = er.Type,
                Data          = er.Data,
                Value         = value,
                TimexStr      = value == null ? string.Empty : ((DateTimeResolutionResult)value).Timex,
                ResolutionStr = string.Empty,
            };

            return(ret);
        }
예제 #27
0
        public DateTimeParseResult Parse(ExtractResult er, DateObject reference)
        {
            var referenceDate = reference;

            object value = null;

            if (er.Type.Equals(ParserName))
            {
                var innerResult = ParseBasicRegexMatch(er.Text, referenceDate);
                if (!innerResult.Success)
                {
                    innerResult = ParseImplicitDate(er.Text, referenceDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseWeekdayOfMonth(er.Text, referenceDate);
                }

                if (!innerResult.Success)
                {
                    innerResult = ParseDurationWithAgoAndLater(er.Text, referenceDate);
                }

                // NumberWithMonth must be the second last one, because it only need to find a number and a month to get a "success"
                if (!innerResult.Success)
                {
                    innerResult = ParseNumberWithMonth(er.Text, referenceDate);
                }

                // SingleNumber last one
                if (!innerResult.Success)
                {
                    innerResult = ParseSingleNumber(er.Text, referenceDate);
                }

                if (innerResult.Success)
                {
                    innerResult.FutureResolution = new Dictionary <string, string>
                    {
                        { TimeTypeConstants.DATE, DateTimeFormatUtil.FormatDate((DateObject)innerResult.FutureValue) }
                    };

                    innerResult.PastResolution = new Dictionary <string, string>
                    {
                        { TimeTypeConstants.DATE, DateTimeFormatUtil.FormatDate((DateObject)innerResult.PastValue) }
                    };

                    value = innerResult;
                }
            }

            var ret = new DateTimeParseResult
            {
                Text          = er.Text,
                Start         = er.Start,
                Length        = er.Length,
                Type          = er.Type,
                Data          = er.Data,
                Value         = value,
                TimexStr      = value == null ? "" : ((DateTimeResolutionResult)value).Timex,
                ResolutionStr = ""
            };

            return(ret);
        }
예제 #28
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);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            ret.Success = true;
            return(ret);
        }
        private DateTimeResolutionResult MergeTwoTimePoints(string text, DateObject referenceTime)
        {
            var ret = new DateTimeResolutionResult();
            DateTimeParseResult pr1 = null, pr2 = null;
            var validTimeNumber = false;

            var ers = this.config.TimeExtractor.Extract(text, referenceTime);

            if (ers.Count != 2)
            {
                if (ers.Count == 1)
                {
                    var numErs = this.config.IntegerExtractor.Extract(text);

                    foreach (var num in numErs)
                    {
                        int midStrBegin = 0, midStrEnd = 0;
                        // ending number
                        if (num.Start > ers[0].Start + ers[0].Length)
                        {
                            midStrBegin = ers[0].Start + ers[0].Length ?? 0;
                            midStrEnd   = num.Start - midStrBegin ?? 0;
                        }
                        else if (num.Start + num.Length < ers[0].Start)
                        {
                            midStrBegin = num.Start + num.Length ?? 0;
                            midStrEnd   = ers[0].Start - midStrBegin ?? 0;
                        }

                        // check if the middle string between the time point and the valid number is a connect string.
                        var middleStr = text.Substring(midStrBegin, midStrEnd);
                        var tillMatch = this.config.TillRegex.Match(middleStr);
                        if (tillMatch.Success)
                        {
                            num.Data = null;
                            num.Type = Constants.SYS_DATETIME_TIME;
                            ers.Add(num);
                            validTimeNumber = true;
                            break;
                        }
                    }

                    ers.Sort((x, y) => (x.Start - y.Start ?? 0));
                }

                if (!validTimeNumber)
                {
                    return(ret);
                }
            }

            pr1 = this.config.TimeParser.Parse(ers[0], referenceTime);
            pr2 = this.config.TimeParser.Parse(ers[1], referenceTime);

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

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

            var beginTime = (DateObject)((DateTimeResolutionResult)pr1.Value).FutureValue;
            var endTime   = (DateObject)((DateTimeResolutionResult)pr2.Value).FutureValue;

            if (!string.IsNullOrEmpty(ampmStr2) && ampmStr2.EndsWith(Constants.Comment_AmPm) && endTime <= beginTime && endTime.AddHours(Constants.HalfDayHourCount) > beginTime)
            {
                endTime = endTime.AddHours(Constants.HalfDayHourCount);
                ((DateTimeResolutionResult)pr2.Value).FutureValue = endTime;
                pr2.TimexStr = $"T{endTime.Hour}";
                if (endTime.Minute > 0)
                {
                    pr2.TimexStr = $"{pr2.TimexStr}:{endTime.Minute}";
                }
            }

            if (!string.IsNullOrEmpty(ampmStr1) && ampmStr1.EndsWith(Constants.Comment_AmPm) && endTime > beginTime.AddHours(Constants.HalfDayHourCount))
            {
                beginTime = beginTime.AddHours(Constants.HalfDayHourCount);
                ((DateTimeResolutionResult)pr1.Value).FutureValue = beginTime;
                pr1.TimexStr = $"T{beginTime.Hour}";
                if (beginTime.Minute > 0)
                {
                    pr1.TimexStr = $"{pr1.TimexStr}:{beginTime.Minute}";
                }
            }

            if (endTime < beginTime)
            {
                endTime = endTime.AddDays(1);
            }

            var minutes = (endTime - beginTime).Minutes;
            var hours   = (endTime - beginTime).Hours;

            ret.Timex = $"({pr1.TimexStr},{pr2.TimexStr}," +
                        $"PT{(hours > 0 ? hours + "H" : "")}{(minutes > 0 ? minutes + "M" : "")})";
            ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginTime, endTime);
            ret.Success     = true;

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

            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.SubDateTimeEntities = new List <object> {
                pr1, pr2
            };

            return(ret);
        }
예제 #30
0
        private static DateTimeResolutionResult GetAgoLaterResult(
            DateTimeParseResult durationParseResult,
            string afterStr,
            string beforeStr,
            DateObject referenceTime,
            IParser numberParser,
            IDateTimeUtilityConfiguration utilityConfiguration,
            AgoLaterMode mode,
            SwiftDayDelegate swiftDay)
        {
            var ret            = new DateTimeResolutionResult();
            var resultDateTime = referenceTime;
            var timex          = durationParseResult.TimexStr;

            if (((DateTimeResolutionResult)durationParseResult.Value).Mod == Constants.MORE_THAN_MOD)
            {
                ret.Mod = Constants.MORE_THAN_MOD;
            }
            else if (((DateTimeResolutionResult)durationParseResult.Value).Mod == Constants.LESS_THAN_MOD)
            {
                ret.Mod = Constants.LESS_THAN_MOD;
            }

            if (MatchingUtil.ContainsAgoLaterIndex(afterStr, utilityConfiguration.AgoRegex))
            {
                var match = utilityConfiguration.AgoRegex.Match(afterStr);
                var swift = 0;

                // Handle cases like "3 days before yesterday"
                if (match.Success && !string.IsNullOrEmpty(match.Groups["day"].Value))
                {
                    swift = swiftDay(match.Groups["day"].Value);
                }
                else if (utilityConfiguration.CheckBothBeforeAfter && match.Success && !MatchingUtil.ContainsAgoLaterIndexInBeforeString(beforeStr, utilityConfiguration.AgoRegex))
                {
                    match = utilityConfiguration.AgoRegex.Match(beforeStr + " " + afterStr);
                    if (match.Success && !string.IsNullOrEmpty(match.Groups["day"].Value))
                    {
                        swift = swiftDay(match.Groups["day"].Value);
                    }
                }

                resultDateTime = DurationParsingUtil.ShiftDateTime(timex, referenceTime.AddDays(swift), false);

                ((DateTimeResolutionResult)durationParseResult.Value).Mod = Constants.BEFORE_MOD;
            }
            else if (utilityConfiguration.CheckBothBeforeAfter && MatchingUtil.ContainsAgoLaterIndexInBeforeString(beforeStr, utilityConfiguration.AgoRegex))
            {
                var match = utilityConfiguration.AgoRegex.Match(beforeStr);
                var swift = 0;

                // Handle cases like "3 days before yesterday"
                if (match.Success && !string.IsNullOrEmpty(match.Groups["day"].Value))
                {
                    swift = swiftDay(match.Groups["day"].Value);
                }

                resultDateTime = DurationParsingUtil.ShiftDateTime(timex, referenceTime.AddDays(swift), false);

                ((DateTimeResolutionResult)durationParseResult.Value).Mod = Constants.BEFORE_MOD;
            }
            else if (MatchingUtil.ContainsAgoLaterIndex(afterStr, utilityConfiguration.LaterRegex) ||
                     MatchingUtil.ContainsTermIndex(beforeStr, utilityConfiguration.InConnectorRegex) ||
                     (utilityConfiguration.CheckBothBeforeAfter && MatchingUtil.ContainsAgoLaterIndexInBeforeString(beforeStr, utilityConfiguration.LaterRegex)))
            {
                var match = utilityConfiguration.LaterRegex.Match(afterStr);
                var swift = 0;

                if (utilityConfiguration.CheckBothBeforeAfter && MatchingUtil.ContainsAgoLaterIndexInBeforeString(beforeStr, utilityConfiguration.LaterRegex) && string.IsNullOrEmpty(match.Groups["day"].Value))
                {
                    match = utilityConfiguration.LaterRegex.Match(beforeStr);
                }

                // Handle cases like "3 days after tomorrow"
                if (match.Success && !string.IsNullOrEmpty(match.Groups["day"].Value))
                {
                    swift = swiftDay(match.Groups["day"].Value);
                }

                var yearMatch = utilityConfiguration.SinceYearSuffixRegex.Match(afterStr);
                if (yearMatch.Success)
                {
                    var yearString = yearMatch.Groups[Constants.YearGroupName].Value;
                    var yearEr     = new ExtractResult {
                        Text = yearString
                    };
                    var year = Convert.ToInt32((double)(numberParser.Parse(yearEr).Value ?? 0));
                    referenceTime = DateObject.MinValue.SafeCreateFromValue(year, 1, 1);
                }

                resultDateTime = DurationParsingUtil.ShiftDateTime(timex, referenceTime.AddDays(swift), true);

                ((DateTimeResolutionResult)durationParseResult.Value).Mod = Constants.AFTER_MOD;
            }
            else if (utilityConfiguration.CheckBothBeforeAfter && (MatchingUtil.ContainsAgoLaterIndexInBeforeString(beforeStr, utilityConfiguration.LaterRegex) ||
                                                                   MatchingUtil.ContainsAgoLaterIndex(afterStr, utilityConfiguration.InConnectorRegex) ||
                                                                   MatchingUtil.ContainsAgoLaterIndex(afterStr, utilityConfiguration.LaterRegex)))
            {
                // Check also beforeStr
                var match = utilityConfiguration.LaterRegex.Match(beforeStr);
                var swift = 0;

                if (MatchingUtil.ContainsAgoLaterIndex(afterStr, utilityConfiguration.LaterRegex) && string.IsNullOrEmpty(match.Groups["day"].Value))
                {
                    match = utilityConfiguration.LaterRegex.Match(beforeStr);
                }

                // Handle cases like "3 days after tomorrow"
                if (match.Success && !string.IsNullOrEmpty(match.Groups["day"].Value))
                {
                    swift = swiftDay(match.Groups["day"].Value);
                }

                var yearMatch = utilityConfiguration.SinceYearSuffixRegex.Match(beforeStr);
                if (yearMatch.Success)
                {
                    var yearString = yearMatch.Groups[Constants.YearGroupName].Value;
                    var yearEr     = new ExtractResult {
                        Text = yearString
                    };
                    var year = Convert.ToInt32((double)(numberParser.Parse(yearEr).Value ?? 0));
                    referenceTime = DateObject.MinValue.SafeCreateFromValue(year, 1, 1);
                }

                resultDateTime = DurationParsingUtil.ShiftDateTime(timex, referenceTime.AddDays(swift), true);

                ((DateTimeResolutionResult)durationParseResult.Value).Mod = Constants.AFTER_MOD;
            }

            if (resultDateTime != referenceTime)
            {
                if (mode.Equals(AgoLaterMode.Date))
                {
                    ret.Timex = $"{DateTimeFormatUtil.LuisDate(resultDateTime)}";
                }
                else if (mode.Equals(AgoLaterMode.DateTime))
                {
                    ret.Timex = $"{DateTimeFormatUtil.LuisDateTime(resultDateTime)}";
                }

                ret.FutureValue         = ret.PastValue = resultDateTime;
                ret.SubDateTimeEntities = new List <object> {
                    durationParseResult
                };
                ret.Success = true;
            }

            return(ret);
        }