private DateTimeResolutionResult ParseQuarter(string text, DateObject referenceDate)
        {
            var ret   = new DateTimeResolutionResult();
            var match = this.config.QuarterRegex.Match(text);

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

            var cardinalStr = match.Groups["cardinal"].Value.ToLower();
            var yearStr     = match.Groups["year"].Value.ToLower();
            var orderStr    = match.Groups["order"].Value.ToLower();

            int year;

            if (!string.IsNullOrEmpty(yearStr))
            {
                year = int.Parse(yearStr);
            }
            else
            {
                var swift = this.config.GetSwiftYear(orderStr);
                if (swift < -1)
                {
                    return(ret);
                }
                year = referenceDate.Year + swift;
            }
            var quarterNum = this.config.CardinalMap[cardinalStr];
            var beginDate  = new DateObject(year, quarterNum * 3 - 2, 1);
            var endDate    = new DateObject(year, quarterNum * 3 + 1, 1);

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

            return(ret);
        }
Example #2
0
        // handle cases like "the 27th". In the extractor, only the unmatched weekday and date will output this date.
        private DateTimeResolutionResult ParseSingleNumber(string text, DateObject referenceDate)
        {
            var ret = new DateTimeResolutionResult();

            var trimedText = text.Trim().ToLower();
            int month = referenceDate.Month, day = 0, year = referenceDate.Year;

            var er = this.config.OrdinalExtractor.Extract(trimedText);

            if (er.Count == 0)
            {
                er = this.config.IntegerExtractor.Extract(trimedText);
            }

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

            day = Convert.ToInt32((double)(this.config.NumberParser.Parse(er[0]).Value ?? 0));

            // for LUIS format value string
            ret.Timex = FormatUtil.LuisDate(-1, -1, day);
            var pastDate   = DateObject.MinValue.SafeCreateFromValue(year, month, day);
            var futureDate = DateObject.MinValue.SafeCreateFromValue(year, month, day);

            if (!futureDate.Equals(DateObject.MinValue) && futureDate < referenceDate)
            {
                futureDate = futureDate.AddMonths(1);
            }

            if (!pastDate.Equals(DateObject.MinValue) && pastDate >= referenceDate)
            {
                pastDate = pastDate.AddMonths(-1);
            }

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

            return(ret);
        }
        private DateTimeResolutionResult ParseQuarter(string text, DateObject referenceDate)
        {
            var ret   = new DateTimeResolutionResult();
            var match = this.config.QuarterRegex.Match(text);

            if (!(match.Success && match.Length == text.Length))
            {
                match = this.config.QuarterRegexYearFront.Match(text);
            }

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

            var cardinalStr = match.Groups["cardinal"].Value.ToLower();
            var orderStr    = match.Groups["order"].Value.ToLower();

            int year = ((BaseDateExtractor)this.config.DateExtractor).GetYearFromText(match);

            if (year == Constants.InvalidYear)
            {
                var swift = this.config.GetSwiftYear(orderStr);
                if (swift < -1)
                {
                    return(ret);
                }
                year = referenceDate.Year + swift;
            }

            var quarterNum = this.config.CardinalMap[cardinalStr];
            var beginDate  = DateObject.MinValue.SafeCreateFromValue(year, quarterNum * 3 - 2, 1);
            var endDate    = DateObject.MinValue.SafeCreateFromValue(year, quarterNum * 3 + 1, 1);

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

            return(ret);
        }
Example #4
0
        public static string GenerateDatePeriodTimex(DateObject begin, DateObject end, DatePeriodTimexType timexType, DateObject alternativeBegin = default(DateObject), DateObject alternativeEnd = default(DateObject))
        {
            var equalDurationLength = ((end - begin) == (alternativeEnd - alternativeBegin));

            if (alternativeBegin.IsDefaultValue() || alternativeEnd.IsDefaultValue())
            {
                equalDurationLength = true;
            }

            var unitCount = "XX";

            if (equalDurationLength)
            {
                switch (timexType)
                {
                case DatePeriodTimexType.ByDay:
                    unitCount = (end - begin).TotalDays.ToString(CultureInfo.InvariantCulture);
                    break;

                case DatePeriodTimexType.ByWeek:
                    unitCount = ((end - begin).TotalDays / 7).ToString(CultureInfo.InvariantCulture);
                    break;

                case DatePeriodTimexType.ByMonth:
                    unitCount = (((end.Year - begin.Year) * 12) + (end.Month - begin.Month)).ToString();
                    break;

                default:
                    unitCount = ((end.Year - begin.Year) + (end.Month - begin.Month) / 12.0).ToString(CultureInfo.InvariantCulture);
                    break;
                }
            }

            var datePeriodTimex = $"P{unitCount}{DatePeriodTimexTypeToTimexSuffix[timexType]}";

            return($"({FormatUtil.LuisDate(begin, alternativeBegin)},{FormatUtil.LuisDate(end, alternativeEnd)},{datePeriodTimex})");
        }
