private static DateTimeResolutionResult GetAgoLaterResult( DateTimeParseResult durationParseResult, string afterStr, string beforeStr, DateObject 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 = $"{DateTimeFormatUtil.LuisDate(resultDateTime)}"; } else if (mode.Equals(AgoLaterMode.DateTime)) { ret.Timex = $"{DateTimeFormatUtil.LuisDateTime(resultDateTime)}"; } ret.FutureValue = ret.PastValue = resultDateTime; ret.SubDateTimeEntities = new List <object> { durationParseResult }; ret.Success = true; } return(ret); }
private static DateTimeResolutionResult GetAgoLaterResult( DateTimeParseResult durationParseResult, string afterStr, string beforeStr, DateObject referenceTime, IParser numberParser, IDateTimeUtilityConfiguration utilityConfiguration, AgoLaterMode mode, SwiftDayDelegate swiftDay) { var ret = new DateTimeResolutionResult(); var resultDateTime = referenceTime; var timex = durationParseResult.TimexStr; if (((DateTimeResolutionResult)durationParseResult.Value).Mod == Constants.MORE_THAN_MOD) { ret.Mod = Constants.MORE_THAN_MOD; } else if (((DateTimeResolutionResult)durationParseResult.Value).Mod == Constants.LESS_THAN_MOD) { ret.Mod = Constants.LESS_THAN_MOD; } int swift = 0; bool isMatch = false, isLater = false; string dayStr = null; var agoLaterRegexes = new List <(Regex, string)> { (utilityConfiguration.AgoRegex, "ago"), (utilityConfiguration.LaterRegex, "later"), }; // AgoRegex and LaterRegex cases foreach (var regex in agoLaterRegexes) { // Match in afterStr if (MatchingUtil.ContainsAgoLaterIndex(afterStr, regex.Item1, inSuffix: true)) { isMatch = true; isLater = regex.Item2 == "later" ? true : false; var match = regex.Item1.Match(afterStr); dayStr = match.Groups["day"].Value; } if (utilityConfiguration.CheckBothBeforeAfter) { // Match split between beforeStr and afterStr if (string.IsNullOrEmpty(dayStr) && isMatch) { var match = regex.Item1.Match(beforeStr + " " + afterStr); dayStr = match.Groups["day"].Value; } // Match in beforeStr if (string.IsNullOrEmpty(dayStr) && MatchingUtil.ContainsAgoLaterIndex(beforeStr, regex.Item1, inSuffix: false)) { isMatch = true; isLater = regex.Item2 == "later" ? true : false; var match = regex.Item1.Match(beforeStr); dayStr = match.Groups["day"].Value; } } if (isMatch) { break; } } // InConnectorRegex cases if (!isMatch) { if (MatchingUtil.ContainsTermIndex(beforeStr, utilityConfiguration.InConnectorRegex)) { // Match in afterStr isMatch = isLater = true; var match = utilityConfiguration.LaterRegex.Match(afterStr); dayStr = match.Groups["day"].Value; } else if (utilityConfiguration.CheckBothBeforeAfter && MatchingUtil.ContainsAgoLaterIndex(afterStr, utilityConfiguration.InConnectorRegex, inSuffix: true)) { // Match in beforeStr isMatch = isLater = true; var match = utilityConfiguration.LaterRegex.Match(beforeStr); dayStr = match.Groups["day"].Value; } } if (isMatch) { // Handle cases like "3 days before yesterday", "3 days after tomorrow" if (!string.IsNullOrEmpty(dayStr)) { swift = swiftDay(dayStr); } if (isLater) { var yearMatch = utilityConfiguration.SinceYearSuffixRegex.Match(afterStr); if (yearMatch.Success) { var yearString = yearMatch.Groups[Constants.YearGroupName].Value; var yearEr = new ExtractResult { Text = yearString }; var year = Convert.ToInt32((double)(numberParser.Parse(yearEr).Value ?? 0)); referenceTime = DateObject.MinValue.SafeCreateFromValue(year, 1, 1); } } resultDateTime = DurationParsingUtil.ShiftDateTime(timex, referenceTime.AddDays(swift), isLater ? true : false); ((DateTimeResolutionResult)durationParseResult.Value).Mod = isLater ? Constants.AFTER_MOD : Constants.BEFORE_MOD; } if (resultDateTime != referenceTime) { if (mode.Equals(AgoLaterMode.Date)) { ret.Timex = $"{DateTimeFormatUtil.LuisDate(resultDateTime)}"; } else if (mode.Equals(AgoLaterMode.DateTime)) { ret.Timex = $"{DateTimeFormatUtil.LuisDateTime(resultDateTime)}"; } ret.FutureValue = ret.PastValue = resultDateTime; ret.SubDateTimeEntities = new List <object> { durationParseResult }; ret.Success = true; } return(ret); }
public static string GenerateDateTimePeriodTimex(DateObject beginDateTime, DateObject endDateTime, string durationTimex) { return(GenerateDateTimePeriodTimex(DateTimeFormatUtil.LuisDateTime(beginDateTime), DateTimeFormatUtil.LuisDateTime(endDateTime), durationTimex)); }
private DateTimeResolutionResult MergeTwoTimePoints(string text, DateObject referenceTime) { var ret = new DateTimeResolutionResult(); DateTimeParseResult pr1 = null, pr2 = null; bool bothHaveDates = false, beginHasDate = false, endHasDate = false; var er1 = this.config.TimeExtractor.Extract(text, referenceTime); var er2 = this.config.DateTimeExtractor.Extract(text, referenceTime); var rightTime = DateObject.MinValue.SafeCreateFromValue(referenceTime.Year, referenceTime.Month, referenceTime.Day); var leftTime = DateObject.MinValue.SafeCreateFromValue(referenceTime.Year, referenceTime.Month, referenceTime.Day); if (er2.Count == 2) { pr1 = this.config.DateTimeParser.Parse(er2[0], referenceTime); pr2 = this.config.DateTimeParser.Parse(er2[1], referenceTime); bothHaveDates = true; } else if (er2.Count == 1 && er1.Count == 2) { if (!er2[0].IsOverlap(er1[0])) { pr1 = this.config.TimeParser.Parse(er1[0], referenceTime); pr2 = this.config.DateTimeParser.Parse(er2[0], referenceTime); endHasDate = true; } else { pr1 = this.config.DateTimeParser.Parse(er2[0], referenceTime); pr2 = this.config.TimeParser.Parse(er1[1], referenceTime); beginHasDate = true; } } else if (er2.Count == 1 && er1.Count == 1) { if (er1[0].Start < er2[0].Start) { pr1 = this.config.TimeParser.Parse(er1[0], referenceTime); pr2 = this.config.DateTimeParser.Parse(er2[0], referenceTime); endHasDate = true; } else { pr1 = this.config.DateTimeParser.Parse(er2[0], referenceTime); pr2 = this.config.TimeParser.Parse(er1[0], referenceTime); beginHasDate = true; } } else if (er1.Count == 2) { // if both ends are Time. then this is a TimePeriod, not a DateTimePeriod return(ret); } else { return(ret); } if (pr1.Value == null || pr2.Value == null) { return(ret); } DateObject futureBegin = (DateObject)((DateTimeResolutionResult)pr1.Value).FutureValue, futureEnd = (DateObject)((DateTimeResolutionResult)pr2.Value).FutureValue; DateObject pastBegin = (DateObject)((DateTimeResolutionResult)pr1.Value).PastValue, pastEnd = (DateObject)((DateTimeResolutionResult)pr2.Value).PastValue; if (futureBegin > futureEnd) { futureBegin = pastBegin; } if (pastEnd < pastBegin) { pastEnd = futureEnd; } if (bothHaveDates) { rightTime = DateObject.MinValue.SafeCreateFromValue(futureEnd.Year, futureEnd.Month, futureEnd.Day); leftTime = DateObject.MinValue.SafeCreateFromValue(futureBegin.Year, futureBegin.Month, futureBegin.Day); } else if (beginHasDate) { // TODO: Handle "明天下午两点到五点" futureEnd = DateObject.MinValue.SafeCreateFromValue( futureBegin.Year, futureBegin.Month, futureBegin.Day, futureEnd.Hour, futureEnd.Minute, futureEnd.Second); pastEnd = DateObject.MinValue.SafeCreateFromValue( pastBegin.Year, pastBegin.Month, pastBegin.Day, pastEnd.Hour, pastEnd.Minute, pastEnd.Second); leftTime = DateObject.MinValue.SafeCreateFromValue(futureBegin.Year, futureBegin.Month, futureBegin.Day); } else if (endHasDate) { // TODO: Handle "明天下午两点到五点" futureBegin = DateObject.MinValue.SafeCreateFromValue( futureEnd.Year, futureEnd.Month, futureEnd.Day, futureBegin.Hour, futureBegin.Minute, futureBegin.Second); pastBegin = DateObject.MinValue.SafeCreateFromValue( pastEnd.Year, pastEnd.Month, pastEnd.Day, pastBegin.Hour, pastBegin.Minute, pastBegin.Second); rightTime = DateObject.MinValue.SafeCreateFromValue(futureEnd.Year, futureEnd.Month, futureEnd.Day); } var leftResult = (DateTimeResolutionResult)pr1.Value; var rightResult = (DateTimeResolutionResult)pr2.Value; var leftResultTime = (DateObject)leftResult.FutureValue; var rightResultTime = (DateObject)rightResult.FutureValue; int day = referenceTime.Day, month = referenceTime.Month, year = referenceTime.Year; // check if the right time is smaller than the left time, if yes, add one day int hour = leftResultTime.Hour > 0 ? leftResultTime.Hour : 0, min = leftResultTime.Minute > 0 ? leftResultTime.Minute : 0, second = leftResultTime.Second > 0 ? leftResultTime.Second : 0; leftTime = leftTime.AddHours(hour); leftTime = leftTime.AddMinutes(min); leftTime = leftTime.AddSeconds(second); DateObject.MinValue.SafeCreateFromValue(year, month, day, hour, min, second); hour = rightResultTime.Hour > 0 ? rightResultTime.Hour : 0; min = rightResultTime.Minute > 0 ? rightResultTime.Minute : 0; second = rightResultTime.Second > 0 ? rightResultTime.Second : 0; rightTime = rightTime.AddHours(hour); rightTime = rightTime.AddMinutes(min); rightTime = rightTime.AddSeconds(second); // the right side time contains "ampm", while the left side doesn't if (rightResult.Comment is Constants.Comment_AmPm && leftResult.Comment == null && rightTime < leftTime) { rightTime = rightTime.AddHours(Constants.HalfDayHourCount); } if (rightTime < leftTime) { rightTime = rightTime.AddDays(1); } ret.FutureValue = ret.PastValue = new Tuple <DateObject, DateObject>(leftTime, rightTime); var leftTimex = string.Empty; var rightTimex = string.Empty; // "X" is timex token for not determined time if (!pr1.TimexStr.Contains("X") && !pr2.TimexStr.Contains("X")) { leftTimex = DateTimeFormatUtil.LuisDateTime(leftTime); rightTimex = DateTimeFormatUtil.LuisDateTime(rightTime); } else { leftTimex = pr1.TimexStr; rightTimex = pr2.TimexStr; } ret.Timex = $"({leftTimex},{rightTimex},PT{Convert.ToInt32((rightTime - leftTime).TotalHours)}H)"; ret.Success = true; return(ret); }
// handle cases like "5分钟前", "1小时以后" private DateTimeResolutionResult ParserDurationWithAgoAndLater(string text, DateObject referenceDate) { var ret = new DateTimeResolutionResult(); var durationRes = this.config.DurationExtractor.Extract(text, referenceDate); if (durationRes.Count > 0) { var matchAgoLater = this.config.AgoLaterRegex.Match(text); if (matchAgoLater.Success) { var pr = config.DurationParser.Parse(durationRes[0], referenceDate); var isFuture = matchAgoLater.Groups[Constants.LaterGroupName].Success; var timex = pr.TimexStr; var resultDateTime = DurationParsingUtil.ShiftDateTime(timex, referenceDate, future: isFuture); ret.Timex = $"{DateTimeFormatUtil.LuisDateTime(resultDateTime)}"; ret.FutureValue = ret.PastValue = resultDateTime; ret.SubDateTimeEntities = new List <object> { pr }; ret.Success = true; return(ret); } var match = this.config.DateTimePeriodUnitRegex.Match(text); if (match.Success) { var suffix = text.Substring((int)durationRes[0].Start + (int)durationRes[0].Length).Trim(); var srcUnit = match.Groups[Constants.UnitGroupName].Value; var numberStr = text.Substring((int)durationRes[0].Start, match.Index - (int)durationRes[0].Start).Trim(); var number = ConvertCJKToNum(numberStr); if (this.config.UnitMap.ContainsKey(srcUnit)) { var unitStr = this.config.UnitMap[srcUnit]; var beforeMatch = this.config.BeforeRegex.Match(suffix); if (beforeMatch.Success && suffix.StartsWith(beforeMatch.Value, StringComparison.InvariantCulture)) { DateObject date; switch (unitStr) { case Constants.TimexHour: date = referenceDate.AddHours(-number); break; case Constants.TimexMinute: date = referenceDate.AddMinutes(-number); break; case Constants.TimexSecond: date = referenceDate.AddSeconds(-number); break; default: return(ret); } ret.Timex = $"{DateTimeFormatUtil.LuisDate(date)}"; ret.FutureValue = ret.PastValue = date; ret.Success = true; return(ret); } var afterMatch = this.config.AfterRegex.Match(suffix); if (afterMatch.Success && suffix.StartsWith(afterMatch.Value, StringComparison.Ordinal)) { DateObject date; switch (unitStr) { case Constants.TimexHour: date = referenceDate.AddHours(number); break; case Constants.TimexMinute: date = referenceDate.AddMinutes(number); break; case Constants.TimexSecond: date = referenceDate.AddSeconds(number); break; default: return(ret); } ret.Timex = $"{DateTimeFormatUtil.LuisDate(date)}"; ret.FutureValue = ret.PastValue = date; ret.Success = true; return(ret); } } } } return(ret); }
private static DateTimeResolutionResult GetAgoLaterResult( DateTimeParseResult durationParseResult, string afterStr, string beforeStr, DateObject referenceTime, IParser numberParser, IDateTimeUtilityConfiguration utilityConfiguration, AgoLaterMode mode, SwiftDayDelegate swiftDay) { var ret = new DateTimeResolutionResult(); var resultDateTime = referenceTime; var timex = durationParseResult.TimexStr; if (((DateTimeResolutionResult)durationParseResult.Value).Mod == Constants.MORE_THAN_MOD) { ret.Mod = Constants.MORE_THAN_MOD; } else if (((DateTimeResolutionResult)durationParseResult.Value).Mod == Constants.LESS_THAN_MOD) { ret.Mod = Constants.LESS_THAN_MOD; } if (MatchingUtil.ContainsAgoLaterIndex(afterStr, utilityConfiguration.AgoRegex)) { var match = utilityConfiguration.AgoRegex.Match(afterStr); var swift = 0; // Handle cases like "3 days before yesterday" if (match.Success && !string.IsNullOrEmpty(match.Groups["day"].Value)) { swift = swiftDay(match.Groups["day"].Value); } else if (utilityConfiguration.CheckBothBeforeAfter && match.Success && !MatchingUtil.ContainsAgoLaterIndexInBeforeString(beforeStr, utilityConfiguration.AgoRegex)) { match = utilityConfiguration.AgoRegex.Match(beforeStr + " " + afterStr); if (match.Success && !string.IsNullOrEmpty(match.Groups["day"].Value)) { swift = swiftDay(match.Groups["day"].Value); } } resultDateTime = DurationParsingUtil.ShiftDateTime(timex, referenceTime.AddDays(swift), false); ((DateTimeResolutionResult)durationParseResult.Value).Mod = Constants.BEFORE_MOD; } else if (utilityConfiguration.CheckBothBeforeAfter && MatchingUtil.ContainsAgoLaterIndexInBeforeString(beforeStr, utilityConfiguration.AgoRegex)) { var match = utilityConfiguration.AgoRegex.Match(beforeStr); var swift = 0; // Handle cases like "3 days before yesterday" if (match.Success && !string.IsNullOrEmpty(match.Groups["day"].Value)) { swift = swiftDay(match.Groups["day"].Value); } resultDateTime = DurationParsingUtil.ShiftDateTime(timex, referenceTime.AddDays(swift), false); ((DateTimeResolutionResult)durationParseResult.Value).Mod = Constants.BEFORE_MOD; } else if (MatchingUtil.ContainsAgoLaterIndex(afterStr, utilityConfiguration.LaterRegex) || MatchingUtil.ContainsTermIndex(beforeStr, utilityConfiguration.InConnectorRegex) || (utilityConfiguration.CheckBothBeforeAfter && MatchingUtil.ContainsAgoLaterIndexInBeforeString(beforeStr, utilityConfiguration.LaterRegex))) { var match = utilityConfiguration.LaterRegex.Match(afterStr); var swift = 0; if (utilityConfiguration.CheckBothBeforeAfter && MatchingUtil.ContainsAgoLaterIndexInBeforeString(beforeStr, utilityConfiguration.LaterRegex) && string.IsNullOrEmpty(match.Groups["day"].Value)) { match = utilityConfiguration.LaterRegex.Match(beforeStr); } // Handle cases like "3 days after tomorrow" if (match.Success && !string.IsNullOrEmpty(match.Groups["day"].Value)) { swift = swiftDay(match.Groups["day"].Value); } var yearMatch = utilityConfiguration.SinceYearSuffixRegex.Match(afterStr); if (yearMatch.Success) { var yearString = yearMatch.Groups[Constants.YearGroupName].Value; var yearEr = new ExtractResult { Text = yearString }; var year = Convert.ToInt32((double)(numberParser.Parse(yearEr).Value ?? 0)); referenceTime = DateObject.MinValue.SafeCreateFromValue(year, 1, 1); } resultDateTime = DurationParsingUtil.ShiftDateTime(timex, referenceTime.AddDays(swift), true); ((DateTimeResolutionResult)durationParseResult.Value).Mod = Constants.AFTER_MOD; } else if (utilityConfiguration.CheckBothBeforeAfter && (MatchingUtil.ContainsAgoLaterIndexInBeforeString(beforeStr, utilityConfiguration.LaterRegex) || MatchingUtil.ContainsAgoLaterIndex(afterStr, utilityConfiguration.InConnectorRegex) || MatchingUtil.ContainsAgoLaterIndex(afterStr, utilityConfiguration.LaterRegex))) { // Check also beforeStr var match = utilityConfiguration.LaterRegex.Match(beforeStr); var swift = 0; if (MatchingUtil.ContainsAgoLaterIndex(afterStr, utilityConfiguration.LaterRegex) && string.IsNullOrEmpty(match.Groups["day"].Value)) { match = utilityConfiguration.LaterRegex.Match(beforeStr); } // Handle cases like "3 days after tomorrow" if (match.Success && !string.IsNullOrEmpty(match.Groups["day"].Value)) { swift = swiftDay(match.Groups["day"].Value); } var yearMatch = utilityConfiguration.SinceYearSuffixRegex.Match(beforeStr); if (yearMatch.Success) { var yearString = yearMatch.Groups[Constants.YearGroupName].Value; var yearEr = new ExtractResult { Text = yearString }; var year = Convert.ToInt32((double)(numberParser.Parse(yearEr).Value ?? 0)); referenceTime = DateObject.MinValue.SafeCreateFromValue(year, 1, 1); } resultDateTime = DurationParsingUtil.ShiftDateTime(timex, referenceTime.AddDays(swift), true); ((DateTimeResolutionResult)durationParseResult.Value).Mod = Constants.AFTER_MOD; } if (resultDateTime != referenceTime) { if (mode.Equals(AgoLaterMode.Date)) { ret.Timex = $"{DateTimeFormatUtil.LuisDate(resultDateTime)}"; } else if (mode.Equals(AgoLaterMode.DateTime)) { ret.Timex = $"{DateTimeFormatUtil.LuisDateTime(resultDateTime)}"; } ret.FutureValue = ret.PastValue = resultDateTime; ret.SubDateTimeEntities = new List <object> { durationParseResult }; ret.Success = true; } return(ret); }