in JavaScript/packages/recognizers-date-time/src/dateTime/baseTimePeriod.ts [364:618]
private parseSpecificTimeCases(source: string, reference: Date): DateTimeResolutionResult {
let result = new DateTimeResolutionResult();
let year = reference.getFullYear();
let month = reference.getMonth();
let day = reference.getDate();
let trimmedText = source.trim().toLowerCase();
// Handle cases like "from 4:30 to 5"
let match = RegExpUtility.getMatches(this.config.specificTimeFromToRegex, source).pop();
if (!match) {
// Handle cases like "between 5:10 and 7"
match = RegExpUtility.getMatches(this.config.specificTimeBetweenAndRegex, source).pop();
}
if (match && match.index === 0 && match.index + match.length === trimmedText.length) {
// Cases like "half past seven" are not handled here
if (match.groups('prefix').value !== '') {
return result;
}
// Cases like "4" is different with "4:00" as the Timex is different "T04H" vs "T04H00M"
// Uses this invalidFlag to differentiate
let beginHour: number;
let invalidFlag = -1;
let beginMinute = invalidFlag;
let beginSecond = invalidFlag;
let endHour: number;
let endMinute = invalidFlag;
let endSecond = invalidFlag;
// Get time1 and time2
let hourGroup = match.groups('hour');
let hourStr = hourGroup.captures[0];
if (this.config.numbers.has(hourStr)) {
beginHour = this.config.numbers.get(hourStr);
}
else {
beginHour = parseInt(hourStr, 10);
}
hourStr = hourGroup.captures[1];
if (this.config.numbers.has(hourStr)) {
endHour = this.config.numbers.get(hourStr);
}
else {
endHour = parseInt(hourStr, 10);
}
let time1StartIndex = match.groups('time1').index;
let time1EndIndex = time1StartIndex + match.groups('time1').length;
let time2StartIndex = match.groups('time2').index;
let time2EndIndex = time2StartIndex + match.groups('time2').length;
// Get beginMinute (if exists) and endMinute (if exists)
let lastGroupIndex = 0;
for (let i = 0; i < match.groups('min').captures.length; i++) {
let minuteCapture = match.groups('min').captures[i];
let minuteCaptureIndex = source.indexOf(minuteCapture, lastGroupIndex);
if (minuteCaptureIndex >= time1StartIndex && minuteCaptureIndex + minuteCapture.length <= time1EndIndex) {
beginMinute = parseInt(minuteCapture, 10);
}
else if (minuteCaptureIndex >= time2StartIndex && minuteCaptureIndex + minuteCapture.length <= time2EndIndex) {
endMinute = parseInt(minuteCapture, 10);
}
lastGroupIndex = minuteCaptureIndex + 1;
}
lastGroupIndex = 0;
// Get beginSecond (if exists) and endSecond (if exists)
for (let i = 0; i < match.groups('sec').captures.length; i++) {
let secondCapture = match.groups('sec').captures[i];
let secondCaptureIndex = source.indexOf(secondCapture, lastGroupIndex);
if (secondCaptureIndex >= time1StartIndex && secondCaptureIndex + secondCapture.length <= time1EndIndex) {
beginSecond = parseInt(secondCapture, 10);
}
else if (secondCaptureIndex >= time2StartIndex && secondCaptureIndex + secondCapture.length <= time2EndIndex) {
endSecond = parseInt(secondCapture, 10);
}
lastGroupIndex = secondCaptureIndex + 1;
}
lastGroupIndex = 0;
// Desc here means descriptions like "am / pm / o'clock"
// Get leftDesc (if exists) and rightDesc (if exists)
let leftDesc = match.groups('leftDesc').value;
let rightDesc = match.groups('rightDesc').value;
for (let i = 0; i < match.groups('desc').captures.length; i++) {
let descCapture = match.groups('desc').captures[i];
let descCaptureIndex = source.indexOf(descCapture, lastGroupIndex);
if (descCaptureIndex >= time1StartIndex && descCaptureIndex + descCapture.length <= time1EndIndex && StringUtility.isNullOrEmpty(leftDesc)) {
leftDesc = descCapture;
}
else if (descCaptureIndex >= time2StartIndex && descCaptureIndex + descCapture.length <= time2EndIndex && StringUtility.isNullOrEmpty(rightDesc)) {
rightDesc = descCapture;
}
lastGroupIndex = descCaptureIndex + 1;
}
let beginDateTime = DateUtils.safeCreateFromMinValue(year, month, day, beginHour, beginMinute >= 0 ? beginMinute : 0, beginSecond >= 0 ? beginSecond : 0);
let endDateTime = DateUtils.safeCreateFromMinValue(year, month, day, endHour, endMinute >= 0 ? endMinute : 0, endSecond >= 0 ? endSecond : 0);
let hasLeftAm = !StringUtility.isNullOrEmpty(leftDesc) && leftDesc.toLowerCase().startsWith('a');
let hasLeftPm = !StringUtility.isNullOrEmpty(leftDesc) && leftDesc.toLowerCase().startsWith('p');
let hasRightAm = !StringUtility.isNullOrEmpty(rightDesc) && rightDesc.toLowerCase().startsWith('a');
let hasRightPm = !StringUtility.isNullOrEmpty(rightDesc) && rightDesc.toLowerCase().startsWith('p');
let hasLeft = hasLeftAm || hasLeftPm;
let hasRight = hasRightAm || hasRightPm;
// Both timepoint has description like 'am' or 'pm'
if (hasLeft && hasRight) {
if (hasLeftAm) {
if (beginHour >= 12) {
beginDateTime = DateUtils.addHours(beginDateTime, -12);
}
}
else if (hasLeftPm) {
if (beginHour < 12) {
beginDateTime = DateUtils.addHours(beginDateTime, 12);
}
}
if (hasRightAm) {
if (endHour >= 12) {
endDateTime = DateUtils.addHours(endDateTime, -12);
}
}
else if (hasRightPm) {
if (endHour < 12) {
endDateTime = DateUtils.addHours(endDateTime, 12);
}
}
}
else if (hasLeft || hasRight) {
if (hasLeftAm) {
if (beginHour >= 12) {
beginDateTime = DateUtils.addHours(beginDateTime, -12);
}
if (endHour < 12) {
if (endDateTime < beginDateTime) {
endDateTime = DateUtils.addHours(endDateTime, 12);
}
}
}
else if (hasLeftPm) {
if (beginHour < 12) {
beginDateTime = DateUtils.addHours(beginDateTime, 12);
}
if (endHour < 12) {
if (endDateTime.getTime() < beginDateTime.getTime()) {
let span = DateUtils.totalHoursFloor(beginDateTime, endDateTime);
if (span >= 12) {
endDateTime = DateUtils.addHours(endDateTime, 24);
}
else {
endDateTime = DateUtils.addHours(endDateTime, 12);
}
}
}
}
if (hasRightAm) {
if (endHour >= 12) {
endDateTime = DateUtils.addHours(endDateTime, -12);
}
if (beginHour < 12) {
if (endDateTime.getTime() < beginDateTime.getTime()) {
beginDateTime = DateUtils.addHours(beginDateTime, -12);
}
}
}
else if (hasRightPm) {
if (endHour < 12) {
endDateTime = DateUtils.addHours(endDateTime, 12);
}
if (beginHour < 12) {
if (endDateTime.getTime() < beginDateTime.getTime()) {
beginDateTime = DateUtils.addHours(beginDateTime, -12);
}
else {
let span = DateUtils.totalHoursFloor(endDateTime, beginDateTime);
if (span > 12) {
beginDateTime = DateUtils.addHours(beginDateTime, 12);
}
}
}
}
}
else if (!hasLeft && !hasRight && beginHour <= 12 && endHour <= 12) {
if (beginHour > endHour) {
if (beginHour === 12) {
beginDateTime = DateUtils.addHours(beginDateTime, -12);
}
else {
endDateTime = DateUtils.addHours(endDateTime, 12);
}
}
result.comment = Constants.CommentAmPm;
}
if (endDateTime.getTime() < beginDateTime.getTime()) {
endDateTime = DateUtils.addHours(endDateTime, 24);
}
let beginStr = DateTimeFormatUtil.shortTime(beginDateTime.getHours(), beginMinute, beginSecond);
let endStr = DateTimeFormatUtil.shortTime(endDateTime.getHours(), endMinute, endSecond);
result.success = true;
result.timex = `(${beginStr},${endStr},${DateTimeFormatUtil.luisTimeSpan(endDateTime, beginDateTime)})`;
result.futureValue = result.pastValue = { item1: beginDateTime, item2: endDateTime };
result.subDateTimeEntities = [];
// 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) {
let er = {
start: time1StartIndex,
length: time1EndIndex - time1StartIndex,
text: source.substring(time1StartIndex, time1EndIndex),
type: Constants.SYS_DATETIME_TIME
} as ExtractResult;
let pr = this.config.timeParser.parse(er, reference);
result.subDateTimeEntities.push(pr);
}
// Cases like "from 4am to 5", "5" should not be treated as SubDateTimeEntity
if (hasRight || endMinute !== invalidFlag || endSecond !== invalidFlag) {
let er = {
start: time2StartIndex,
length: time2EndIndex - time2StartIndex,
text: source.substring(time2StartIndex, time2EndIndex),
type: Constants.SYS_DATETIME_TIME
} as ExtractResult;
let pr = this.config.timeParser.parse(er, reference);
result.subDateTimeEntities.push(pr);
}
}
return result;
}