Example #5
0
        public DateTimeParseResult Parse(ExtractResult er, DateObject referenceTime)
        {
            object value = null;

            if (er.Type.Equals(ParserName))
            {
                var innerResult = InternalParse(er.Text, referenceTime);
                if (innerResult.Success)
                {
                    innerResult.FutureResolution = new Dictionary <string, string>
                    {
                        { TimeTypeConstants.TIME, FormatUtil.FormatTime((DateObject)innerResult.FutureValue) }
                    };

                    innerResult.PastResolution = new Dictionary <string, string>
                    {
                        { TimeTypeConstants.TIME, FormatUtil.FormatTime((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);
        }
Example #6
0
        // Parse specific TimeOfDay like "this night", "early morning", "late evening"
        protected virtual DateTimeResolutionResult ParseSpecificTimeOfDay(string text, DateObject referenceTime)
        {
            var ret        = new DateTimeResolutionResult();
            var trimedText = text.Trim().ToLowerInvariant();
            var timeText   = trimedText;

            var match = this.Config.PeriodTimeOfDayWithDateRegex.Match(trimedText);

            // Extract early/late prefix from text if any
            bool hasEarly = false, hasLate = false;

            if (match.Success)
            {
                timeText = match.Groups["timeOfDay"].Value;
                if (!string.IsNullOrEmpty(match.Groups["early"].Value))
                {
                    hasEarly    = true;
                    ret.Comment = Constants.Comment_Early;
                }

                if (!hasEarly && !string.IsNullOrEmpty(match.Groups["late"].Value))
                {
                    hasLate     = true;
                    ret.Comment = Constants.Comment_Late;
                }
            }
            else
            {
                match = this.Config.AmDescRegex.Match(trimedText);
                if (!match.Success)
                {
                    match = this.Config.PmDescRegex.Match(trimedText);
                }

                if (match.Success)
                {
                    timeText = match.Value;
                }
            }

            // Handle time of day

            // Late/early only works with time of day
            // Only standard time of day (morinng, afternoon, evening and night) will not directly return
            if (!this.Config.GetMatchedTimeRange(timeText, out string timeStr, out int beginHour, out int endHour, out int endMin))
            {
                return(ret);
            }

            // Modify time period if "early" or "late" exists
            // Since 'time of day' is defined as four hour periods,
            // the first 2 hours represent early, the later 2 hours represent late
            if (hasEarly)
            {
                endHour = beginHour + 2;
                // Handling speical case: night ends with 23:59
                if (endMin == 59)
                {
                    endMin = 0;
                }
            }
            else if (hasLate)
            {
                beginHour = beginHour + 2;
            }

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

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

                ret.Timex = FormatUtil.FormatDate(date) + timeStr;

                ret.FutureValue   =
                    ret.PastValue =
                        new Tuple <DateObject, DateObject>(DateObject.MinValue.SafeCreateFromValue(year, month, day, beginHour, 0, 0),
                                                           DateObject.MinValue.SafeCreateFromValue(year, month, day, endHour, endMin, endMin));

                ret.Success = true;
                return(ret);
            }

            // Handle Date followed by morning, afternoon and morning, afternoon followed by Date
            match = this.Config.PeriodTimeOfDayWithDateRegex.Match(trimedText);

            if (!match.Success)
            {
                match = this.Config.AmDescRegex.Match(trimedText);
                if (!match.Success)
                {
                    match = this.Config.PmDescRegex.Match(trimedText);
                }
            }

            if (match.Success)
            {
                var beforeStr = trimedText.Substring(0, match.Index).Trim();
                var afterStr  = trimedText.Substring(match.Index + match.Length).Trim();

                // Eliminate time period, if any
                var timePeriodErs = this.Config.TimePeriodExtractor.Extract(beforeStr);
                if (timePeriodErs.Count > 0)
                {
                    beforeStr = beforeStr.Remove(timePeriodErs[0].Start ?? 0, timePeriodErs[0].Length ?? 0).Trim();
                }
                else
                {
                    timePeriodErs = this.Config.TimePeriodExtractor.Extract(afterStr);
                    if (timePeriodErs.Count > 0)
                    {
                        afterStr = afterStr.Remove(timePeriodErs[0].Start ?? 0, timePeriodErs[0].Length ?? 0).Trim();
                    }
                }

                var ers = this.Config.DateExtractor.Extract(beforeStr, referenceTime);

                if (ers.Count == 0 || ers[0].Length != beforeStr.Length)
                {
                    var valid = false;

                    if (ers.Count > 0 && ers[0].Start == 0)
                    {
                        var midStr = beforeStr.Substring(ers[0].Start + ers[0].Length ?? 0);
                        if (string.IsNullOrWhiteSpace(midStr.Replace(',', ' ')))
                        {
                            valid = true;
                        }
                    }

                    if (!valid)
                    {
                        ers = this.Config.DateExtractor.Extract(afterStr, referenceTime);

                        if (ers.Count == 0 || ers[0].Length != afterStr.Length)
                        {
                            if (ers.Count > 0 && ers[0].Start + ers[0].Length == afterStr.Length)
                            {
                                var midStr = afterStr.Substring(0, ers[0].Start ?? 0);
                                if (string.IsNullOrWhiteSpace(midStr.Replace(',', ' ')))
                                {
                                    valid = true;
                                }
                            }
                        }
                        else
                        {
                            valid = true;
                        }
                    }

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

                var hasSpecificTimePeriod = false;
                if (timePeriodErs.Count > 0)
                {
                    var timePr = this.Config.TimePeriodParser.Parse(timePeriodErs[0], referenceTime);
                    if (timePr != null)
                    {
                        var periodFuture = (Tuple <DateObject, DateObject>)(((DateTimeResolutionResult)timePr.Value).FutureValue);
                        var periodPast   = (Tuple <DateObject, DateObject>)((DateTimeResolutionResult)timePr.Value).PastValue;

                        if (periodFuture == periodPast)
                        {
                            beginHour = periodFuture.Item1.Hour;
                            endHour   = periodFuture.Item2.Hour;
                        }
                        else
                        {
                            if (periodFuture.Item1.Hour >= beginHour || periodFuture.Item2.Hour <= endHour)
                            {
                                beginHour = periodFuture.Item1.Hour;
                                endHour   = periodFuture.Item2.Hour;
                            }
                            else
                            {
                                beginHour = periodPast.Item1.Hour;
                                endHour   = periodPast.Item2.Hour;
                            }
                        }

                        hasSpecificTimePeriod = true;
                    }
                }

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

                if (!hasSpecificTimePeriod)
                {
                    ret.Timex = pr.TimexStr + timeStr;
                }
                else
                {
                    ret.Timex = string.Format("({0}T{1},{0}T{2},PT{3}H)", pr.TimexStr, beginHour, endHour, endHour - beginHour);
                }

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

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

                ret.Success = true;

                return(ret);
            }

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

            object value = null;

            if (er.Type.Equals(ParserName))
            {
                var innerResult = MergeDateAndTimePeriods(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,
                                FormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)innerResult.FutureValue).Item1)
                            },
                            {
                                TimeTypeConstants.END_DATETIME,
                                FormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)innerResult.FutureValue).Item2)
                            }
                        };

                        innerResult.PastResolution = new Dictionary <string, string>
                        {
                            {
                                TimeTypeConstants.START_DATETIME,
                                FormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)innerResult.PastValue).Item1)
                            },
                            {
                                TimeTypeConstants.END_DATETIME,
                                FormatUtil.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,
                                    FormatUtil.FormatDateTime((DateObject)(innerResult.FutureValue))
                                }
                            };

                            innerResult.PastResolution = new Dictionary <string, string>
                            {
                                {
                                    TimeTypeConstants.START_DATETIME,
                                    FormatUtil.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,
                                    FormatUtil.FormatDateTime((DateObject)(innerResult.FutureValue))
                                }
                            };

                            innerResult.PastResolution = new Dictionary <string, string>
                            {
                                {
                                    TimeTypeConstants.END_DATETIME,
                                    FormatUtil.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);
        }
Example #8
0
        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    isPeriod                   = false;
            var    isSinglePoint              = false;
            string singlePointResolution      = "";
            string pastStartPointResolution   = "";
            string pastEndPointResolution     = "";
            string futureStartPointResolution = "";
            string futureEndPointResolution   = "";
            string singlePointType            = "";
            string startPointType             = "";
            string endPointType               = "";

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

                case Constants.SYS_DATETIME_DATETIMEPERIOD:
                    startPointType             = TimeTypeConstants.START_DATETIME;
                    endPointType               = TimeTypeConstants.END_DATETIME;
                    pastStartPointResolution   = FormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)ret.PastValue).Item1);
                    pastEndPointResolution     = FormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)ret.PastValue).Item2);
                    futureStartPointResolution = FormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)ret.FutureValue).Item1);
                    futureEndPointResolution   = FormatUtil.FormatDateTime(((Tuple <DateObject, DateObject>)ret.FutureValue).Item2);
                    break;

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

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

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

            if (isPeriod)
            {
                ret.FutureResolution = new Dictionary <string, string>
                {
                    { startPointType, futureStartPointResolution },
                    { endPointType, futureEndPointResolution },
                    { ExtendedModelResult.ParentTextKey, parentText }
                };

                ret.PastResolution = new Dictionary <string, string>
                {
                    { startPointType, pastStartPointResolution },
                    { endPointType, pastEndPointResolution },
                    { ExtendedModelResult.ParentTextKey, parentText }
                };
            }
            else if (isSinglePoint)
            {
                ret.FutureResolution = new Dictionary <string, string>
                {
                    { singlePointType, singlePointResolution },
                    { ExtendedModelResult.ParentTextKey, parentText }
                };

                ret.PastResolution = new Dictionary <string, string>
                {
                    { singlePointType, singlePointResolution },
                    { ExtendedModelResult.ParentTextKey, parentText }
                };
            }

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

            return(ret);
        }
Example #9
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 = 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)
                {
                    innerResult = ParseDecade(er.Text, referenceDate);
                }

                // Parse duration should be at the end since it will extract "the last week" from "the last week of July"
                if (!innerResult.Success)
                {
                    innerResult = ParseDuration(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);
        }
