Skip to content

Commit

Permalink
Add flag for more lenient handling of times in strict mode
Browse files Browse the repository at this point in the history
This adds a flag that controls, when in strict mode, if the parser will
throw a parse exception for time ranges that end earlier than they
start.
  • Loading branch information
simonpoole committed Nov 2, 2021
1 parent 287411d commit d829f97
Show file tree
Hide file tree
Showing 11 changed files with 278,778 additions and 11,072 deletions.
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ Deviations from the grammar as of [this version of the opening hours specificati
* unicode EN DASH (U+2013) EM DASH (U+2014) characters are allowed for hyphen
* various unicode whitespace characters are ignored

In strict mode time ranges that have a nummerically earlier ending time than start and
do not use the _extended time_ format will cause a parse exception to be thrown, this
can be overridden when calling the parser.

In non-strict mode the following further differences are allowed:

* three-character weekday abbreviations
* German two-letter weekday abbreviations
* times extending in to the next day that are missing the extra 24 hours are corrected
* single 0 for minutes
* minutes in times optional
* ignore spaces and more than one leading zeros in minutes
Expand All @@ -39,7 +42,7 @@ Converting the data structures generated by parsing back to strings will result
try {
OpeningHoursParser parser = new OpeningHoursParser(
new ByteArrayInputStream(line.getBytes()));
List<Rule> rules = parser.rules(strict);
List<Rule> rules = parser.rules(strict, strictTime);
// ...
} catch(OpeningHoursParseException e) {
// ...
Expand All @@ -48,7 +51,7 @@ try {
}
```

Detailed documentation can be found in the [JavaDoc](http://www.javadoc.io/doc/ch.poole/OpeningHoursParser/0.25.0).
Detailed documentation can be found in the [JavaDoc](http://www.javadoc.io/doc/ch.poole/OpeningHoursParser/0.26.0).


## Including in your project
Expand All @@ -64,7 +67,7 @@ repositories {

``` groovy
dependencies {
compile "ch.poole:OpeningHoursParser:0.25.0"
compile "ch.poole:OpeningHoursParser:0.26.0"
}
```

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ apply plugin: 'maven-publish'
apply plugin: 'signing'
apply plugin: "jacoco"

version = '0.25.0'
version = '0.26.0'

java {
sourceCompatibility = JavaVersion.VERSION_1_8
Expand Down
25 changes: 20 additions & 5 deletions src/main/java/ch/poole/openinghoursparser/OpeningHoursParser.jj
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public class OpeningHoursParser
static int TWELVEHOURS = 12*60;

boolean strict = false;
boolean strictTime = false;
enum AMPM { AM, PM };
boolean monthOnly = false;
List < ParseException > exceptions = new ArrayList < ParseException > ();
Expand All @@ -71,10 +72,23 @@ public class OpeningHoursParser
* @throws OpeningHoursParseException on parse errors
*/
public List < Rule > rules(boolean strict) throws OpeningHoursParseException
{
return rules(strict, true);
}

/**
* Get the output of the parser
*
* @param strict if true the parser will run in strict mode
* @param strictTime if false and strict is true, earlier than the start time endings will be fixed up silently
* @return a List of Rule elements
* @throws OpeningHoursParseException on parse errors
*/
public List < Rule > rules(boolean strict, boolean strictTime) throws OpeningHoursParseException
{
try
{
List < Rule > r = rules0(strict);
List < Rule > r = rules0(strict, strictTime);
if (exceptions.size() > 1)
{
throw new OpeningHoursParseException(exceptions);
Expand Down Expand Up @@ -592,7 +606,7 @@ TimeSpan timespan() :
end = extendedtime()
{
if (end < start) {
if (!strict)
if (!strict || !strictTime)
{
// non-strict, add 24h
end = end + 24*60;
Expand Down Expand Up @@ -1437,9 +1451,10 @@ Rule rule() :
}
}

private List < Rule > rules0(boolean strict) :
private List < Rule > rules0(boolean strict, boolean strictTime) :
{
this.strict = strict;
this.strictTime = strictTime;
List < Rule > result = new ArrayList < Rule > ();
Rule r = null;
Rule r1 = null;
Expand All @@ -1454,7 +1469,7 @@ private List < Rule > rules0(boolean strict) :
catch (ParseException e)
{
error_skip(e);
return rules0(strict);
return rules0(strict, strictTime);
}
try
{
Expand Down Expand Up @@ -1494,7 +1509,7 @@ private List < Rule > rules0(boolean strict) :
catch (ParseException e)
{
error_skip(e);
return rules0(strict);
return rules0(strict, strictTime);
}
{
r.additive = false;
Expand Down
29 changes: 20 additions & 9 deletions src/test/java/ch/poole/openinghoursparser/DataTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,26 @@ public class DataTest {
*/
@Test
public void regressionTest() {
parseData("test-data/oh.txt", false, false, "test-data/oh.txt-result");
parseData("test-data/oh.txt", false, true, "test-data/oh.txt-debug-result");
parseData("test-data/oh.txt", false, false, false, "test-data/oh.txt-result");
parseData("test-data/oh.txt", false, false, true, "test-data/oh.txt-debug-result");
}

/**
* Compare strict mode output
* Compare strict mode output (time strict false)
*/
@Test
public void regressionTestStrict() {
parseData("test-data/oh.txt", true, false, "test-data/oh.txt-result-strict");
parseData("test-data/oh.txt", true, true, "test-data/oh.txt-debug-result-strict");
parseData("test-data/oh.txt", true, false, false, "test-data/oh.txt-result-strict");
parseData("test-data/oh.txt", true, false, true, "test-data/oh.txt-debug-result-strict");
}

/**
* Compare strict mode output with time strict set to true
*/
@Test
public void regressionTestTimeStrict() {
parseData("test-data/oh.txt", true, true, false, "test-data/oh.txt-result-time-strict");
parseData("test-data/oh.txt", true, true, true, "test-data/oh.txt-debug-result-time-strict");
}

/**
Expand All @@ -72,10 +81,11 @@ public void regressionTestStrict() {
*
* @param inputFile input data file
* @param strict if true use strict mode
* @param strict if true use strict time interpretation in strict mode
* @param debug if true produce debug output
* @param resultsFile file to write results to
*/
private void parseData(String inputFile, boolean strict, boolean debug, String resultsFile) {
private void parseData(String inputFile, boolean strict, boolean timeStrict, boolean debug, String resultsFile) {
int differences = 0;
int successful = 0;
int errors = 0;
Expand All @@ -92,10 +102,11 @@ private void parseData(String inputFile, boolean strict, boolean debug, String r
} catch (FileNotFoundException fnfex) {
System.out.println("File not found " + fnfex.toString());
}
String mode = (strict && !timeStrict ? "-strict" : "") + (strict && timeStrict ? "-time-strict" : "") + (debug ? "-debug" : "");
outputExpected = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(inputFile + "-result" + (strict ? "-strict" : "") + (debug ? "-debug" : "") + "-temp"), StandardCharsets.UTF_8));
new FileOutputStream(inputFile + "-result" + mode + "-temp"), StandardCharsets.UTF_8));
outputFail = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(inputFile + "-fail" + (strict ? "-strict" + (debug ? "-debug" : "") : "")), StandardCharsets.UTF_8));
new FileOutputStream(inputFile + "-fail" + mode), StandardCharsets.UTF_8));

String expectedResultCode = null;
String expectedResult = null;
Expand All @@ -115,7 +126,7 @@ private void parseData(String inputFile, boolean strict, boolean debug, String r
}
try {
OpeningHoursParser parser = new OpeningHoursParser(new ByteArrayInputStream(line.getBytes()));
List<ch.poole.openinghoursparser.Rule> rules = parser.rules(strict);
List<ch.poole.openinghoursparser.Rule> rules = parser.rules(strict, timeStrict);
String result = debug ? Util.rulesToOpeningHoursDebugString(rules) : Util.rulesToOpeningHoursString(rules);
successful++;
outputExpected.write("0\t" + result + "\n");
Expand Down
67 changes: 67 additions & 0 deletions src/test/java/ch/poole/openinghoursparser/UnitTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -782,4 +782,71 @@ public void invalidDateRange() {
assertEquals("Encountered: <HYPHEN> \"- \" at line 1, column 11" + System.lineSeparator() + "Was expecting: <EOF>", pex.getMessage());
}
}

@Test
public void timeStrict() {
OpeningHoursParser parser = new OpeningHoursParser(new ByteArrayInputStream("07:00-06:00".getBytes()));
try {
List<Rule> rules = parser.rules(true);
fail("this should have thrown an exception");
} catch (ParseException pex) {
assertEquals("End time earlier than start time at line 1, column 11", pex.getMessage());
}
parser = new OpeningHoursParser(new ByteArrayInputStream("07:00-06:00".getBytes()));
try {
List<Rule> rules = parser.rules(true, false);
assertEquals(1, rules.size());
Rule r = rules.get(0);
List<TimeSpan> spans = r.getTimes();
assertEquals(1, spans.size());
assertEquals(7 * 60, spans.get(0).getStart());
assertEquals(30 * 60, spans.get(0).getEnd());
assertEquals("07:00-06:00", Util.rulesToOpeningHoursString(rules));
} catch (ParseException pex) {
fail(pex.getMessage());
}
}

@Test
public void midnight() {
OpeningHoursParser parser = new OpeningHoursParser(new ByteArrayInputStream("07:00-24:00".getBytes()));
try {
List<Rule> rules = parser.rules(true, true);
assertEquals(1, rules.size());
Rule r = rules.get(0);
List<TimeSpan> spans = r.getTimes();
assertEquals(1, spans.size());
assertEquals(7 * 60, spans.get(0).getStart());
assertEquals(24 * 60, spans.get(0).getEnd());
assertEquals("07:00-24:00", Util.rulesToOpeningHoursString(rules));
} catch (ParseException pex) {
fail(pex.getMessage());
}
parser = new OpeningHoursParser(new ByteArrayInputStream("07:00-24:00".getBytes()));
try {
List<Rule> rules = parser.rules(true, false);
assertEquals(1, rules.size());
Rule r = rules.get(0);
List<TimeSpan> spans = r.getTimes();
assertEquals(1, spans.size());
assertEquals(7 * 60, spans.get(0).getStart());
assertEquals(24 * 60, spans.get(0).getEnd());
assertEquals("07:00-24:00", Util.rulesToOpeningHoursString(rules));
} catch (ParseException pex) {
fail(pex.getMessage());
}
parser = new OpeningHoursParser(new ByteArrayInputStream("07:00-00:00".getBytes()));
try {
List<Rule> rules = parser.rules(true, false);
assertEquals(1, rules.size());
Rule r = rules.get(0);
List<TimeSpan> spans = r.getTimes();
assertEquals(1, spans.size());
assertEquals(7 * 60, spans.get(0).getStart());
assertEquals(24 * 60, spans.get(0).getEnd());
assertEquals("07:00-24:00", Util.rulesToOpeningHoursString(rules));
} catch (ParseException pex) {
fail(pex.getMessage());
}
}
}
2 changes: 2 additions & 0 deletions test-data/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@
/oh.txt-fail-strict-debug
/diff.txt
/diff-strict.txt
/oh.txt-result-time-strict-debug-temp
/oh.txt-result-time-strict-temp
Loading

0 comments on commit d829f97

Please sign in to comment.