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); }
// 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); }
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})"); }
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); }
// 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); }
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); }
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); }
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); }
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); }
// 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); }
// 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); }
// 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); }
// 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); }
// 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); }
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); }
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); }
//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); }
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); }
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); } }
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); }
// 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); }
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); }