Example #10
0
        private DateTimeResolutionResult ParseDecade(string text, DateObject referenceDate)
        {
            var ret = new DateTimeResolutionResult();
            int firstTwoNumOfYear = referenceDate.Year / 100;
            int decade;
            int beginYear;
            int beginMonth = 1, endMonth = 12;
            int beginDay = 1, endDay = 31;
            int decadeLastYear = 9;
            var inputCentury   = false;

            var    trimedText = text.Trim();
            var    match = this.config.DecadeWithCenturyRegex.Match(trimedText);
            string beginLuisStr, endLuisStr;

            if (match.Success && match.Index == 0 && match.Length == trimedText.Length)
            {
                var decadeStr = match.Groups["decade"].Value.ToLower();
                if (!int.TryParse(decadeStr, out decade))
                {
                    if (this.config.WrittenDecades.ContainsKey(decadeStr))
                    {
                        decade = this.config.WrittenDecades[decadeStr];
                    }
                    else if (this.config.SpecialDecadeCases.ContainsKey(decadeStr))
                    {
                        firstTwoNumOfYear = this.config.SpecialDecadeCases[decadeStr] / 100;
                        decade            = this.config.SpecialDecadeCases[decadeStr] % 100;
                        inputCentury      = true;
                    }
                }

                var centuryStr = match.Groups["century"].Value.ToLower();
                if (!string.IsNullOrEmpty(centuryStr))
                {
                    if (!int.TryParse(centuryStr, out firstTwoNumOfYear))
                    {
                        if (this.config.Numbers.ContainsKey(centuryStr))
                        {
                            firstTwoNumOfYear = this.config.Numbers[centuryStr];
                        }
                        else
                        {
                            // handle the case "two thousand"
                            firstTwoNumOfYear = 20;
                        }
                    }

                    inputCentury = true;
                }
            }
            else
            {
                return(ret);
            }


            beginYear = firstTwoNumOfYear * 100 + decade;

            if (inputCentury)
            {
                beginLuisStr = FormatUtil.LuisDate(beginYear, beginMonth, beginDay);
                endLuisStr   = FormatUtil.LuisDate(beginYear + decadeLastYear, endMonth, endDay);
            }
            else
            {
                var beginYearStr = "XX" + decade.ToString();
                beginLuisStr = FormatUtil.LuisDate(-1, beginMonth, beginDay);
                beginLuisStr = beginLuisStr.Replace("XXXX", beginYearStr);

                var endYearStr = "XX" + (decade + decadeLastYear).ToString();
                endLuisStr = FormatUtil.LuisDate(-1, endMonth, endDay);
                endLuisStr = endLuisStr.Replace("XXXX", endYearStr);
            }
            ret.Timex = $"({beginLuisStr},{endLuisStr},P10Y)";

            int futureYear = beginYear, pastYear = beginYear;
            var startDate = DateObject.MinValue.SafeCreateFromValue(beginYear, beginMonth, beginDay);

            if (!inputCentury && startDate < referenceDate)
            {
                futureYear += 100;
            }

            if (!inputCentury && startDate >= referenceDate)
            {
                pastYear -= 100;
            }

            ret.FutureValue = new Tuple <DateObject, DateObject>(
                DateObject.MinValue.SafeCreateFromValue(futureYear, beginMonth, beginDay),
                DateObject.MinValue.SafeCreateFromValue(futureYear + decadeLastYear, endMonth, endDay));

            ret.PastValue = new Tuple <DateObject, DateObject>(
                DateObject.MinValue.SafeCreateFromValue(pastYear, beginMonth, beginDay),
                DateObject.MinValue.SafeCreateFromValue(pastYear + decadeLastYear, endMonth, endDay));

            ret.Success = true;

            return(ret);
        }
Example #11
0
        // handle cases like "January first", "twenty-two of August"
        // handle cases like "20th of next month"
        private DateTimeResolutionResult ParseNumberWithMonth(string text, DateObject referenceDate)
        {
            var ret = new DateTimeResolutionResult();

            var  trimedText = text.Trim().ToLower();
            int  month = 0, day = 0, year = referenceDate.Year;
            bool ambiguous = true;

            var er = this.config.OrdinalExtractor.Extract(trimedText);

            if (er.Count == 0)
            {
                er = this.config.IntegerExtractor.Extract(trimedText);
            }

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

            var num = Convert.ToInt32((double)(this.config.NumberParser.Parse(er[0]).Value ?? 0));

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

            if (match.Success)
            {
                month = this.config.MonthOfYear[match.Value.Trim()];
                day   = num;
            }

            // handling relatived month
            if (!match.Success)
            {
                match = this.config.RelativeMonthRegex.Match(trimedText);
                if (match.Success)
                {
                    var monthStr = match.Groups["order"].Value;
                    var swift    = this.config.GetSwiftMonth(monthStr);
                    month     = referenceDate.AddMonths(swift).Month;
                    day       = num;
                    ambiguous = false;
                }
            }

            // handling casesd like 'second Sunday'
            if (!match.Success)
            {
                match = this.config.WeekDayRegex.Match(trimedText);
                if (match.Success)
                {
                    month = referenceDate.Month;
                    // resolve the date of wanted week day
                    var wantedWeekDay      = this.config.DayOfWeek[match.Groups["weekday"].Value];
                    var firstDate          = DateObject.MinValue.SafeCreateFromValue(referenceDate.Year, referenceDate.Month, 1);
                    var firstWeekDay       = (int)firstDate.DayOfWeek;
                    var firstWantedWeekDay = firstDate.AddDays(wantedWeekDay > firstWeekDay ? wantedWeekDay - firstWeekDay : wantedWeekDay - firstWeekDay + 7);
                    var AnswerDay          = firstWantedWeekDay.Day + ((num - 1) * 7);
                    day       = AnswerDay;
                    ambiguous = false;
                }
            }

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

            // for LUIS format value string
            var futureDate = DateObject.MinValue.SafeCreateFromValue(year, month, day);
            var pastDate   = DateObject.MinValue.SafeCreateFromValue(year, month, day);

            if (ambiguous)
            {
                ret.Timex = FormatUtil.LuisDate(-1, month, day);
                if (futureDate < referenceDate)
                {
                    futureDate = futureDate.AddYears(+1);
                }

                if (pastDate >= referenceDate)
                {
                    pastDate = pastDate.AddYears(-1);
                }
            }
            else
            {
                ret.Timex = FormatUtil.LuisDate(year, month, day);
            }

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

            return(ret);
        }
