Skip to content

Commit d829f97

Browse files
committed
Add flag for more lenient handling of times in strict mode
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.
1 parent 287411d commit d829f97

File tree

11 files changed

+278778
-11072
lines changed

11 files changed

+278778
-11072
lines changed

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ Deviations from the grammar as of [this version of the opening hours specificati
1414
* unicode EN DASH (U+2013) EM DASH (U+2014) characters are allowed for hyphen
1515
* various unicode whitespace characters are ignored
1616

17+
In strict mode time ranges that have a nummerically earlier ending time than start and
18+
do not use the _extended time_ format will cause a parse exception to be thrown, this
19+
can be overridden when calling the parser.
20+
1721
In non-strict mode the following further differences are allowed:
1822

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

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

5356

5457
## Including in your project
@@ -64,7 +67,7 @@ repositories {
6467

6568
``` groovy
6669
dependencies {
67-
compile "ch.poole:OpeningHoursParser:0.25.0"
70+
compile "ch.poole:OpeningHoursParser:0.26.0"
6871
}
6972
```
7073

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ apply plugin: 'maven-publish'
1414
apply plugin: 'signing'
1515
apply plugin: "jacoco"
1616

17-
version = '0.25.0'
17+
version = '0.26.0'
1818

1919
java {
2020
sourceCompatibility = JavaVersion.VERSION_1_8

src/main/java/ch/poole/openinghoursparser/OpeningHoursParser.jj

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public class OpeningHoursParser
5959
static int TWELVEHOURS = 12*60;
6060

6161
boolean strict = false;
62+
boolean strictTime = false;
6263
enum AMPM { AM, PM };
6364
boolean monthOnly = false;
6465
List < ParseException > exceptions = new ArrayList < ParseException > ();
@@ -71,10 +72,23 @@ public class OpeningHoursParser
7172
* @throws OpeningHoursParseException on parse errors
7273
*/
7374
public List < Rule > rules(boolean strict) throws OpeningHoursParseException
75+
{
76+
return rules(strict, true);
77+
}
78+
79+
/**
80+
* Get the output of the parser
81+
*
82+
* @param strict if true the parser will run in strict mode
83+
* @param strictTime if false and strict is true, earlier than the start time endings will be fixed up silently
84+
* @return a List of Rule elements
85+
* @throws OpeningHoursParseException on parse errors
86+
*/
87+
public List < Rule > rules(boolean strict, boolean strictTime) throws OpeningHoursParseException
7488
{
7589
try
7690
{
77-
List < Rule > r = rules0(strict);
91+
List < Rule > r = rules0(strict, strictTime);
7892
if (exceptions.size() > 1)
7993
{
8094
throw new OpeningHoursParseException(exceptions);
@@ -592,7 +606,7 @@ TimeSpan timespan() :
592606
end = extendedtime()
593607
{
594608
if (end < start) {
595-
if (!strict)
609+
if (!strict || !strictTime)
596610
{
597611
// non-strict, add 24h
598612
end = end + 24*60;
@@ -1437,9 +1451,10 @@ Rule rule() :
14371451
}
14381452
}
14391453

1440-
private List < Rule > rules0(boolean strict) :
1454+
private List < Rule > rules0(boolean strict, boolean strictTime) :
14411455
{
14421456
this.strict = strict;
1457+
this.strictTime = strictTime;
14431458
List < Rule > result = new ArrayList < Rule > ();
14441459
Rule r = null;
14451460
Rule r1 = null;
@@ -1454,7 +1469,7 @@ private List < Rule > rules0(boolean strict) :
14541469
catch (ParseException e)
14551470
{
14561471
error_skip(e);
1457-
return rules0(strict);
1472+
return rules0(strict, strictTime);
14581473
}
14591474
try
14601475
{
@@ -1494,7 +1509,7 @@ private List < Rule > rules0(boolean strict) :
14941509
catch (ParseException e)
14951510
{
14961511
error_skip(e);
1497-
return rules0(strict);
1512+
return rules0(strict, strictTime);
14981513
}
14991514
{
15001515
r.additive = false;

src/test/java/ch/poole/openinghoursparser/DataTest.java

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,26 @@ public class DataTest {
5353
*/
5454
@Test
5555
public void regressionTest() {
56-
parseData("test-data/oh.txt", false, false, "test-data/oh.txt-result");
57-
parseData("test-data/oh.txt", false, true, "test-data/oh.txt-debug-result");
56+
parseData("test-data/oh.txt", false, false, false, "test-data/oh.txt-result");
57+
parseData("test-data/oh.txt", false, false, true, "test-data/oh.txt-debug-result");
5858
}
5959

6060
/**
61-
* Compare strict mode output
61+
* Compare strict mode output (time strict false)
6262
*/
6363
@Test
6464
public void regressionTestStrict() {
65-
parseData("test-data/oh.txt", true, false, "test-data/oh.txt-result-strict");
66-
parseData("test-data/oh.txt", true, true, "test-data/oh.txt-debug-result-strict");
65+
parseData("test-data/oh.txt", true, false, false, "test-data/oh.txt-result-strict");
66+
parseData("test-data/oh.txt", true, false, true, "test-data/oh.txt-debug-result-strict");
67+
}
68+
69+
/**
70+
* Compare strict mode output with time strict set to true
71+
*/
72+
@Test
73+
public void regressionTestTimeStrict() {
74+
parseData("test-data/oh.txt", true, true, false, "test-data/oh.txt-result-time-strict");
75+
parseData("test-data/oh.txt", true, true, true, "test-data/oh.txt-debug-result-time-strict");
6776
}
6877

6978
/**
@@ -72,10 +81,11 @@ public void regressionTestStrict() {
7281
*
7382
* @param inputFile input data file
7483
* @param strict if true use strict mode
84+
* @param strict if true use strict time interpretation in strict mode
7585
* @param debug if true produce debug output
7686
* @param resultsFile file to write results to
7787
*/
78-
private void parseData(String inputFile, boolean strict, boolean debug, String resultsFile) {
88+
private void parseData(String inputFile, boolean strict, boolean timeStrict, boolean debug, String resultsFile) {
7989
int differences = 0;
8090
int successful = 0;
8191
int errors = 0;
@@ -92,10 +102,11 @@ private void parseData(String inputFile, boolean strict, boolean debug, String r
92102
} catch (FileNotFoundException fnfex) {
93103
System.out.println("File not found " + fnfex.toString());
94104
}
105+
String mode = (strict && !timeStrict ? "-strict" : "") + (strict && timeStrict ? "-time-strict" : "") + (debug ? "-debug" : "");
95106
outputExpected = new BufferedWriter(new OutputStreamWriter(
96-
new FileOutputStream(inputFile + "-result" + (strict ? "-strict" : "") + (debug ? "-debug" : "") + "-temp"), StandardCharsets.UTF_8));
107+
new FileOutputStream(inputFile + "-result" + mode + "-temp"), StandardCharsets.UTF_8));
97108
outputFail = new BufferedWriter(new OutputStreamWriter(
98-
new FileOutputStream(inputFile + "-fail" + (strict ? "-strict" + (debug ? "-debug" : "") : "")), StandardCharsets.UTF_8));
109+
new FileOutputStream(inputFile + "-fail" + mode), StandardCharsets.UTF_8));
99110

100111
String expectedResultCode = null;
101112
String expectedResult = null;
@@ -115,7 +126,7 @@ private void parseData(String inputFile, boolean strict, boolean debug, String r
115126
}
116127
try {
117128
OpeningHoursParser parser = new OpeningHoursParser(new ByteArrayInputStream(line.getBytes()));
118-
List<ch.poole.openinghoursparser.Rule> rules = parser.rules(strict);
129+
List<ch.poole.openinghoursparser.Rule> rules = parser.rules(strict, timeStrict);
119130
String result = debug ? Util.rulesToOpeningHoursDebugString(rules) : Util.rulesToOpeningHoursString(rules);
120131
successful++;
121132
outputExpected.write("0\t" + result + "\n");

src/test/java/ch/poole/openinghoursparser/UnitTest.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,4 +782,71 @@ public void invalidDateRange() {
782782
assertEquals("Encountered: <HYPHEN> \"- \" at line 1, column 11" + System.lineSeparator() + "Was expecting: <EOF>", pex.getMessage());
783783
}
784784
}
785+
786+
@Test
787+
public void timeStrict() {
788+
OpeningHoursParser parser = new OpeningHoursParser(new ByteArrayInputStream("07:00-06:00".getBytes()));
789+
try {
790+
List<Rule> rules = parser.rules(true);
791+
fail("this should have thrown an exception");
792+
} catch (ParseException pex) {
793+
assertEquals("End time earlier than start time at line 1, column 11", pex.getMessage());
794+
}
795+
parser = new OpeningHoursParser(new ByteArrayInputStream("07:00-06:00".getBytes()));
796+
try {
797+
List<Rule> rules = parser.rules(true, false);
798+
assertEquals(1, rules.size());
799+
Rule r = rules.get(0);
800+
List<TimeSpan> spans = r.getTimes();
801+
assertEquals(1, spans.size());
802+
assertEquals(7 * 60, spans.get(0).getStart());
803+
assertEquals(30 * 60, spans.get(0).getEnd());
804+
assertEquals("07:00-06:00", Util.rulesToOpeningHoursString(rules));
805+
} catch (ParseException pex) {
806+
fail(pex.getMessage());
807+
}
808+
}
809+
810+
@Test
811+
public void midnight() {
812+
OpeningHoursParser parser = new OpeningHoursParser(new ByteArrayInputStream("07:00-24:00".getBytes()));
813+
try {
814+
List<Rule> rules = parser.rules(true, true);
815+
assertEquals(1, rules.size());
816+
Rule r = rules.get(0);
817+
List<TimeSpan> spans = r.getTimes();
818+
assertEquals(1, spans.size());
819+
assertEquals(7 * 60, spans.get(0).getStart());
820+
assertEquals(24 * 60, spans.get(0).getEnd());
821+
assertEquals("07:00-24:00", Util.rulesToOpeningHoursString(rules));
822+
} catch (ParseException pex) {
823+
fail(pex.getMessage());
824+
}
825+
parser = new OpeningHoursParser(new ByteArrayInputStream("07:00-24:00".getBytes()));
826+
try {
827+
List<Rule> rules = parser.rules(true, false);
828+
assertEquals(1, rules.size());
829+
Rule r = rules.get(0);
830+
List<TimeSpan> spans = r.getTimes();
831+
assertEquals(1, spans.size());
832+
assertEquals(7 * 60, spans.get(0).getStart());
833+
assertEquals(24 * 60, spans.get(0).getEnd());
834+
assertEquals("07:00-24:00", Util.rulesToOpeningHoursString(rules));
835+
} catch (ParseException pex) {
836+
fail(pex.getMessage());
837+
}
838+
parser = new OpeningHoursParser(new ByteArrayInputStream("07:00-00:00".getBytes()));
839+
try {
840+
List<Rule> rules = parser.rules(true, false);
841+
assertEquals(1, rules.size());
842+
Rule r = rules.get(0);
843+
List<TimeSpan> spans = r.getTimes();
844+
assertEquals(1, spans.size());
845+
assertEquals(7 * 60, spans.get(0).getStart());
846+
assertEquals(24 * 60, spans.get(0).getEnd());
847+
assertEquals("07:00-24:00", Util.rulesToOpeningHoursString(rules));
848+
} catch (ParseException pex) {
849+
fail(pex.getMessage());
850+
}
851+
}
785852
}

test-data/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@
88
/oh.txt-fail-strict-debug
99
/diff.txt
1010
/diff-strict.txt
11+
/oh.txt-result-time-strict-debug-temp
12+
/oh.txt-result-time-strict-temp

0 commit comments

Comments
 (0)