chrono-node
Version:
A natural language date parser in Javascript
258 lines • 8.82 kB
JavaScript
import { AbstractParserWithWordBoundaryChecking } from "../../../common/parsers/AbstractParserWithWordBoundary.js";
import { Meridiem } from "../../../types.js";
import { NUMBER, jaStringToNumber, toHankaku } from "../constants.js";
const FIRST_REG_PATTERN = new RegExp("(?:" +
"(午前|午後|A.M.|P.M.|AM|PM)" +
")?" +
"(?:[\\s,,、]*)" +
"(?:([0-90-9]+|[" +
Object.keys(NUMBER).join("") +
"]+)(?:\\s*)(?:時|:|:)" +
"(?:\\s*)" +
"([0-90-9]+|半|[" +
Object.keys(NUMBER).join("") +
"]+)?(?:\\s*)(?:分|:|:)?" +
"(?:\\s*)" +
"([0-90-9]+|[" +
Object.keys(NUMBER).join("") +
"]+)?(?:\\s*)(?:秒)?)" +
"(?:\\s*(A.M.|P.M.|AM?|PM?))?", "i");
const SECOND_REG_PATTERN = new RegExp("(?:^\\s*(?:から|\\-|\\–|\\-|\\~|\\〜)\\s*)" +
"(?:" +
"(午前|午後|A.M.|P.M.|AM|PM)" +
")?" +
"(?:[\\s,,、]*)" +
"(?:([0-90-9]+|[" +
Object.keys(NUMBER).join("") +
"]+)(?:\\s*)(?:時|:|:)" +
"(?:\\s*)" +
"([0-90-9]+|半|[" +
Object.keys(NUMBER).join("") +
"]+)?(?:\\s*)(?:分|:|:)?" +
"(?:\\s*)" +
"([0-90-9]+|[" +
Object.keys(NUMBER).join("") +
"]+)?(?:\\s*)(?:秒)?)" +
"(?:\\s*(A.M.|P.M.|AM?|PM?))?", "i");
const AM_PM_HOUR_GROUP_1 = 1;
const HOUR_GROUP = 2;
const MINUTE_GROUP = 3;
const SECOND_GROUP = 4;
const AM_PM_HOUR_GROUP_2 = 5;
export default class JPTimeExpressionParser extends AbstractParserWithWordBoundaryChecking {
innerPattern() {
return FIRST_REG_PATTERN;
}
innerExtract(context, match) {
if (match.index > 0 && context.text[match.index - 1].match(/\w/)) {
return null;
}
const result = context.createParsingResult(match.index, match[0]);
let hour = 0;
let minute = 0;
let meridiem = -1;
if (match[SECOND_GROUP]) {
let second = parseInt(toHankaku(match[SECOND_GROUP]));
if (isNaN(second)) {
second = jaStringToNumber(match[SECOND_GROUP]);
}
if (second >= 60)
return null;
result.start.assign("second", second);
}
hour = parseInt(toHankaku(match[HOUR_GROUP]));
if (isNaN(hour)) {
hour = jaStringToNumber(match[HOUR_GROUP]);
}
if (match[MINUTE_GROUP]) {
if (match[MINUTE_GROUP] === "半") {
minute = 30;
}
else {
minute = parseInt(toHankaku(match[MINUTE_GROUP]));
if (isNaN(minute)) {
minute = jaStringToNumber(match[MINUTE_GROUP]);
}
}
}
else if (hour > 100) {
minute = hour % 100;
hour = Math.floor(hour / 100);
}
if (minute >= 60) {
return null;
}
if (hour > 24) {
return null;
}
if (hour >= 12) {
meridiem = Meridiem.PM;
}
if (match[AM_PM_HOUR_GROUP_1]) {
if (hour > 12)
return null;
const AMPMString = match[AM_PM_HOUR_GROUP_1];
const FirstAMPMString = AMPMString[0].toLowerCase();
if (AMPMString === "午前" || FirstAMPMString === "a") {
meridiem = Meridiem.AM;
if (hour === 12)
hour = 0;
}
else if (AMPMString === "午後" || FirstAMPMString === "p") {
meridiem = Meridiem.PM;
if (hour != 12)
hour += 12;
}
}
else if (match[AM_PM_HOUR_GROUP_2]) {
if (hour > 12)
return null;
const ampm = match[AM_PM_HOUR_GROUP_2][0].toLowerCase();
if (ampm === "a") {
meridiem = Meridiem.AM;
if (hour === 12)
hour = 0;
}
if (ampm === "p") {
meridiem = Meridiem.PM;
if (hour != 12)
hour += 12;
}
}
result.start.assign("hour", hour);
result.start.assign("minute", minute);
if (meridiem >= 0) {
result.start.assign("meridiem", meridiem);
}
else {
if (hour < 12) {
result.start.imply("meridiem", 0);
}
else {
result.start.imply("meridiem", 1);
}
}
match = SECOND_REG_PATTERN.exec(context.text.substring(result.index + result.text.length));
if (!match) {
if (result.text.match(/^\d+$/)) {
return null;
}
return result;
}
result.end = context.createParsingComponents();
hour = 0;
minute = 0;
meridiem = -1;
if (match[SECOND_GROUP]) {
let second = parseInt(toHankaku(match[SECOND_GROUP]));
if (isNaN(second)) {
second = jaStringToNumber(match[SECOND_GROUP]);
}
if (second >= 60)
return null;
result.end.assign("second", second);
}
hour = parseInt(toHankaku(match[HOUR_GROUP]));
if (isNaN(hour)) {
hour = jaStringToNumber(match[HOUR_GROUP]);
}
if (match[MINUTE_GROUP]) {
if (match[MINUTE_GROUP] === "半") {
minute = 30;
}
else {
minute = parseInt(toHankaku(match[MINUTE_GROUP]));
if (isNaN(minute)) {
minute = jaStringToNumber(match[MINUTE_GROUP]);
}
}
}
else if (hour > 100) {
minute = hour % 100;
hour = Math.floor(hour / 100);
}
if (minute >= 60) {
return null;
}
if (hour > 24) {
return null;
}
if (hour >= 12) {
meridiem = Meridiem.PM;
}
if (match[AM_PM_HOUR_GROUP_1]) {
if (hour > 12)
return null;
const AMPMString = match[AM_PM_HOUR_GROUP_1];
const FirstAMPMString = AMPMString[0].toLowerCase();
if (AMPMString === "午前" || FirstAMPMString === "a") {
meridiem = Meridiem.AM;
if (hour === 12)
hour = 0;
}
else if (AMPMString === "午後" || FirstAMPMString === "p") {
meridiem = Meridiem.PM;
if (hour != 12)
hour += 12;
}
if (!result.start.isCertain("meridiem")) {
if (meridiem === Meridiem.AM) {
result.start.imply("meridiem", Meridiem.AM);
if (result.start.get("hour") === 12) {
result.start.assign("hour", 0);
}
}
else {
result.start.imply("meridiem", 1);
if (result.start.get("hour") != 12) {
result.start.assign("hour", result.start.get("hour") + 12);
}
}
}
}
else if (match[AM_PM_HOUR_GROUP_2]) {
if (hour > 12)
return null;
const ampm = match[AM_PM_HOUR_GROUP_2][0].toLowerCase();
if (ampm === "a") {
meridiem = Meridiem.AM;
if (hour === 12)
hour = 0;
}
if (ampm === "p") {
meridiem = Meridiem.PM;
if (hour != 12)
hour += 12;
}
}
result.text = result.text + match[0];
result.end.assign("hour", hour);
result.end.assign("minute", minute);
if (meridiem >= 0) {
result.end.assign("meridiem", meridiem);
}
else {
const startAtPM = result.start.isCertain("meridiem") && result.start.get("hour") > 12;
if (startAtPM) {
if (result.start.get("hour") - 12 > hour) {
result.end.imply("meridiem", Meridiem.AM);
}
else if (hour <= 12) {
result.end.assign("hour", hour + 12);
result.end.assign("meridiem", Meridiem.PM);
}
}
else if (hour > 12) {
result.end.imply("meridiem", Meridiem.PM);
}
else if (hour <= 12) {
result.end.imply("meridiem", Meridiem.AM);
}
}
if (result.end.date().getTime() < result.start.date().getTime()) {
result.end.imply("day", result.end.get("day") + 1);
}
return result;
}
}
//# sourceMappingURL=JPTimeExpressionParser.js.map