Example #12
0
        // match several other cases
        // including 'today', 'the day after tomorrow', 'on 13'
        private DateTimeResolutionResult ParseImplicitDate(string text, DateObject referenceDate)
        {
            var trimedText = text.Trim();

            var ret = new DateTimeResolutionResult();

            // handle "on 12"
            var match = this.config.OnRegex.Match(this.config.DateTokenPrefix + trimedText);

            if (match.Success && match.Index == 3 && match.Length == trimedText.Length)
            {
                int day = 0, month = referenceDate.Month, year = referenceDate.Year;
                var dayStr = match.Groups["day"].Value.ToLower();
                day = this.config.DayOfMonth[dayStr];

                ret.Timex = FormatUtil.LuisDate(-1, -1, day);

                DateObject futureDate, pastDate;
                var        tryStr = FormatUtil.LuisDate(year, month, day);
                if (DateObject.TryParse(tryStr, out DateObject temp))
                {
                    futureDate = DateObject.MinValue.SafeCreateFromValue(year, month, day);
                    pastDate   = DateObject.MinValue.SafeCreateFromValue(year, month, day);

                    if (futureDate < referenceDate)
                    {
                        futureDate = futureDate.AddMonths(+1);
                    }

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


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


                return(ret);
            }

            // handle "today", "the day before yesterday"
            match = this.config.SpecialDayRegex.Match(trimedText);
            if (match.Success && match.Index == 0 && match.Length == trimedText.Length)
            {
                var swift = this.config.GetSwiftDay(match.Value);

                var value = referenceDate.AddDays(swift);

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

                return(ret);
            }

            // handle "next Sunday"
            match = this.config.NextRegex.Match(trimedText);
            if (match.Success && match.Index == 0 && match.Length == trimedText.Length)
            {
                var weekdayStr = match.Groups["weekday"].Value.ToLower();
                var value      = referenceDate.Next((DayOfWeek)this.config.DayOfWeek[weekdayStr]);

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

                return(ret);
            }

            // handle "this Friday"
            match = this.config.ThisRegex.Match(trimedText);
            if (match.Success && match.Index == 0 && match.Length == trimedText.Length)
            {
                var weekdayStr = match.Groups["weekday"].Value.ToLower();
                var value      = referenceDate.This((DayOfWeek)this.config.DayOfWeek[weekdayStr]);

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

                return(ret);
            }

            // handle "last Friday", "last mon"
            match = this.config.LastRegex.Match(trimedText);
            if (match.Success && match.Index == 0 && match.Length == trimedText.Length)
            {
                var weekdayStr = match.Groups["weekday"].Value.ToLower();
                var value      = referenceDate.Last((DayOfWeek)this.config.DayOfWeek[weekdayStr]);

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

                return(ret);
            }

            // handle "Friday"
            match = this.config.WeekDayRegex.Match(trimedText);
            if (match.Success && match.Index == 0 && match.Length == trimedText.Length)
            {
                var weekdayStr = match.Groups["weekday"].Value.ToLower();
                var weekDay    = this.config.DayOfWeek[weekdayStr];
                var value      = referenceDate.This((DayOfWeek)this.config.DayOfWeek[weekdayStr]);

                if (weekDay == 0)
                {
                    weekDay = 7;
                }

                if (weekDay < (int)referenceDate.DayOfWeek)
                {
                    value = referenceDate.Next((DayOfWeek)weekDay);
                }

                ret.Timex = "XXXX-WXX-" + weekDay;
                var futureDate = value;
                var pastDate   = value;
                if (futureDate < referenceDate)
                {
                    futureDate = futureDate.AddDays(7);
                }

                if (pastDate >= referenceDate)
                {
                    pastDate = pastDate.AddDays(-7);
                }

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

                return(ret);
            }

            // handle "for the 27th."
            match = this.config.ForTheRegex.Match(text);
            if (match.Success)
            {
                int day = 0, month = referenceDate.Month, year = referenceDate.Year;
                var dayStr = match.Groups["DayOfMonth"].Value.ToLower();

                // create a extract result which content ordinal string of text
                ExtractResult er = new ExtractResult();
                er.Text   = dayStr;
                er.Start  = match.Groups["DayOfMonth"].Index;
                er.Length = match.Groups["DayOfMonth"].Length;

                day = Convert.ToInt32((double)(this.config.NumberParser.Parse(er).Value ?? 0));

                ret.Timex = FormatUtil.LuisDate(-1, -1, day);

                DateObject futureDate;
                var        tryStr = FormatUtil.LuisDate(year, month, day);
                if (DateObject.TryParse(tryStr, out DateObject temp))
                {
                    futureDate = DateObject.MinValue.SafeCreateFromValue(year, month, day);
                }
                else
                {
                    futureDate = DateObject.MinValue.SafeCreateFromValue(year, month + 1, day);
                }

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

                return(ret);
            }

            // handling cases like 'Thursday the 21st', which both 'Thursday' and '21st' refer to a same date
            match = this.config.WeekDayAndDayOfMothRegex.Match(text);
            if (match.Success)
            {
                int month = referenceDate.Month, year = referenceDate.Year;
                // create a extract result which content ordinal string of text
                ExtractResult erTmp = new ExtractResult();
                erTmp.Text   = match.Groups["DayOfMonth"].Value.ToString();
                erTmp.Start  = match.Groups["DayOfMonth"].Index;
                erTmp.Length = match.Groups["DayOfMonth"].Length;

                // parse the day in text into number
                var day = Convert.ToInt32((double)(this.config.NumberParser.Parse(erTmp).Value ?? 0));

                // the validity of the phrase is guaranteed in the Date Extractor
                ret.Timex       = FormatUtil.LuisDate(year, month, day);
                ret.FutureValue = new DateObject(year, month, day);;
                ret.PastValue   = new DateObject(year, month, day);;
                ret.Success     = true;

                return(ret);
            }

            return(ret);
        }
Example #13
0
        // parse "last minute", "next hour"
        private DateTimeResolutionResult ParseRelativeUnit(string text, DateObject referenceTime)
        {
            var ret = new DateTimeResolutionResult();

            var match = Config.RelativeTimeUnitRegex.Match(text);

            if (match.Success)
            {
                var srcUnit = match.Groups["unit"].Value.ToLower();

                var unitStr = Config.UnitMap[srcUnit];

                int swiftValue  = 1;
                var prefixMatch = Config.PastRegex.Match(text);
                if (prefixMatch.Success)
                {
                    swiftValue = -1;
                }

                DateObject beginTime;
                var        endTime = beginTime = referenceTime;

                if (Config.UnitMap.ContainsKey(srcUnit))
                {
                    switch (unitStr)
                    {
                    case "H":
                        beginTime = swiftValue > 0 ? beginTime : referenceTime.AddHours(swiftValue);
                        endTime   = swiftValue > 0 ? referenceTime.AddHours(swiftValue) : endTime;
                        break;

                    case "M":
                        beginTime = swiftValue > 0 ? beginTime : referenceTime.AddMinutes(swiftValue);
                        endTime   = swiftValue > 0 ? referenceTime.AddMinutes(swiftValue) : endTime;
                        break;

                    case "S":
                        beginTime = swiftValue > 0 ? beginTime : referenceTime.AddSeconds(swiftValue);
                        endTime   = swiftValue > 0 ? referenceTime.AddSeconds(swiftValue) : endTime;
                        break;

                    default:
                        return(ret);
                    }

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

                    return(ret);
                }
            }

            return(ret);
        }
Example #14
0
        // parse specific TimeOfDay like "this night", "early morning", "late evening"
        protected virtual DateTimeResolutionResult ParseSpecificTimeOfDay(string text, DateObject referenceTime)
        {
            var ret        = new DateTimeResolutionResult();
            var trimedText = text.Trim().ToLowerInvariant();
            var timeText   = trimedText;

            var match = this.Config.PeriodTimeOfDayWithDateRegex.Match(trimedText);

            // extract early/late prefix from text if any
            bool hasEarly = false, hasLate = false;

            if (match.Success)
            {
                timeText = match.Groups["timeOfDay"].Value;
                if (!string.IsNullOrEmpty(match.Groups["early"].Value))
                {
                    hasEarly    = true;
                    ret.Comment = "early";
                }
                if (!hasEarly && !string.IsNullOrEmpty(match.Groups["late"].Value))
                {
                    hasLate     = true;
                    ret.Comment = "late";
                }
            }

            // handle time of day
            int    beginHour, endHour, endMin = 0;
            string timeStr;

            // late/early is only working iwth time of day
            // only standard time of day (morinng, afternoon, evening and night) will not directly return
            if (!this.Config.GetMatchedTimeRange(timeText, out timeStr, out beginHour, out endHour, out endMin))
            {
                return(ret);
            }

            // modify time period if "early" or "late" is existed
            // since time of day is all defined as four hours,
            // using previous 2 hours represents early
            // late 2 hours represents late
            if (hasEarly)
            {
                endHour = beginHour + 2;
                // handling speical case: night end with 23:59
                if (endMin == 59)
                {
                    endMin = 0;
                }
            }
            else if (hasLate)
            {
                beginHour = beginHour + 2;
            }

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

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

                ret.Timex = FormatUtil.FormatDate(date) + timeStr;

                ret.FutureValue   =
                    ret.PastValue =
                        new Tuple <DateObject, DateObject>(DateObject.MinValue.SafeCreateFromValue(year, month, day, beginHour, 0, 0),
                                                           DateObject.MinValue.SafeCreateFromValue(year, month, day, endHour, endMin, endMin));

                ret.Success = true;
                return(ret);
            }

            // handle Date followed by morning, afternoon
            // handle morning, afternoon followed by Date
            match = this.Config.PeriodTimeOfDayWithDateRegex.Match(trimedText);
            if (match.Success)
            {
                var beforeStr = trimedText.Substring(0, match.Index).Trim();
                var ers       = this.Config.DateExtractor.Extract(beforeStr);
                if (ers.Count == 0 || ers[0].Length != beforeStr.Length)
                {
                    var afterStr = trimedText.Substring(match.Index + match.Length).Trim();
                    ers = this.Config.DateExtractor.Extract(afterStr);
                    if (ers.Count == 0 || ers[0].Length != afterStr.Length)
                    {
                        return(ret);
                    }
                }
                var pr         = this.Config.DateParser.Parse(ers[0], referenceTime);
                var futureDate = (DateObject)((DateTimeResolutionResult)pr.Value).FutureValue;
                var pastDate   = (DateObject)((DateTimeResolutionResult)pr.Value).PastValue;

                ret.Timex = pr.TimexStr + timeStr;

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

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

                ret.Success = true;

                return(ret);
            }

            return(ret);
        }
