chrono-node
Advanced tools
Comparing version 2.2.5 to 2.2.6
@@ -15,2 +15,3 @@ import { Parser, ParsingContext } from "../../chrono"; | ||
private checkAndReturnWithoutFollowingPattern; | ||
private checkAndReturnWithFollowingPattern; | ||
private cachedPrimaryPrefix; | ||
@@ -17,0 +18,0 @@ private cachedPrimarySuffix; |
@@ -6,3 +6,3 @@ "use strict"; | ||
function primaryTimePattern(primaryPrefix, primarySuffix) { | ||
return new RegExp("(^|\\s|T)" + | ||
return new RegExp("(^|\\s|T|\\b)" + | ||
`${primaryPrefix}` + | ||
@@ -66,24 +66,34 @@ "(\\d{1,4})" + | ||
} | ||
const result = context.createParsingResult(match.index + match[1].length, match[0].substring(match[1].length), startComponents); | ||
const remainingText = context.text.substring(match.index + match[0].length); | ||
const index = match.index + match[1].length; | ||
const text = match[0].substring(match[1].length); | ||
const result = context.createParsingResult(index, text, startComponents); | ||
match.index += match[0].length; | ||
const remainingText = context.text.substring(match.index); | ||
const followingPattern = this.getFollowingTimePatternThroughCache(); | ||
match = followingPattern.exec(remainingText); | ||
if (!match || | ||
match[0].match(/^\s*([+-])\s*\d{3,4}$/)) { | ||
const followingMatch = followingPattern.exec(remainingText); | ||
if (!followingMatch || | ||
followingMatch[0].match(/^\s*([+-])\s*\d{3,4}$/)) { | ||
return this.checkAndReturnWithoutFollowingPattern(result); | ||
} | ||
result.end = this.extractFollowingTimeComponents(context, match, result); | ||
result.end = this.extractFollowingTimeComponents(context, followingMatch, result); | ||
if (result.end) { | ||
if (result.end) { | ||
result.text += match[0]; | ||
} | ||
result.text += followingMatch[0]; | ||
} | ||
return result; | ||
return this.checkAndReturnWithFollowingPattern(result); | ||
} | ||
extractPrimaryTimeComponents(context, match, strict = false) { | ||
const components = context.createParsingComponents(); | ||
let hour = 0; | ||
let minute = 0; | ||
let meridiem = null; | ||
hour = parseInt(match[HOUR_GROUP]); | ||
let hour = parseInt(match[HOUR_GROUP]); | ||
if (hour > 100) { | ||
if (this.strictMode || match[MINUTE_GROUP] != null) { | ||
return null; | ||
} | ||
minute = hour % 100; | ||
hour = Math.floor(hour / 100); | ||
} | ||
if (hour > 24) { | ||
return null; | ||
} | ||
if (match[MINUTE_GROUP] != null) { | ||
@@ -95,10 +105,3 @@ if (match[MINUTE_GROUP].length == 1 && !match[AM_PM_HOUR_GROUP]) { | ||
} | ||
else if (hour > 100) { | ||
if (this.strictMode) { | ||
return null; | ||
} | ||
minute = hour % 100; | ||
hour = Math.floor(hour / 100); | ||
} | ||
if (minute >= 60 || hour > 24) { | ||
if (minute >= 60) { | ||
return null; | ||
@@ -265,2 +268,24 @@ } | ||
} | ||
checkAndReturnWithFollowingPattern(result) { | ||
if (result.text.match(/^\d+-\d+$/)) { | ||
return null; | ||
} | ||
const endingWithNumbers = result.text.match(/[^\d:.](\d[\d.]+)\s*-\s*(\d[\d.]+)$/); | ||
if (endingWithNumbers) { | ||
if (this.strictMode) { | ||
return null; | ||
} | ||
const startingNumbers = endingWithNumbers[1]; | ||
const endingNumbers = endingWithNumbers[2]; | ||
if (endingNumbers.includes(".") && !endingNumbers.match(/\d(\.\d{2})+$/)) { | ||
return null; | ||
} | ||
const endingNumberVal = parseInt(endingNumbers); | ||
const startingNumberVal = parseInt(startingNumbers); | ||
if (endingNumberVal > 24 || startingNumberVal > 24) { | ||
return null; | ||
} | ||
} | ||
return result; | ||
} | ||
getPrimaryTimePatternThroughCache() { | ||
@@ -267,0 +292,0 @@ const primaryPrefix = this.primaryPrefix(); |
@@ -20,2 +20,3 @@ "use strict"; | ||
configuration.refiners.unshift(new OverlapRemovalRefiner_1.default()); | ||
configuration.refiners.push(new OverlapRemovalRefiner_1.default()); | ||
configuration.refiners.push(new ForwardDateRefiner_1.default()); | ||
@@ -22,0 +23,0 @@ configuration.refiners.push(new UnlikelyFormatFilter_1.default(strictMode)); |
@@ -16,3 +16,3 @@ "use strict"; | ||
primarySuffix() { | ||
return "(?:\\s*(?:o\\W*clock|at\\s*night|in\\s*the\\s*(?:morning|afternoon)))?(?=\\W|$)"; | ||
return "(?:\\s*(?:o\\W*clock|at\\s*night|in\\s*the\\s*(?:morning|afternoon)))?(?!/)(?=\\W|$)"; | ||
} | ||
@@ -19,0 +19,0 @@ extractPrimaryTimeComponents(context, match) { |
@@ -18,3 +18,3 @@ { | ||
"license": "MIT", | ||
"version": "2.2.5", | ||
"version": "2.2.6", | ||
"directories": { | ||
@@ -21,0 +21,0 @@ "source": "./src", |
@@ -8,3 +8,3 @@ import { Parser, ParsingContext } from "../../chrono"; | ||
return new RegExp( | ||
"(^|\\s|T)" + | ||
"(^|\\s|T|\\b)" + | ||
`${primaryPrefix}` + | ||
@@ -76,19 +76,18 @@ "(\\d{1,4})" + | ||
if (!startComponents) { | ||
match.index += match[0].length; | ||
match.index += match[0].length; // Skip over potential overlapping pattern | ||
return null; | ||
} | ||
const result = context.createParsingResult( | ||
match.index + match[1].length, | ||
match[0].substring(match[1].length), | ||
startComponents | ||
); | ||
const index = match.index + match[1].length; | ||
const text = match[0].substring(match[1].length); | ||
const result = context.createParsingResult(index, text, startComponents); | ||
match.index += match[0].length; // Skip over potential overlapping pattern | ||
const remainingText = context.text.substring(match.index + match[0].length); | ||
const remainingText = context.text.substring(match.index); | ||
const followingPattern = this.getFollowingTimePatternThroughCache(); | ||
match = followingPattern.exec(remainingText); | ||
const followingMatch = followingPattern.exec(remainingText); | ||
if ( | ||
!match || | ||
!followingMatch || | ||
// Pattern "YY.YY -XXXX" is more like timezone offset | ||
match[0].match(/^\s*([+-])\s*\d{3,4}$/) | ||
followingMatch[0].match(/^\s*([+-])\s*\d{3,4}$/) | ||
) { | ||
@@ -98,10 +97,8 @@ return this.checkAndReturnWithoutFollowingPattern(result); | ||
result.end = this.extractFollowingTimeComponents(context, match, result); | ||
result.end = this.extractFollowingTimeComponents(context, followingMatch, result); | ||
if (result.end) { | ||
if (result.end) { | ||
result.text += match[0]; | ||
} | ||
result.text += followingMatch[0]; | ||
} | ||
return result; | ||
return this.checkAndReturnWithFollowingPattern(result); | ||
} | ||
@@ -115,3 +112,2 @@ | ||
const components = context.createParsingComponents(); | ||
let hour = 0; | ||
let minute = 0; | ||
@@ -121,4 +117,16 @@ let meridiem = null; | ||
// ----- Hours | ||
hour = parseInt(match[HOUR_GROUP]); | ||
let hour = parseInt(match[HOUR_GROUP]); | ||
if (hour > 100) { | ||
if (this.strictMode || match[MINUTE_GROUP] != null) { | ||
return null; | ||
} | ||
minute = hour % 100; | ||
hour = Math.floor(hour / 100); | ||
} | ||
if (hour > 24) { | ||
return null; | ||
} | ||
// ----- Minutes | ||
@@ -132,12 +140,5 @@ if (match[MINUTE_GROUP] != null) { | ||
minute = parseInt(match[MINUTE_GROUP]); | ||
} else if (hour > 100) { | ||
if (this.strictMode) { | ||
return null; | ||
} | ||
minute = hour % 100; | ||
hour = Math.floor(hour / 100); | ||
} | ||
if (minute >= 60 || hour > 24) { | ||
if (minute >= 60) { | ||
return null; | ||
@@ -343,2 +344,33 @@ } | ||
private checkAndReturnWithFollowingPattern(result) { | ||
if (result.text.match(/^\d+-\d+$/)) { | ||
return null; | ||
} | ||
// If it ends only with numbers or dots | ||
const endingWithNumbers = result.text.match(/[^\d:.](\d[\d.]+)\s*-\s*(\d[\d.]+)$/); | ||
if (endingWithNumbers) { | ||
// In strict mode (e.g. "at 1-3" or "at 1.2 - 2.3"), this should not be accepted | ||
if (this.strictMode) { | ||
return null; | ||
} | ||
const startingNumbers: string = endingWithNumbers[1]; | ||
const endingNumbers: string = endingWithNumbers[2]; | ||
// If it ends only with dot single digit, e.g. "at 1.2" | ||
if (endingNumbers.includes(".") && !endingNumbers.match(/\d(\.\d{2})+$/)) { | ||
return null; | ||
} | ||
// If it ends only with numbers above 24, e.g. "at 25" | ||
const endingNumberVal = parseInt(endingNumbers); | ||
const startingNumberVal = parseInt(startingNumbers); | ||
if (endingNumberVal > 24 || startingNumberVal > 24) { | ||
return null; | ||
} | ||
} | ||
return result; | ||
} | ||
private cachedPrimaryPrefix = null; | ||
@@ -345,0 +377,0 @@ private cachedPrimarySuffix = null; |
@@ -18,2 +18,4 @@ import { Configuration } from "./chrono"; | ||
configuration.refiners.unshift(new OverlapRemovalRefiner()); | ||
configuration.refiners.push(new OverlapRemovalRefiner()); | ||
configuration.refiners.push(new ForwardDateRefiner()); | ||
@@ -20,0 +22,0 @@ configuration.refiners.push(new UnlikelyFormatFilter(strictMode)); |
@@ -20,3 +20,3 @@ import { ParsingContext } from "../../../chrono"; | ||
primarySuffix(): string { | ||
return "(?:\\s*(?:o\\W*clock|at\\s*night|in\\s*the\\s*(?:morning|afternoon)))?(?=\\W|$)"; | ||
return "(?:\\s*(?:o\\W*clock|at\\s*night|in\\s*the\\s*(?:morning|afternoon)))?(?!/)(?=\\W|$)"; | ||
} | ||
@@ -23,0 +23,0 @@ |
@@ -263,2 +263,8 @@ import * as chrono from "../../src"; | ||
test("Test - Parsing negative cases : 'at [some numbers] - [some numbers]'", function () { | ||
testUnexpectedResult(chrono, "I'm at 10.1 - 10.12"); | ||
testUnexpectedResult(chrono, "I'm at 10 - 10.1"); | ||
}); | ||
test("Test - Parsing negative cases (Strict)", function () { | ||
@@ -275,1 +281,11 @@ testUnexpectedResult(chrono.strict, "I'm at 101,194 points!"); | ||
}); | ||
test("Test - Parsing negative cases : 'at [some numbers] - [some numbers]' (Strict)", function () { | ||
testUnexpectedResult(chrono.strict, "I'm at 10.1 - 10.12"); | ||
testUnexpectedResult(chrono.strict, "I'm at 10 - 10.1"); | ||
testUnexpectedResult(chrono.strict, "I'm at 10 - 20"); | ||
testUnexpectedResult(chrono.strict, "7-730"); | ||
}); |
@@ -31,2 +31,20 @@ import * as chrono from "../../src"; | ||
test("Test - Quoted Expressions", function () { | ||
testSingleCase(chrono, "Want to meet for dinner (5pm EST)?", new Date(2020, 7 - 1, 6), (result) => { | ||
expect(result.text).toContain("5pm EST"); | ||
}); | ||
testSingleCase(chrono, "between '3:30-4:30pm'", new Date(2020, 7 - 1, 6), (result) => { | ||
expect(result.text).toContain("3:30-4:30pm"); | ||
expect(result.start).toBeDate(new Date(2020, 7 - 1, 6, 15, 30)); | ||
expect(result.end).toBeDate(new Date(2020, 7 - 1, 6, 16, 30)); | ||
}); | ||
testSingleCase(chrono, "The date is '2014-04-18'", (result) => { | ||
expect(result.text).toContain("2014-04-18"); | ||
expect(result.start).toBeDate(new Date(2014, 4 - 1, 18, 12)); | ||
}); | ||
}); | ||
test("Test - Strict Mode", function () { | ||
@@ -83,30 +101,2 @@ testUnexpectedResult(chrono.strict, "Tuesday"); | ||
test("Test - Random non-date patterns", function () { | ||
testUnexpectedResult(chrono, " 3"); | ||
testUnexpectedResult(chrono, " 1"); | ||
testUnexpectedResult(chrono, " 11 "); | ||
testUnexpectedResult(chrono, " 0.5 "); | ||
testUnexpectedResult(chrono, " 35.49 "); | ||
testUnexpectedResult(chrono, "12.53%"); | ||
testUnexpectedResult(chrono, "6358fe2310> *5.0* / 5 Outstanding"); | ||
testUnexpectedResult(chrono, "6358fe2310> *1.5* / 5 Outstanding"); | ||
testUnexpectedResult(chrono, "Total: $1,194.09 [image: View Reservation"); | ||
testUnexpectedResult(chrono, "Version: 1.1.3"); | ||
testUnexpectedResult(chrono, "Version: 1.1.30"); | ||
testUnexpectedResult(chrono, "Version: 1.10.30"); | ||
testUnexpectedResult(chrono, "at 6.5 kilograms"); | ||
}); | ||
test("Test - Wikipedia Texts", function () { | ||
@@ -113,0 +103,0 @@ const text = |
@@ -172,15 +172,1 @@ import * as chrono from "../src/"; | ||
}); | ||
test("Test - Skip version-number-like pattern", () => { | ||
testSingleCase(chrono, "1.5.3 - 2015-09-24", (result) => { | ||
expect(result.text).toBe("2015-09-24"); | ||
}); | ||
testSingleCase(chrono, "1.5.30 - 2015-09-24", (result) => { | ||
expect(result.text).toBe("2015-09-24"); | ||
}); | ||
testSingleCase(chrono, "1.50.30 - 2015-09-24", (result) => { | ||
expect(result.text).toBe("2015-09-24"); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
804461
341
18185