Added year to opening hours parser
This commit is contained in:
parent
678f9f7bc0
commit
6282cf520f
2 changed files with 226 additions and 30 deletions
|
@ -594,6 +594,14 @@ public class OpeningHoursParser {
|
||||||
*/
|
*/
|
||||||
public boolean containsMonth(Calendar cal);
|
public boolean containsMonth(Calendar cal);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the year of "cal" is part of this rule
|
||||||
|
*
|
||||||
|
* @param cal the time to check
|
||||||
|
* @return true if the year is part of the rule
|
||||||
|
*/
|
||||||
|
public boolean containsYear(Calendar cal);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if the rule overlap to the next day
|
* @return true if the rule overlap to the next day
|
||||||
*/
|
*/
|
||||||
|
@ -644,6 +652,14 @@ public class OpeningHoursParser {
|
||||||
*/
|
*/
|
||||||
private boolean[] months = new boolean[12];
|
private boolean[] months = new boolean[12];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* represents the list on which year / month it is open.
|
||||||
|
*/
|
||||||
|
private int[] firstYearMonths = null;
|
||||||
|
private int[] lastYearMonths = null;
|
||||||
|
private int fullYears = 0;
|
||||||
|
private int year = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* represents the list on which day it is open.
|
* represents the list on which day it is open.
|
||||||
*/
|
*/
|
||||||
|
@ -908,10 +924,29 @@ public class OpeningHoursParser {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean containsMonth(Calendar cal) {
|
public boolean containsMonth(Calendar cal) {
|
||||||
int i = cal.get(Calendar.MONTH);
|
int month = cal.get(Calendar.MONTH);
|
||||||
if (months[i]) {
|
int year = cal.get(Calendar.YEAR);
|
||||||
|
return containsYear(cal) && months[month];
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsYear(Calendar cal) {
|
||||||
|
if (year == 0 && firstYearMonths == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
int month = cal.get(Calendar.MONTH);
|
||||||
|
int year = cal.get(Calendar.YEAR);
|
||||||
|
if (firstYearMonths != null && firstYearMonths[month] == year ||
|
||||||
|
lastYearMonths != null && lastYearMonths[month] == year ||
|
||||||
|
firstYearMonths == null && lastYearMonths == null && this.year == year) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (fullYears > 0 && this.year > 0) {
|
||||||
|
for (int i = 1; i <= fullYears; i++) {
|
||||||
|
if (this.year + i == year) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -994,6 +1029,7 @@ public class OpeningHoursParser {
|
||||||
boolean dash = false;
|
boolean dash = false;
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
int monthAdded = -1;
|
int monthAdded = -1;
|
||||||
|
int dayAdded = -1;
|
||||||
int excludedMonthEnd = -1;
|
int excludedMonthEnd = -1;
|
||||||
int excludedDayEnd = -1;
|
int excludedDayEnd = -1;
|
||||||
int excludedMonthStart = -1;
|
int excludedMonthStart = -1;
|
||||||
|
@ -1036,6 +1072,7 @@ public class OpeningHoursParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
boolean yearAdded = false;
|
||||||
for (int month = 0; month < dayMonths.length; month++) {
|
for (int month = 0; month < dayMonths.length; month++) {
|
||||||
for (int day = 0; day < dayMonths[month].length; day++) {
|
for (int day = 0; day < dayMonths[month].length; day++) {
|
||||||
if (excludedDayStart != -1 && excludedDayEnd != -1) {
|
if (excludedDayStart != -1 && excludedDayEnd != -1) {
|
||||||
|
@ -1046,7 +1083,7 @@ public class OpeningHoursParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dayMonths[month][day]) {
|
if (dayMonths[month][day]) {
|
||||||
if (day == 0 && dash) {
|
if (day == 0 && dash && dayMonths[month][1]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (day > 0 && dayMonths[month][day - 1]
|
if (day > 0 && dayMonths[month][day - 1]
|
||||||
|
@ -1065,11 +1102,13 @@ public class OpeningHoursParser {
|
||||||
b.append(", ");
|
b.append(", ");
|
||||||
monthAdded = -1;
|
monthAdded = -1;
|
||||||
}
|
}
|
||||||
if (monthAdded != month) {
|
yearAdded = appendYearString(b, dash ? lastYearMonths : firstYearMonths, month);
|
||||||
|
if (monthAdded != month || yearAdded) {
|
||||||
b.append(monthNames[month]).append(" ");
|
b.append(monthNames[month]).append(" ");
|
||||||
monthAdded = month;
|
monthAdded = month;
|
||||||
}
|
}
|
||||||
b.append(day + 1);
|
dayAdded = day + 1;
|
||||||
|
b.append(dayAdded);
|
||||||
dash = false;
|
dash = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1080,9 +1119,18 @@ public class OpeningHoursParser {
|
||||||
} else if (!dash) {
|
} else if (!dash) {
|
||||||
b.append(", ");
|
b.append(", ");
|
||||||
}
|
}
|
||||||
|
appendYearString(b, firstYearMonths, excludedMonthStart);
|
||||||
b.append(monthNames[excludedMonthStart]).append(" ").append(excludedDayStart + 1)
|
b.append(monthNames[excludedMonthStart]).append(" ").append(excludedDayStart + 1)
|
||||||
.append("-")
|
.append("-");
|
||||||
.append(monthNames[excludedMonthEnd]).append(" ").append(excludedDayEnd + 1);
|
appendYearString(b, lastYearMonths, excludedMonthEnd);
|
||||||
|
b.append(monthNames[excludedMonthEnd]).append(" ").append(excludedDayEnd + 1);
|
||||||
|
} else if (yearAdded && !dash && monthAdded != -1 && lastYearMonths != null) {
|
||||||
|
b.append("-");
|
||||||
|
appendYearString(b, lastYearMonths, monthAdded);
|
||||||
|
b.append(monthNames[monthAdded]);
|
||||||
|
if (dayAdded != -1) {
|
||||||
|
b.append(" ").append(dayAdded);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!first) {
|
if (!first) {
|
||||||
b.append(" ");
|
b.append(" ");
|
||||||
|
@ -1139,6 +1187,17 @@ public class OpeningHoursParser {
|
||||||
return b.toString();
|
return b.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean appendYearString(StringBuilder b, int[] yearMonths, int month) {
|
||||||
|
if (yearMonths != null && yearMonths[month] > 0) {
|
||||||
|
b.append(yearMonths[month]).append(" ");
|
||||||
|
return true;
|
||||||
|
} else if (year > 0) {
|
||||||
|
b.append(year).append(" ");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void addArray(boolean[] array, String[] arrayNames, StringBuilder b) {
|
private void addArray(boolean[] array, String[] arrayNames, StringBuilder b) {
|
||||||
boolean dash = false;
|
boolean dash = false;
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
|
@ -1405,7 +1464,7 @@ public class OpeningHoursParser {
|
||||||
|
|
||||||
private int calculate(Calendar cal) {
|
private int calculate(Calendar cal) {
|
||||||
int month = cal.get(Calendar.MONTH);
|
int month = cal.get(Calendar.MONTH);
|
||||||
if (!months[month]) {
|
if (!containsMonth(cal)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int dmonth = cal.get(Calendar.DAY_OF_MONTH) - 1;
|
int dmonth = cal.get(Calendar.DAY_OF_MONTH) - 1;
|
||||||
|
@ -1500,6 +1559,11 @@ public class OpeningHoursParser {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsYear(Calendar cal) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toRuleString() {
|
public String toRuleString() {
|
||||||
return ruleString;
|
return ruleString;
|
||||||
|
@ -1547,12 +1611,14 @@ public class OpeningHoursParser {
|
||||||
TOKEN_COMMA(2),
|
TOKEN_COMMA(2),
|
||||||
TOKEN_DASH(3),
|
TOKEN_DASH(3),
|
||||||
// order is important
|
// order is important
|
||||||
TOKEN_MONTH(4),
|
TOKEN_YEAR(4),
|
||||||
TOKEN_DAY_MONTH(5),
|
TOKEN_MONTH(5),
|
||||||
TOKEN_HOLIDAY(6),
|
TOKEN_DAY_MONTH(6),
|
||||||
TOKEN_DAY_WEEK(6),
|
TOKEN_HOLIDAY(7),
|
||||||
TOKEN_HOUR_MINUTES (7),
|
TOKEN_DAY_WEEK(7),
|
||||||
TOKEN_OFF_ON(8);
|
TOKEN_HOUR_MINUTES (8),
|
||||||
|
TOKEN_OFF_ON(9);
|
||||||
|
|
||||||
public final int ord;
|
public final int ord;
|
||||||
|
|
||||||
private TokenType(int ord) {
|
private TokenType(int ord) {
|
||||||
|
@ -1696,22 +1762,21 @@ public class OpeningHoursParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// recognize other numbers
|
// recognize other numbers
|
||||||
// if there is no on/off and minutes/hours
|
boolean monthSpecified = false;
|
||||||
boolean hoursSpecified = false;
|
for (Token t : tokens) {
|
||||||
for(int i = 0; i < tokens.size(); i ++) {
|
if (t.type == TokenType.TOKEN_MONTH) {
|
||||||
if(tokens.get(i).type == TokenType.TOKEN_HOUR_MINUTES ||
|
monthSpecified = true;
|
||||||
tokens.get(i).type == TokenType.TOKEN_OFF_ON) {
|
|
||||||
hoursSpecified = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(int i = 0; i < tokens.size(); i ++) {
|
for(int i = 0; i < tokens.size(); i ++) {
|
||||||
if(tokens.get(i).type == TokenType.TOKEN_UNKNOWN && tokens.get(i).mainNumber >= 0) {
|
Token t = tokens.get(i);
|
||||||
tokens.get(i).type = hoursSpecified ? TokenType.TOKEN_DAY_MONTH : TokenType.TOKEN_HOUR_MINUTES;
|
if (t.type == TokenType.TOKEN_UNKNOWN && t.mainNumber >= 0) {
|
||||||
if(tokens.get(i).type == TokenType.TOKEN_HOUR_MINUTES) {
|
if (monthSpecified && t.mainNumber <= 31) {
|
||||||
tokens.get(i).mainNumber = tokens.get(i).mainNumber * 60;
|
t.type = TokenType.TOKEN_DAY_MONTH;
|
||||||
} else {
|
t.mainNumber = t.mainNumber - 1;
|
||||||
tokens.get(i).mainNumber = tokens.get(i).mainNumber - 1;
|
} else if (t.mainNumber > 1000) {
|
||||||
|
t.type = TokenType.TOKEN_YEAR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1727,6 +1792,7 @@ public class OpeningHoursParser {
|
||||||
Token[] currentPair = new Token[2];
|
Token[] currentPair = new Token[2];
|
||||||
listOfPairs.add(currentPair);
|
listOfPairs.add(currentPair);
|
||||||
Token prevToken = null;
|
Token prevToken = null;
|
||||||
|
Token prevYearToken = null;
|
||||||
int indexP = 0;
|
int indexP = 0;
|
||||||
for(int i = 0; i <= tokens.size(); i++) {
|
for(int i = 0; i <= tokens.size(); i++) {
|
||||||
Token t = i == tokens.size() ? null : tokens.get(i);
|
Token t = i == tokens.size() ? null : tokens.get(i);
|
||||||
|
@ -1782,6 +1848,40 @@ public class OpeningHoursParser {
|
||||||
} else if (array != null) {
|
} else if (array != null) {
|
||||||
fillRuleArray(array, pair);
|
fillRuleArray(array, pair);
|
||||||
}
|
}
|
||||||
|
int ruleYear = basic.year;
|
||||||
|
if ((ruleYear > 0 || prevYearToken != null) && firstMonthToken != null && lastMonthToken != null) {
|
||||||
|
int length = lastMonthToken.mainNumber > firstMonthToken.mainNumber ?
|
||||||
|
lastMonthToken.mainNumber - firstMonthToken.mainNumber : 12 - firstMonthToken.mainNumber + lastMonthToken.mainNumber;
|
||||||
|
int month = firstMonthToken.mainNumber;
|
||||||
|
int endYear = prevYearToken != null ? prevYearToken.mainNumber : ruleYear;
|
||||||
|
int startYear = ruleYear > 0 ? ruleYear : endYear;
|
||||||
|
int year = startYear;
|
||||||
|
if (basic.firstYearMonths == null) {
|
||||||
|
basic.firstYearMonths = new int[12];
|
||||||
|
}
|
||||||
|
int[] yearMonths = basic.firstYearMonths;
|
||||||
|
int k = 0;
|
||||||
|
while (k <= length) {
|
||||||
|
yearMonths[month++] = year;
|
||||||
|
if (month > 11) {
|
||||||
|
month = 0;
|
||||||
|
year = endYear;
|
||||||
|
if (basic.lastYearMonths == null) {
|
||||||
|
basic.lastYearMonths = new int[12];
|
||||||
|
}
|
||||||
|
yearMonths = basic.lastYearMonths;
|
||||||
|
}
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
if (endYear - startYear > 1) {
|
||||||
|
basic.fullYears = endYear - startYear - 1;
|
||||||
|
}
|
||||||
|
if (endYear > startYear && firstMonthToken.mainNumber >= lastMonthToken.mainNumber) {
|
||||||
|
//basic.dayMonths = null;
|
||||||
|
Arrays.fill(basic.months, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if (pair[0] != null) {
|
} else if (pair[0] != null) {
|
||||||
if (pair[0].type == TokenType.TOKEN_HOLIDAY) {
|
if (pair[0].type == TokenType.TOKEN_HOLIDAY) {
|
||||||
if (pair[0].mainNumber == 0) {
|
if (pair[0].mainNumber == 0) {
|
||||||
|
@ -1798,6 +1898,9 @@ public class OpeningHoursParser {
|
||||||
}
|
}
|
||||||
if (array != null) {
|
if (array != null) {
|
||||||
array[pair[0].mainNumber] = true;
|
array[pair[0].mainNumber] = true;
|
||||||
|
if (prevYearToken != null) {
|
||||||
|
basic.year = prevYearToken.mainNumber;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1813,6 +1916,11 @@ public class OpeningHoursParser {
|
||||||
if (l[0] != null && l[0].mainNumber == 0) {
|
if (l[0] != null && l[0].mainNumber == 0) {
|
||||||
basic.off = true;
|
basic.off = true;
|
||||||
}
|
}
|
||||||
|
} else if (currentParse == TokenType.TOKEN_YEAR) {
|
||||||
|
Token[] l = listOfPairs.get(0);
|
||||||
|
if (l[0] != null && l[0].mainNumber > 1000) {
|
||||||
|
prevYearToken = l[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
listOfPairs.clear();
|
listOfPairs.clear();
|
||||||
currentPair = new Token[2];
|
currentPair = new Token[2];
|
||||||
|
@ -1842,6 +1950,8 @@ public class OpeningHoursParser {
|
||||||
}
|
}
|
||||||
} else if (t.type == TokenType.TOKEN_DASH) {
|
} else if (t.type == TokenType.TOKEN_DASH) {
|
||||||
|
|
||||||
|
} else if (t.type == TokenType.TOKEN_YEAR) {
|
||||||
|
prevYearToken = t;
|
||||||
} else if (t.type.ord() == currentParse.ord()) {
|
} else if (t.type.ord() == currentParse.ord()) {
|
||||||
if (indexP < 2) {
|
if (indexP < 2) {
|
||||||
currentPair[indexP++] = t;
|
currentPair[indexP++] = t;
|
||||||
|
|
|
@ -116,7 +116,93 @@ public class OpeningHoursParserTest {
|
||||||
Locale locale = Locale.getDefault();
|
Locale locale = Locale.getDefault();
|
||||||
try {
|
try {
|
||||||
Locale.setDefault(Locale.forLanguageTag("en-US"));
|
Locale.setDefault(Locale.forLanguageTag("en-US"));
|
||||||
OpeningHours hours = parseOpenedHours("Apr 05-Oct 24: Fr 08:00-16:00");
|
|
||||||
|
OpeningHours hours = parseOpenedHours("2019 Apr 1 - 2020 Apr 1");
|
||||||
|
System.out.println(hours);
|
||||||
|
testOpened("01.04.2018 15:00", hours, false);
|
||||||
|
testOpened("01.04.2019 15:00", hours, true);
|
||||||
|
testOpened("01.04.2020 15:00", hours, true);
|
||||||
|
|
||||||
|
hours = parseOpenedHours("2019 Apr 15 - 2020 Mar 1");
|
||||||
|
System.out.println(hours);
|
||||||
|
testOpened("01.04.2018 15:00", hours, false);
|
||||||
|
testOpened("01.04.2019 15:00", hours, false);
|
||||||
|
testOpened("15.04.2019 15:00", hours, true);
|
||||||
|
testOpened("15.09.2019 15:00", hours, true);
|
||||||
|
testOpened("15.02.2020 15:00", hours, true);
|
||||||
|
testOpened("15.03.2020 15:00", hours, false);
|
||||||
|
testOpened("15.04.2020 15:00", hours, false);
|
||||||
|
|
||||||
|
hours = parseOpenedHours("2019 Jul 23 05:00-24:00; 2019 Jul 24-2019 Jul 26 00:00-24:00; 2019 Jul 27 00:00-18:00");
|
||||||
|
System.out.println(hours);
|
||||||
|
testOpened("23.07.2018 15:00", hours, false);
|
||||||
|
testOpened("23.07.2019 15:00", hours, true);
|
||||||
|
testOpened("23.07.2019 04:00", hours, false);
|
||||||
|
testOpened("23.07.2020 15:00", hours, false);
|
||||||
|
testOpened("25.07.2018 15:00", hours, false);
|
||||||
|
testOpened("24.07.2019 15:00", hours, true);
|
||||||
|
testOpened("25.07.2019 04:00", hours, true);
|
||||||
|
testOpened("26.07.2019 15:00", hours, true);
|
||||||
|
testOpened("25.07.2020 15:00", hours, false);
|
||||||
|
testOpened("27.07.2018 15:00", hours, false);
|
||||||
|
testOpened("27.07.2019 15:00", hours, true);
|
||||||
|
testOpened("27.07.2019 19:00", hours, false);
|
||||||
|
testOpened("27.07.2020 15:00", hours, false);
|
||||||
|
|
||||||
|
hours = parseOpenedHours("2019 Sep 1 - 2022 Apr 1");
|
||||||
|
System.out.println(hours);
|
||||||
|
testOpened("01.02.2018 15:00", hours, false);
|
||||||
|
testOpened("29.05.2019 15:00", hours, false);
|
||||||
|
testOpened("05.09.2019 11:00", hours, true);
|
||||||
|
testOpened("05.02.2020 11:00", hours, true);
|
||||||
|
testOpened("03.06.2020 11:00", hours, false);
|
||||||
|
testOpened("05.02.2021 11:00", hours, true);
|
||||||
|
testOpened("05.02.2022 11:00", hours, true);
|
||||||
|
testOpened("05.02.2023 11:00", hours, false);
|
||||||
|
|
||||||
|
hours = parseOpenedHours("2019 Apr 15 - 2019 Sep 1: Mo-Fr 00:00-24:00");
|
||||||
|
System.out.println(hours);
|
||||||
|
testOpened("06.04.2019 15:00", hours, false);
|
||||||
|
testOpened("29.05.2019 15:00", hours, true);
|
||||||
|
testOpened("25.07.2019 11:00", hours, true);
|
||||||
|
testOpened("12.07.2018 11:00", hours, false);
|
||||||
|
testOpened("18.07.2020 11:00", hours, false);
|
||||||
|
testOpened("28.07.2021 11:00", hours, false);
|
||||||
|
|
||||||
|
hours = parseOpenedHours("2019 Sep 1 - 2020 Apr 1");
|
||||||
|
System.out.println(hours);
|
||||||
|
testOpened("01.04.2019 15:00", hours, false);
|
||||||
|
testOpened("29.05.2019 15:00", hours, false);
|
||||||
|
testOpened("05.09.2019 11:00", hours, true);
|
||||||
|
testOpened("05.02.2020 11:00", hours, true);
|
||||||
|
testOpened("05.06.2020 11:00", hours, false);
|
||||||
|
testOpened("05.02.2021 11:00", hours, false);
|
||||||
|
|
||||||
|
hours = parseOpenedHours("2019 Apr 15 - 2019 Sep 1");
|
||||||
|
System.out.println(hours);
|
||||||
|
testOpened("01.04.2019 15:00", hours, false);
|
||||||
|
testOpened("29.05.2019 15:00", hours, true);
|
||||||
|
testOpened("27.07.2019 15:00", hours, true);
|
||||||
|
testOpened("05.09.2019 11:00", hours, false);
|
||||||
|
testOpened("05.06.2018 11:00", hours, false);
|
||||||
|
testOpened("05.06.2020 11:00", hours, false);
|
||||||
|
|
||||||
|
hours = parseOpenedHours("Apr 15 - Sep 1");
|
||||||
|
System.out.println(hours);
|
||||||
|
testOpened("01.04.2019 15:00", hours, false);
|
||||||
|
testOpened("29.05.2019 15:00", hours, true);
|
||||||
|
testOpened("27.07.2019 15:00", hours, true);
|
||||||
|
testOpened("05.09.2019 11:00", hours, false);
|
||||||
|
|
||||||
|
hours = parseOpenedHours("Apr 15 - Sep 1: Mo-Fr 00:00-24:00");
|
||||||
|
System.out.println(hours);
|
||||||
|
testOpened("01.04.2019 15:00", hours, false);
|
||||||
|
testOpened("29.05.2019 15:00", hours, true);
|
||||||
|
testOpened("24.07.2019 15:00", hours, true);
|
||||||
|
testOpened("27.07.2019 15:00", hours, false);
|
||||||
|
testOpened("05.09.2019 11:00", hours, false);
|
||||||
|
|
||||||
|
hours = parseOpenedHours("Apr 05-Oct 24: Fr 08:00-16:00");
|
||||||
System.out.println(hours);
|
System.out.println(hours);
|
||||||
testOpened("26.08.2018 15:00", hours, false);
|
testOpened("26.08.2018 15:00", hours, false);
|
||||||
testOpened("29.03.2019 15:00", hours, false);
|
testOpened("29.03.2019 15:00", hours, false);
|
||||||
|
|
Loading…
Reference in a new issue