Example #15
0
        // match several other cases
        // including 'today', 'the day after tomorrow', 'on 13'
        private DateTimeResolutionResult ParseImplicitDate(string text, DateObject referenceDate)
        {
            var trimedText = text.Trim();

            var ret = new DateTimeResolutionResult();

            // handle "on 12"
            var match = this.config.OnRegex.Match(this.config.DateTokenPrefix + trimedText);

            if (match.Success && match.Index == 3 && match.Length == trimedText.Length)
            {
                int day = 0, month = referenceDate.Month, year = referenceDate.Year;
                var dayStr = match.Groups["day"].Value.ToLower();
                day = this.config.DayOfMonth[dayStr];

                ret.Timex = FormatUtil.LuisDate(-1, -1, day);

                DateObject futureDate, pastDate, temp;
                var        tryStr = FormatUtil.LuisDate(year, month, day);
                if (DateObject.TryParse(tryStr, out temp))
                {
                    futureDate = new DateObject(year, month, day);
                    pastDate   = new DateObject(year, month, day);
                    if (futureDate < referenceDate)
                    {
                        futureDate = futureDate.AddMonths(+1);
                    }
                    if (pastDate >= referenceDate)
                    {
                        pastDate = pastDate.AddMonths(-1);
                    }
                }
                else
                {
                    futureDate = new DateObject(year, month + 1, day);
                    pastDate   = new DateObject(year, month - 1, day);
                }


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


                return(ret);
            }

            // handle "today", "the day before yesterday"
            match = this.config.SpecialDayRegex.Match(trimedText);
            if (match.Success && match.Index == 0 && match.Length == trimedText.Length)
            {
                var swift = this.config.GetSwiftDay(match.Value);

                var value = referenceDate.AddDays(swift);

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

                return(ret);
            }

            // handle "next Sunday"
            match = this.config.NextRegex.Match(trimedText);
            if (match.Success && match.Index == 0 && match.Length == trimedText.Length)
            {
                var weekdayStr = match.Groups["weekday"].Value.ToLower();
                var value      = referenceDate.Next((DayOfWeek)this.config.DayOfWeek[weekdayStr]);

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

                return(ret);
            }

            // handle "this Friday"
            match = this.config.ThisRegex.Match(trimedText);
            if (match.Success && match.Index == 0 && match.Length == trimedText.Length)
            {
                var weekdayStr = match.Groups["weekday"].Value.ToLower();
                var value      = referenceDate.This((DayOfWeek)this.config.DayOfWeek[weekdayStr]);

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

                return(ret);
            }

            // handle "last Friday", "last mon"
            match = this.config.LastRegex.Match(trimedText);
            if (match.Success && match.Index == 0 && match.Length == trimedText.Length)
            {
                var weekdayStr = match.Groups["weekday"].Value.ToLower();
                var value      = referenceDate.Last((DayOfWeek)this.config.DayOfWeek[weekdayStr]);

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

                return(ret);
            }

            // handle "Friday"
            match = this.config.StrictWeekDay.Match(trimedText);
            if (match.Success && match.Index == 0 && match.Length == trimedText.Length)
            {
                var weekdayStr = match.Groups["weekday"].Value.ToLower();
                var weekDay    = this.config.DayOfWeek[weekdayStr];
                var value      = referenceDate.This((DayOfWeek)this.config.DayOfWeek[weekdayStr]);

                if (weekDay == 0)
                {
                    weekDay = 7;
                }
                if (weekDay < (int)referenceDate.DayOfWeek)
                {
                    value = referenceDate.Next((DayOfWeek)weekDay);
                }

                ret.Timex = "XXXX-WXX-" + weekDay;
                var futureDate = value;
                var pastDate   = value;
                if (futureDate < referenceDate)
                {
                    futureDate = futureDate.AddDays(7);
                }
                if (pastDate >= referenceDate)
                {
                    pastDate = pastDate.AddDays(-7);
                }

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

                return(ret);
            }

            return(ret);
        }
        // parse "in 20 minutes"
        private DateTimeResolutionResult ParseNumberWithUnit(string text, DateObject referenceTime)
        {
            var    ret = new DateTimeResolutionResult();
            string numStr, unitStr;

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

            if (ers.Count == 1)
            {
                var pr        = this.Config.NumberParser.Parse(ers[0]);
                var srcUnit   = text.Substring(ers[0].Start + ers[0].Length ?? 0).Trim().ToLower();
                var beforeStr = text.Substring(0, ers[0].Start ?? 0).Trim().ToLowerInvariant();

                if (this.Config.UnitMap.ContainsKey(srcUnit))
                {
                    numStr  = pr.ResolutionStr;
                    unitStr = this.Config.UnitMap[srcUnit];
                    var prefixMatch = this.Config.PastRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "H":
                            beginDate = referenceTime.AddHours(-(double)pr.Value);
                            endDate   = referenceTime;
                            break;

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

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

                        default:
                            return(ret);
                        }

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

                    prefixMatch = this.Config.FutureRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "H":
                            beginDate = referenceTime;
                            endDate   = referenceTime.AddHours((double)pr.Value);
                            break;

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

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

                        default:
                            return(ret);
                        }

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

                        return(ret);
                    }
                }
            }

            // if there are NO spaces between number and unit
            var match = this.Config.NumberCombinedWithUnitRegex.Match(text);

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

                    var prefixMatch = this.Config.PastRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "H":
                            beginDate = referenceTime.AddHours(-double.Parse(numStr));
                            endDate   = referenceTime;
                            break;

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

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

                        default:
                            return(ret);
                        }

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

                        return(ret);
                    }

                    prefixMatch = this.Config.FutureRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "H":
                            beginDate = referenceTime;
                            endDate   = referenceTime.AddHours(double.Parse(numStr));
                            break;

                        case "M":
                            beginDate = referenceTime;
                            endDate   = referenceTime.AddMinutes(double.Parse(numStr));
                            break;

                        case "S":
                            beginDate = referenceTime;
                            endDate   = referenceTime.AddSeconds(double.Parse(numStr));
                            break;

                        default:
                            return(ret);
                        }

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

                        return(ret);
                    }
                }
            }

            // handle "last hour"
            match = this.Config.UnitRegex.Match(text);
            if (match.Success)
            {
                var srcUnit   = match.Groups["unit"].Value.ToLower();
                var beforeStr = text.Substring(0, match.Index).Trim().ToLowerInvariant();
                if (this.Config.UnitMap.ContainsKey(srcUnit))
                {
                    unitStr = this.Config.UnitMap[srcUnit];
                    var prefixMatch = this.Config.PastRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "H":
                            beginDate = referenceTime.AddHours(-1);
                            endDate   = referenceTime;
                            break;

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

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

                        default:
                            return(ret);
                        }

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

                        return(ret);
                    }

                    prefixMatch = this.Config.FutureRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "H":
                            beginDate = referenceTime;
                            endDate   = referenceTime.AddHours(1);
                            break;

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

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

                        default:
                            return(ret);
                        }

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

                        return(ret);
                    }
                }
            }

            return(ret);
        }
        // parse "this night"
        protected virtual DateTimeResolutionResult ParseSpecificNight(string text, DateObject referenceTime)
        {
            var ret        = new DateTimeResolutionResult();
            var trimedText = text.Trim().ToLowerInvariant();

            // handle morning, afternoon..
            int    beginHour, endHour, endMin = 0;
            string timeStr;

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

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

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

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

                ret.Timex = FormatUtil.FormatDate(date) + timeStr;

                ret.FutureValue   =
                    ret.PastValue =
                        new Tuple <DateObject, DateObject>(new DateObject(year, month, day, beginHour, 0, 0),
                                                           new DateObject(year, month, day, endHour, endMin, endMin));

                ret.Success = true;
                return(ret);
            }


            // handle Date followed by morning, afternoon
            match = this.Config.NightRegex.Match(trimedText);
            if (match.Success)
            {
                var beforeStr = trimedText.Substring(0, match.Index).Trim();
                var ers       = this.Config.DateExtractor.Extract(beforeStr);
                if (ers.Count == 0 || ers[0].Length != beforeStr.Length)
                {
                    return(ret);
                }

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

                ret.Timex = pr.TimexStr + timeStr;

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

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

                ret.Success = true;

                return(ret);
            }

            return(ret);
        }
Example #18
0
        private static DateTimeResolutionResult GetAgoLaterResult(
            DateTimeParseResult durationParseResult,
            string afterStr,
            string beforeStr,
            System.DateTime referenceTime,
            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);
                }

                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))
            {
                var match = utilityConfiguration.LaterRegex.Match(afterStr);
                var swift = 0;

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

                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 = $"{FormatUtil.LuisDate(resultDateTime)}";
                }
                else if (mode.Equals(AgoLaterMode.DateTime))
                {
                    ret.Timex = $"{FormatUtil.LuisDateTime(resultDateTime)}";
                }

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

            return(ret);
        }
