in Python/libraries/recognizers-date-time/recognizers_date_time/date_time/base_datetimeperiod.py [0:0]
def parse_specific_time_of_day(self, source: str, reference: datetime) -> DateTimeResolutionResult:
result = DateTimeResolutionResult()
trimmed_source = source.strip()
time_text = trimmed_source
match = regex.search(self.config.period_time_of_day_with_date_regex, trimmed_source)
# Extract early/late prefix from text if any
has_early = False
has_late = False
if match:
time_text = RegExpUtility.get_group(match, Constants.TIME_OF_DAY_GROUP_NAME)
if RegExpUtility.get_group(match, Constants.COMMENT_EARLY):
has_early = True
result.comment = Constants.COMMENT_EARLY
result.mod = TimeTypeConstants.EARLY_MOD
if RegExpUtility.get_group(match, Constants.COMMENT_LATE):
has_late = True
result.comment = Constants.COMMENT_LATE
result.mod = TimeTypeConstants.LATE_MOD
else:
match = self.config.am_desc_regex.match(trimmed_source)
if not match:
match = self.config.pm_desc_regex.match(trimmed_source)
else:
time_text = match.group()
# handle time of day
# Late/early only works with time of day
# Only standard time of day (morning, afternoon, evening and night) will not directly return
values = self.config.get_matched_time_range(time_text)
if not values.success:
return result
# 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 has_early:
values.end_hour = values.begin_hour + 2
if values.end_min == 59:
values.end_min = 0
elif has_late:
values.begin_hour = values.begin_hour + 2
if RegExpUtility.is_exact_match(self.config.specific_time_of_day_regex, trimmed_source, True):
swift = self.config.get_swift_prefix(trimmed_source)
date = (reference + timedelta(days=swift)).date()
day = date.day
month = date.month
year = date.year
result.timex = DateTimeFormatUtil.format_date(date) + values.time_str
result.future_value = result.past_value = (DateUtils.safe_create_from_min_value(year, month, day,
values.begin_hour, 0, 0),
DateUtils.safe_create_from_min_value(year, month, day,
values.end_hour, values.end_min, values.end_min))
result.success = True
return result
# Handle Date followed by morning, afternoon and morning, afternoon followed by Date
match = self.config.period_time_of_day_with_date_regex.search(trimmed_source)
if not match:
match = self.config.am_desc_regex.sarch(trimmed_source)
if not match:
match = self.config.pm_desc_regex.search(trimmed_source)
else:
before_str = trimmed_source[0:match.start()].strip()
_before_str = before_str
trimmed_before_str = ''
after_str = trimmed_source[match.end():].strip()
_after_str = after_str
trimmed_after_str = ''
# Eliminate time period, if any
time_period_extract_results = self.config.time_period_extractor.extract(before_str)
if len(time_period_extract_results) > 0:
start = time_period_extract_results[0].start
length = time_period_extract_results[0].length
for i in range(start, length):
trimmed_before_str = _before_str.replace(_before_str[start], '', 1)
_before_str = trimmed_before_str
trimmed_before_str = trimmed_before_str.strip()
else:
time_period_extract_results = self.config.time_period_extractor.extract(after_str)
if len(time_period_extract_results) > 0:
start = time_period_extract_results[0].start
length = time_period_extract_results[0].length
for i in range(start, length):
trimmed_after_str = _after_str.replace(_after_str[start], '', 1)
_before_str = trimmed_after_str
trimmed_after_str = trimmed_after_str.strip()
extracted_results = self.config.date_extractor.extract((trimmed_before_str if trimmed_before_str is not '' else before_str) + ' ' + (trimmed_after_str if trimmed_after_str is not '' else after_str), reference)
if len(extracted_results) == 0 or extracted_results[0].length < len(trimmed_before_str):
valid = False
if len(extracted_results) > 0 and extracted_results[0].start == 0:
mid_str = before_str[extracted_results[0].start + extracted_results[0].length:]
if mid_str.replace(',', ' '):
valid = True
if not valid:
extracted_results = self.config.date_extractor.extract(after_str, reference)
if len(extracted_results) == 0 or extracted_results[0].length != len(after_str):
if len(extracted_results) > 0 and extracted_results[0].start + extracted_results[0].length ==\
len(after_str):
mid_str = after_str[0:extracted_results[0].start]
if not mid_str.replace(',', ' '):
valid = True
else:
valid = True
if not valid:
return result
has_specific_time_period = False
if len(time_period_extract_results) > 0:
time_parse_result = self.config.time_period_parser.parse(time_period_extract_results[0], reference)
if time_parse_result:
period_future = (time_parse_result.value.future_value.start, time_parse_result.value.future_value.end)
period_past = (time_parse_result.value.past_value.start, time_parse_result.value.past_value.end)
if period_future == period_past:
values.begin_hour = period_future[0].hour
values.end_hour = period_future[1].hour
else:
if period_future[0].hour >= values.begin_hour or period_future[1].hour <= values.end_hour:
values.begin_hour = period_future[0].hour
values.end_hour = period_future[1].hour
else:
values.begin_hour = period_past[0].hour
values.end_hour = period_past[1].hour
has_specific_time_period = True
parse_result = self.config.date_parser.parse(extracted_results[0], reference)
future_date = parse_result.value.future_value
past_date = parse_result.value.past_value
if not has_specific_time_period:
result.timex = parse_result.timex_str + values.time_str
else:
format_str = '({}T{},{}T{},PT{}H)'
result.timex = format_str.format(parse_result.timex_str, values.begin_hour, parse_result.timex_str, values.end_hour,
values.end_hour - values.begin_hour)
result.future_value = (DateUtils.safe_create_from_min_value(future_date.year, future_date.month,
future_date.day, values.begin_hour, 0, 0),
DateUtils.safe_create_from_min_value(future_date.year, future_date.month,
future_date.day, values.end_hour, values.end_min, values.end_min))
result.past_value = (DateUtils.safe_create_from_min_value(past_date.year, past_date.month,
past_date.day, values.begin_hour, 0, 0),
DateUtils.safe_create_from_min_value(past_date.year, past_date.month,
past_date.day, values.end_hour, values.end_min, values.end_min))
result.success = True
return result
return result