private DateTimeResolutionResult MergeDateWithSingleTimePeriod(string text, DateObject referenceTime) { var ret = new DateTimeResolutionResult(); var trimmedText = text.Trim().ToLower(); var ers = Config.TimePeriodExtractor.Extract(trimmedText, referenceTime); if (ers.Count == 0) { return(ParsePureNumberCases(text, referenceTime)); } else if (ers.Count == 1) { var timePeriodParseResult = Config.TimePeriodParser.Parse(ers[0]); var timePeriodResolutionResult = (DateTimeResolutionResult)timePeriodParseResult.Value; if (timePeriodResolutionResult == null) { return(ParsePureNumberCases(text, referenceTime)); } if (timePeriodResolutionResult.TimeZoneResolution != null) { ret.TimeZoneResolution = timePeriodResolutionResult.TimeZoneResolution; } var timePeriodTimex = timePeriodResolutionResult.Timex; // If it is a range type timex if (TimexUtility.IsRangeTimex(timePeriodTimex)) { var dateResult = this.Config.DateExtractor.Extract(trimmedText.Replace(ers[0].Text, ""), referenceTime); var dateText = trimmedText.Replace(ers[0].Text, "").Replace(Config.TokenBeforeDate, "").Trim(); // If only one Date is extracted and the Date text equals to the rest part of source text if (dateResult.Count == 1 && dateText.Equals(dateResult[0].Text)) { string dateTimex; DateObject futureTime; DateObject pastTime; var pr = this.Config.DateParser.Parse(dateResult[0], referenceTime); if (pr.Value != null) { futureTime = (DateObject)((DateTimeResolutionResult)pr.Value).FutureValue; pastTime = (DateObject)((DateTimeResolutionResult)pr.Value).PastValue; dateTimex = pr.TimexStr; } else { return(ParsePureNumberCases(text, referenceTime)); } var rangeTimexComponents = TimexUtility.GetRangeTimexComponents(timePeriodTimex); if (rangeTimexComponents.IsValid) { var beginTimex = TimexUtility.CombineDateAndTimeTimex(dateTimex, rangeTimexComponents.BeginTimex); var endTimex = TimexUtility.CombineDateAndTimeTimex(dateTimex, rangeTimexComponents.EndTimex); ret.Timex = TimexUtility.GenerateDateTimePeriodTimex(beginTimex, endTimex, rangeTimexComponents.DurationTimex); var timePeriodFutureValue = (Tuple <DateObject, DateObject>)timePeriodResolutionResult.FutureValue; var beginTime = timePeriodFutureValue.Item1; var endTime = timePeriodFutureValue.Item2; ret.FutureValue = new Tuple <DateObject, DateObject>( DateObject.MinValue.SafeCreateFromValue(futureTime.Year, futureTime.Month, futureTime.Day, beginTime.Hour, beginTime.Minute, beginTime.Second), DateObject.MinValue.SafeCreateFromValue(futureTime.Year, futureTime.Month, futureTime.Day, endTime.Hour, endTime.Minute, endTime.Second) ); ret.PastValue = new Tuple <DateObject, DateObject>( DateObject.MinValue.SafeCreateFromValue(pastTime.Year, pastTime.Month, pastTime.Day, beginTime.Hour, beginTime.Minute, beginTime.Second), DateObject.MinValue.SafeCreateFromValue(pastTime.Year, pastTime.Month, pastTime.Day, endTime.Hour, endTime.Minute, endTime.Second) ); if (!string.IsNullOrEmpty(timePeriodResolutionResult.Comment) && timePeriodResolutionResult.Comment.Equals(Constants.Comment_AmPm)) { // AmPm comment is used for later SetParserResult to judge whether this parse result should have two parsing results // Cases like "from 10:30 to 11 on 1/1/2015" should have AmPm comment, as it can be parsed to "10:30am to 11am" and also be parsed to "10:30pm to 11pm" // Cases like "from 10:30 to 3 on 1/1/2015" should not have AmPm comment if (beginTime.Hour < Constants.HalfDayHourCount && endTime.Hour < Constants.HalfDayHourCount) { ret.Comment = Constants.Comment_AmPm; } } ret.Success = true; ret.SubDateTimeEntities = new List <object> { pr, timePeriodParseResult }; return(ret); } } return(ParsePureNumberCases(text, referenceTime)); } } return(ret); }