Example #19
0
        private DateTimeResolutionResult ParseTimeOfToday(string text, DateObject referenceTime)
        {
            var ret        = new DateTimeResolutionResult();
            var trimedText = text.ToLowerInvariant().Trim();

            int    hour = 0, min = 0, sec = 0;
            string timeStr = string.Empty;

            var wholeMatch = this.config.SimpleTimeOfTodayAfterRegex.Match(trimedText);

            if (!(wholeMatch.Success && wholeMatch.Length == trimedText.Length))
            {
                wholeMatch = this.config.SimpleTimeOfTodayBeforeRegex.Match(trimedText);
            }
            if (wholeMatch.Success && wholeMatch.Length == trimedText.Length)
            {
                var hourStr = wholeMatch.Groups["hour"].Value;
                if (string.IsNullOrEmpty(hourStr))
                {
                    hourStr = wholeMatch.Groups["hournum"].Value.ToLower();
                    hour    = this.config.Numbers[hourStr];
                }
                else
                {
                    hour = int.Parse(hourStr);
                }
                timeStr = "T" + hour.ToString("D2");
            }
            else
            {
                var ers = this.config.TimeExtractor.Extract(trimedText);
                if (ers.Count != 1)
                {
                    ers = this.config.TimeExtractor.Extract(this.config.TokenBeforeTime + trimedText);
                    if (ers.Count == 1)
                    {
                        ers[0].Start -= this.config.TokenBeforeTime.Length;
                    }
                    else
                    {
                        return(ret);
                    }
                }

                var pr = this.config.TimeParser.Parse(ers[0], referenceTime);
                if (pr.Value == null)
                {
                    return(ret);
                }

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

                hour    = time.Hour;
                min     = time.Minute;
                sec     = time.Second;
                timeStr = pr.TimexStr;
            }


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

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

                // handle "last", "next"
                var swift = this.config.GetSwiftDay(matchStr);

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

                // handle "morning", "afternoon"
                hour = this.config.GetHour(matchStr, hour);

                // in this situation, luisStr cannot end up with "ampm", because we always have a "morning" or "night"
                if (timeStr.EndsWith("ampm"))
                {
                    timeStr = timeStr.Substring(0, timeStr.Length - 4);
                }
                timeStr = "T" + hour.ToString("D2") + timeStr.Substring(3);

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

            return(ret);
        }
Example #20
0
        //TODO: this can be abstracted with the similar method in BaseDatePeriodParser
        // Parse "in 20 minutes"
        private DateTimeResolutionResult ParseDuration(string text, DateObject referenceTime)
        {
            var ret = new DateTimeResolutionResult();

            // For the rest of datetime, it will be handled in next function
            if (Config.RestOfDateTimeRegex.IsMatch(text))
            {
                return(ret);
            }

            var ers = Config.DurationExtractor.Extract(text, referenceTime);

            if (ers.Count == 1)
            {
                var pr = Config.DurationParser.Parse(ers[0]);

                var beforeStr = text.Substring(0, pr.Start ?? 0).Trim().ToLowerInvariant();
                var afterStr  = text.Substring((pr.Start ?? 0) + (pr.Length ?? 0)).Trim().ToLowerInvariant();

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

                    DateObject beginTime;
                    var        endTime = beginTime = referenceTime;

                    var prefixMatch = Config.PastRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        mod       = Constants.BEFORE_MOD;
                        beginTime = referenceTime.AddSeconds(-swiftSeconds);
                    }

                    // Handle the "within (the) (next) xx seconds/minutes/hours" case
                    // Should also handle the multiple duration case like P1DT8H
                    // Set the beginTime equal to reference time for now
                    prefixMatch = Config.WithinNextPrefixRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        endTime = beginTime.AddSeconds(swiftSeconds);
                    }

                    prefixMatch = Config.FutureRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        mod     = Constants.AFTER_MOD;
                        endTime = beginTime.AddSeconds(swiftSeconds);
                    }

                    var suffixMatch = Config.PastRegex.Match(afterStr);
                    if (suffixMatch.Success && suffixMatch.Length == afterStr.Length)
                    {
                        mod       = Constants.BEFORE_MOD;
                        beginTime = referenceTime.AddSeconds(-swiftSeconds);
                    }

                    suffixMatch = Config.FutureRegex.Match(afterStr);
                    if (suffixMatch.Success && suffixMatch.Length == afterStr.Length)
                    {
                        mod     = Constants.AFTER_MOD;
                        endTime = beginTime.AddSeconds(swiftSeconds);
                    }

                    suffixMatch = Config.FutureSuffixRegex.Match(afterStr);
                    if (suffixMatch.Success && suffixMatch.Length == afterStr.Length)
                    {
                        mod     = Constants.AFTER_MOD;
                        endTime = beginTime.AddSeconds(swiftSeconds);
                    }

                    ret.Timex =
                        $"({FormatUtil.LuisDate(beginTime)}T{FormatUtil.LuisTime(beginTime)}," +
                        $"{FormatUtil.LuisDate(endTime)}T{FormatUtil.LuisTime(endTime)}," +
                        $"{durationResult.Timex})";

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

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

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

                    return(ret);
                }
            }

            return(ret);
        }
        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 = ParseNight(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);
        }
        //TODO: this can be abstracted with the similar method in BaseDatePeriodParser
        // parse "in 20 minutes"
        private DateTimeResolutionResult ParseDuration(string text, DateObject referenceTime)
        {
            var ret = new DateTimeResolutionResult();

            //for rest of datetime, it will be handled in next function
            if (Config.RestOfDateTimeRegex.IsMatch(text))
            {
                return(ret);
            }

            var ers = Config.DurationExtractor.Extract(text, referenceTime);

            if (ers.Count == 1)
            {
                var pr        = Config.DurationParser.Parse(ers[0]);
                var beforeStr = text.Substring(0, pr.Start ?? 0).Trim().ToLowerInvariant();
                if (pr.Value != null)
                {
                    var swiftSeconds   = 0;
                    var mod            = "";
                    var durationResult = (DateTimeResolutionResult)pr.Value;
                    if (durationResult.PastValue is double && durationResult.FutureValue is double)
                    {
                        swiftSeconds = (int)((double)durationResult.FutureValue);
                    }

                    DateObject beginTime;
                    var        endTime = beginTime = referenceTime;

                    var prefixMatch = Config.PastRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        mod       = TimeTypeConstants.beforeMod;
                        beginTime = referenceTime.AddSeconds(-swiftSeconds);
                    }

                    prefixMatch = Config.FutureRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        mod     = TimeTypeConstants.afterMod;
                        endTime = beginTime.AddSeconds(swiftSeconds);
                    }

                    ret.Timex =
                        $"({FormatUtil.LuisDate(beginTime)}T{FormatUtil.LuisTime(beginTime)}," +
                        $"{FormatUtil.LuisDate(endTime)}T{FormatUtil.LuisTime(endTime)}," +
                        $"{durationResult.Timex})";
                    ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginTime, endTime);
                    ret.Success     = true;

                    if (!string.IsNullOrEmpty(mod))
                    {
                        ((DateTimeResolutionResult)pr.Value).Mod = mod;
                    }
                    ret.SubDateTimeEntities = new List <object> {
                        pr
                    };

                    return(ret);
                }
            }

            return(ret);
        }
