sclass EnglishDateParser > DateStructures { replace P with ParsedWithTokens. bool assumeFuture = true; // e.g. for "tuesday" [not used] LS tok; int maxTokens = 3; // "top dogs" are the longest non-overlapping parses L
> topDogs(S s) { ret pwt_topDogs(pwt_filterByType SomeDate(allParses(s))); } SomeDate parse(S s) { ret getVar(first(topDogs(s))); } ItIt
allParses(S s) { // tokenize, initialize L
> initials = pwt_initial(tok = javaTok(s), maxTokens); new L
out; // find numbers L
> numbers = pwt_transform(number(), initials); // find ordinals (1st, 2nd, ...) new L
> ordinals;
for (P > years = pwt_filter isYear(numbers);
out.addAll(years);
L > months = pwt_filter isMonthNr(numbers);
L > dayOfMonths = pwt_filter isDayOfMonth(numbers);
L > weekdays = pwt_transform(weekday(), initials);
out.addAll(weekdays);
// month names
L > monthNames = pwt_transform(monthName(), initials);
out.addAll(monthNames);
// month name + year, e.g. "February 2020"
out.addAll(pwt_combine(monthNames, years, (month, year) -> new Month(month.month, new Year(year))));
// month name + ordinal, e.g. "March 4th"
out.addAll(pwt_combine(monthNames, ordinals, (month, ord) -> new Day(ord, month)));
// yesterday, today, tomorrow
out.addAll(pwt_transform(t ->
eqic(t, "yesterday") ? new TodayPlus(-1) :
eqic(t, "today") ? new TodayPlus(0) :
new TodayPlus(1),
pwt_transform(fixedToken("yesterday", "today", "tomorrow"), initials)));
// last/this/next week
for (P > hours = pwt_transform numberToHour(numbers);
L > minutes = pwt_filter isMinute(numbers);
L > seconds = minutes;
L > colons = pwt_filter(t -> eq(t, ":"), initials);
// 15:12 etc.
L > hoursAndMinutes = pwt_combine(hours, colons, minutes, (h, _, m) -> new Minute(m, h));
out.addAll(hoursAndMinutes);
L > hoursAndMinutesAndSeconds = pwt_combine(hoursAndMinutes, colons, seconds,
(hm, _, second) -> new Second(second, hm));
out.addAll(hoursAndMinutesAndSeconds);
L > amPMs = pwt_transform(fixedToken("am", "pm"), initials);
// 3 am, 5 pm etc.
L > amPMTimes = pwt_combine(numbers, amPMs, (hour, amPM) -> !between(hour, 1, 12) ? null : new Hour(hour, eqic(amPM, "pm")));
out.addAll(amPMTimes);
// between 1 and 2 pm
for (P ord : parseToTheRight(fixedToken("st", "nd", "rd", "th"), number))
ordinals.add(pwt_combine(number, ord));
//print(+ordinals);
// "in in : parseToTheLeft(fixedToken("in"), number))
for (P days : parseToTheRight(fixedToken("day", "days"), number))
out.add(pwt_combine(new TodayPlus(number!), in, days));
// " daysFromNow : parseToTheRight(fixedToken("day from now", "days from now"), number))
out.add(pwt_combine(new TodayPlus(number!), number, daysFromNow));
L week : pwt_transform(fixedToken("week"), initials))
for (P which : parseToTheLeft(fixedToken("last", "this", "next"), week))
out.add(pwt_combine(new CurrentWeekPlus(
eqic(which!, "last") ? -1
: eqic(which!, "this") ? 0 : 1), which, week));
// "next next : parseToTheLeft(fixedToken("next"), weekday))
out.add(pwt_combine(new Weekday(weekday->weekday, new CurrentWeekPlus(1)), next, weekday));
for (P slash : parseToTheRight(fixedToken("/"), year))
for (P slash2 : parseToTheRight(fixedToken("/"), month))
for (P and : parseToTheLeft(fixedToken("and"), time))
for (P number() { ret s -> isInteger(s) ? parseInt(s) : null; }
bool isYear(int n) { ret between(n, 1900, 2100); }
bool isMonthNr(int n) { ret between(n, 1, 12); }
bool isDayOfMonth(int n) { ret between(n, 1, 31); }
bool isHour(int n) { ret between(n, 0, 23); }
bool isMinute(int n) { ret between(n, 0, 59); }
bool isSecond(int n) { ret between(n, 0, 59); }
Hour numberToHour(int n) { ret !isHour(n) ? null : n > 12 ? new Hour(n-12, true) : new Hour(n, null); }
IF1 fixedToken(S... tokens) { ret fixedToken(litciset(tokens)); }
IF1 fixedToken(Set set) { ret t -> contains(set, t) ? t : null; }
IF1 weekday() {
ret s -> {
int n = parseEnglishWeekday(s);
ret n == 0 ? null : new Weekday(n);
};
}
IF1 monthName() {
ret s -> {
int n = parseEnglishMonthName(s);
ret n == 0 ? null : new Month(n);
};
}
L