Example #23
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, FormatUtil.FormatDate((DateObject)innerResult.FutureValue) }
                    };

                    innerResult.PastResolution = new Dictionary <string, string>
                    {
                        { TimeTypeConstants.DATE, FormatUtil.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);
        }
        private DateTimeResolutionResult ParseDuration(string text, DateObject referenceDate)
        {
            var ret = new DateTimeResolutionResult();

            var ers = config.DurationExtractor.Extract(text);

            if (ers.Count == 1)
            {
                var pr        = config.DurationParser.Parse(ers[0]);
                var beforeStr = text.Substring(0, pr.Start ?? 0).Trim().ToLowerInvariant();
                if (pr.Value != null)
                {
                    var durationResult = (DateTimeResolutionResult)pr.Value;

                    if (string.IsNullOrEmpty(durationResult.Timex))
                    {
                        return(ret);
                    }

                    DateObject beginDate;
                    var        endDate = beginDate = referenceDate;

                    var prefixMatch = config.PastRegex.Match(beforeStr);
                    if (prefixMatch.Success)
                    {
                        beginDate = GetSwiftDate(endDate, durationResult.Timex, false);
                    }

                    prefixMatch = config.FutureRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        //for future the beginDate should add 1 first
                        beginDate = referenceDate.AddDays(1);
                        endDate   = GetSwiftDate(beginDate, durationResult.Timex, true);
                    }

                    //handle the "in two weeks" case which means the second week
                    prefixMatch = config.InConnectorRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        beginDate = referenceDate.AddDays(1);
                        endDate   = GetSwiftDate(beginDate, durationResult.Timex, true);

                        //change the duration value and the beginDate
                        var unit = durationResult.Timex.Substring(durationResult.Timex.Length - 1);

                        durationResult.Timex = "P1" + unit;
                        beginDate            = GetSwiftDate(endDate, durationResult.Timex, false);
                    }

                    if (beginDate.Equals(endDate))
                    {
                        return(ret);
                    }

                    endDate = InclusiveEndPeriod ? endDate.AddDays(-1) : endDate;

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

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

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

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

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

                // Cases like "4" is different with "4:00" as the Timex is different "T04H" vs "T04H00M"
                // 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 time point has description like 'am' or 'pm'
                if (hasLeft && hasRight)
                {
                    if (hasLeftAm)
                    {
                        if (beginHour >= Constants.HalfDayHourCount)
                        {
                            beginDateTime = beginDateTime.AddHours(-Constants.HalfDayHourCount);
                        }
                    }
                    else
                    {
                        if (beginHour < Constants.HalfDayHourCount)
                        {
                            beginDateTime = beginDateTime.AddHours(Constants.HalfDayHourCount);
                        }
                    }

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

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

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

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

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

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

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

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

                var beginStr = 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}"
                    };

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

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

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

                ret.Success = true;
            }

            return(ret);
        }
Example #26
0
        internal void ResolveAmpm(Dictionary <string, object> resolutionDic, string keyName)
        {
            if (resolutionDic.ContainsKey(keyName))
            {
                var resolution = (Dictionary <string, string>)resolutionDic[keyName];
                if (!resolutionDic.ContainsKey("timex"))
                {
                    return;
                }

                var timex = (string)resolutionDic["timex"];
                resolutionDic.Remove(keyName);

                resolutionDic.Add(keyName + "Am", resolution);

                var resolutionPm = new Dictionary <string, string>();
                switch ((string)resolutionDic["type"])
                {
                case Constants.SYS_DATETIME_TIME:
                    resolutionPm[TimeTypeConstants.VALUE] = FormatUtil.ToPm(resolution[TimeTypeConstants.VALUE]);
                    resolutionPm["timex"] = FormatUtil.ToPm(timex);
                    break;

                case Constants.SYS_DATETIME_DATETIME:
                    var splited = resolution[TimeTypeConstants.VALUE].Split(' ');
                    resolutionPm[TimeTypeConstants.VALUE] = splited[0] + " " + FormatUtil.ToPm(splited[1]);
                    resolutionPm["timex"] = FormatUtil.AllStringToPm(timex);
                    break;

                case Constants.SYS_DATETIME_TIMEPERIOD:
                    if (resolution.ContainsKey(TimeTypeConstants.START))
                    {
                        resolutionPm[TimeTypeConstants.START] = FormatUtil.ToPm(resolution[TimeTypeConstants.START]);
                    }

                    if (resolution.ContainsKey(TimeTypeConstants.END))
                    {
                        resolutionPm[TimeTypeConstants.END] = FormatUtil.ToPm(resolution[TimeTypeConstants.END]);
                    }

                    resolutionPm["timex"] = FormatUtil.AllStringToPm(timex);
                    break;

                case Constants.SYS_DATETIME_DATETIMEPERIOD:
                    if (resolution.ContainsKey(TimeTypeConstants.START))
                    {
                        splited = resolution[TimeTypeConstants.START].Split(' ');
                        if (resolution.ContainsKey(TimeTypeConstants.START))
                        {
                            resolutionPm[TimeTypeConstants.START] = splited[0] + " " + FormatUtil.ToPm(splited[1]);
                        }
                    }

                    if (resolution.ContainsKey(TimeTypeConstants.END))
                    {
                        splited = resolution[TimeTypeConstants.END].Split(' ');

                        if (resolution.ContainsKey(TimeTypeConstants.END))
                        {
                            resolutionPm[TimeTypeConstants.END] = splited[0] + " " + FormatUtil.ToPm(splited[1]);
                        }
                    }

                    resolutionPm["timex"] = FormatUtil.AllStringToPm(timex);
                    break;
                }

                resolutionDic.Add(keyName + "Pm", resolutionPm);
            }
        }
Example #27
0
        private DateTimeResolutionResult ParseSimpleCases(string text, DateObject referenceDate)
        {
            var ret = new DateTimeResolutionResult();
            int year = referenceDate.Year, month = referenceDate.Month;
            int beginDay, endDay;
            var noYear = false;

            var    trimedText = text.Trim();
            var    match = this.config.MonthFrontBetweenRegex.Match(trimedText);
            string beginLuisStr, endLuisStr;

            if (!match.Success)
            {
                match = this.config.BetweenRegex.Match(trimedText);
            }

            if (!match.Success)
            {
                match = this.config.MonthFrontSimpleCasesRegex.Match(trimedText);
            }

            if (!match.Success)
            {
                match = this.config.SimpleCasesRegex.Match(trimedText);
            }

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

                var monthStr = match.Groups["month"].Value;
                if (!string.IsNullOrEmpty(monthStr))
                {
                    month  = this.config.MonthOfYear[monthStr.ToLower()];
                    noYear = true;
                }
                else
                {
                    monthStr = match.Groups["relmonth"].Value.Trim().ToLower();
                    var swiftMonth = this.config.GetSwiftDayOrMonth(monthStr);
                    switch (swiftMonth)
                    {
                    case 1:
                        if (month != 12)
                        {
                            month += 1;
                        }
                        else
                        {
                            month = 1;
                            year += 1;
                        }
                        break;

                    case -1:
                        if (month != 1)
                        {
                            month -= 1;
                        }
                        else
                        {
                            month = 12;
                            year -= 1;
                        }
                        break;

                    default:
                        break;
                    }
                }

                if (this.config.IsFuture(monthStr))
                {
                    beginLuisStr = FormatUtil.LuisDate(year, month, beginDay);
                    endLuisStr   = FormatUtil.LuisDate(year, month, endDay);
                }
                else
                {
                    beginLuisStr = FormatUtil.LuisDate(-1, month, beginDay);
                    endLuisStr   = FormatUtil.LuisDate(-1, month, endDay);
                }
            }
            else
            {
                return(ret);
            }

            // parse year
            var yearStr = match.Groups["year"].Value;

            if (!string.IsNullOrEmpty(yearStr))
            {
                year   = int.Parse(yearStr);
                noYear = false;
            }

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

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

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

            ret.Timex       = $"({beginLuisStr},{endLuisStr},P{endDay - beginDay}D)";
            ret.FutureValue = new Tuple <DateObject, DateObject>(
                DateObject.MinValue.SafeCreateFromValue(futureYear, month, beginDay),
                DateObject.MinValue.SafeCreateFromValue(futureYear, month, endDay));
            ret.PastValue = new Tuple <DateObject, DateObject>(
                DateObject.MinValue.SafeCreateFromValue(pastYear, month, beginDay),
                DateObject.MinValue.SafeCreateFromValue(pastYear, month, endDay));
            ret.Success = true;

            return(ret);
        }
Example #28
0
        // Parse "last minute", "next hour"
        private DateTimeResolutionResult ParseRelativeUnit(string text, DateObject referenceTime)
        {
            var ret = new DateTimeResolutionResult();

            var match = Config.RelativeTimeUnitRegex.Match(text);

            if (!match.Success)
            {
                match = this.Config.RestOfDateTimeRegex.Match(text);
            }

            if (match.Success)
            {
                var srcUnit = match.Groups["unit"].Value.ToLower();

                var unitStr = Config.UnitMap[srcUnit];

                int swiftValue  = 1;
                var prefixMatch = Config.PastRegex.Match(text);
                if (prefixMatch.Success)
                {
                    swiftValue = -1;
                }

                DateObject beginTime;
                var        endTime = beginTime = referenceTime;
                var        ptTimex = string.Empty;

                if (Config.UnitMap.ContainsKey(srcUnit))
                {
                    switch (unitStr)
                    {
                    case "D":
                        endTime = DateObject.MinValue.SafeCreateFromValue(beginTime.Year, beginTime.Month, beginTime.Day);
                        endTime = endTime.AddDays(1).AddSeconds(-1);
                        ptTimex = "PT" + (endTime - beginTime).TotalSeconds + "S";
                        break;

                    case "H":
                        beginTime = swiftValue > 0 ? beginTime : referenceTime.AddHours(swiftValue);
                        endTime   = swiftValue > 0 ? referenceTime.AddHours(swiftValue) : endTime;
                        ptTimex   = "PT1H";
                        break;

                    case "M":
                        beginTime = swiftValue > 0 ? beginTime : referenceTime.AddMinutes(swiftValue);
                        endTime   = swiftValue > 0 ? referenceTime.AddMinutes(swiftValue) : endTime;
                        ptTimex   = "PT1M";
                        break;

                    case "S":
                        beginTime = swiftValue > 0 ? beginTime : referenceTime.AddSeconds(swiftValue);
                        endTime   = swiftValue > 0 ? referenceTime.AddSeconds(swiftValue) : endTime;
                        ptTimex   = "PT1S";
                        break;

                    default:
                        return(ret);
                    }

                    ret.Timex =
                        $"({FormatUtil.LuisDate(beginTime)}T{FormatUtil.LuisTime(beginTime)}," +
                        $"{FormatUtil.LuisDate(endTime)}T{FormatUtil.LuisTime(endTime)},{ptTimex})";

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

                    return(ret);
                }
            }

            return(ret);
        }
Example #29
0
        private DateTimeResolutionResult ParseDuration(string text, DateObject referenceDate)
        {
            var        ret = new DateTimeResolutionResult();
            DateObject beginDate;
            var        endDate       = beginDate = referenceDate;
            string     timex         = string.Empty;
            bool       restNowSunday = false;

            var ers = config.DurationExtractor.Extract(text, referenceDate);

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

                if (pr.Value != null)
                {
                    var durationResult = (DateTimeResolutionResult)pr.Value;

                    if (string.IsNullOrEmpty(durationResult.Timex))
                    {
                        return(ret);
                    }

                    var prefixMatch = config.PastRegex.Match(beforeStr);
                    if (prefixMatch.Success)
                    {
                        mod       = TimeTypeConstants.beforeMod;
                        beginDate = DurationParsingUtil.ShiftDateTime(durationResult.Timex, endDate, false);
                    }
                    else
                    {
                        var suffixMatch = config.PastRegex.Match(afterStr);
                        if (suffixMatch.Success)
                        {
                            mod       = TimeTypeConstants.beforeMod;
                            beginDate = DurationParsingUtil.ShiftDateTime(durationResult.Timex, endDate, false);
                        }
                    }

                    prefixMatch = config.FutureRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        mod = TimeTypeConstants.afterMod;

                        // For future the beginDate should add 1 first
                        beginDate = referenceDate.AddDays(1);
                        endDate   = DurationParsingUtil.ShiftDateTime(durationResult.Timex, beginDate, true);
                    }

                    // Handle the "in two weeks" case which means the second week
                    prefixMatch = config.InConnectorRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length &&
                        !DurationParsingUtil.IsMultipleDuration(durationResult.Timex))
                    {
                        mod = TimeTypeConstants.afterMod;

                        beginDate = referenceDate.AddDays(1);
                        endDate   = DurationParsingUtil.ShiftDateTime(durationResult.Timex, beginDate, true);

                        // Change the duration value and the beginDate
                        var unit = durationResult.Timex.Substring(durationResult.Timex.Length - 1);

                        durationResult.Timex = "P1" + unit;
                        beginDate            = DurationParsingUtil.ShiftDateTime(durationResult.Timex, endDate, false);
                    }

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

                    timex = durationResult.Timex;

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

            // Parse "rest of"
            var match = this.config.RestOfDateRegex.Match(text);

            if (match.Success)
            {
                var durationStr  = match.Groups["duration"].Value;
                var durationUnit = this.config.UnitMap[durationStr];
                switch (durationUnit)
                {
                case "W":
                    var diff = 7 - (((int)beginDate.DayOfWeek) == 0? 7: (int)beginDate.DayOfWeek);
                    endDate = beginDate.AddDays(diff);
                    timex   = "P" + diff + "D";
                    if (diff == 0)
                    {
                        restNowSunday = true;
                    }
                    break;

                case "MON":
                    endDate = DateObject.MinValue.SafeCreateFromValue(beginDate.Year, beginDate.Month, 1);
                    endDate = endDate.AddMonths(1).AddDays(-1);
                    diff    = endDate.Day - beginDate.Day + 1;
                    timex   = "P" + diff + "D";
                    break;

                case "Y":
                    endDate = DateObject.MinValue.SafeCreateFromValue(beginDate.Year, 12, 1);
                    endDate = endDate.AddMonths(1).AddDays(-1);
                    diff    = endDate.DayOfYear - beginDate.DayOfYear + 1;
                    timex   = "P" + diff + "D";
                    break;
                }
            }

            if (!beginDate.Equals(endDate) || restNowSunday)
            {
                endDate = InclusiveEndPeriod ? endDate.AddDays(-1) : endDate;

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

                return(ret);
            }

            return(ret);
        }
        private DateTimeResolutionResult ParseNumberWithUnit(string text, DateObject referenceDate)
        {
            var ret = new DateTimeResolutionResult();

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

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

            if (ers.Count == 1)
            {
                var pr        = this.config.NumberParser.Parse(ers[0]);
                var srcUnit   = text.Substring(ers[0].Start + ers[0].Length ?? 0).Trim().ToLowerInvariant();
                var beforeStr = text.Substring(0, ers[0].Start ?? 0).Trim().ToLowerInvariant();
                if (this.config.UnitMap.ContainsKey(srcUnit))
                {
                    numStr  = pr.ResolutionStr;
                    unitStr = this.config.UnitMap[srcUnit];
                    var prefixMatch = this.config.PastRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "D":
                            beginDate = referenceDate.AddDays(-(double)pr.Value);
                            endDate   = referenceDate;
                            break;

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

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

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

                        default:
                            return(ret);
                        }

                        ret.Timex       = $"({FormatUtil.LuisDate(beginDate)},{FormatUtil.LuisDate(endDate)},P{numStr}{unitStr[0]})";
                        ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginDate, endDate);
                        ret.Success     = true;
                        return(ret);
                    }
                    prefixMatch = this.config.FutureRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "D":
                            beginDate = referenceDate;
                            endDate   = referenceDate.AddDays((double)pr.Value);
                            break;

                        case "W":
                            beginDate = config.InStringList.Contains(beforeStr.ToLower()) ? referenceDate.AddDays(7 * ((double)pr.Value - 1)) : referenceDate;
                            endDate   = referenceDate.AddDays(7 * (double)pr.Value);
                            break;

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

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

                        default:
                            return(ret);
                        }

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

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

            if (match.Success)
            {
                var srcUnit   = match.Groups["unit"].Value.ToLowerInvariant();
                var beforeStr = text.Substring(0, match.Index).Trim().ToLowerInvariant();
                if (this.config.UnitMap.ContainsKey(srcUnit))
                {
                    unitStr = this.config.UnitMap[srcUnit];
                    numStr  = match.Groups["num"].Value;
                    var prefixMatch = this.config.PastRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "D":
                            beginDate = referenceDate.AddDays(-double.Parse(numStr));
                            endDate   = referenceDate;
                            break;

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

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

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

                        default:
                            return(ret);
                        }
                        ret.Timex       = $"({FormatUtil.LuisDate(beginDate)},{FormatUtil.LuisDate(endDate)},P{numStr}{unitStr[0]})";
                        ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(beginDate, endDate);
                        ret.Success     = true;
                        return(ret);
                    }
                    prefixMatch = this.config.FutureRegex.Match(beforeStr);
                    if (prefixMatch.Success && prefixMatch.Length == beforeStr.Length)
                    {
                        DateObject beginDate, endDate;
                        switch (unitStr)
                        {
                        case "D":
                            beginDate = referenceDate;
                            endDate   = referenceDate.AddDays(double.Parse(numStr));
                            break;

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

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

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

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

            return(ret);
        }