From 1d6a1507cd471546c0e744a7d36f2093217b5ccd Mon Sep 17 00:00:00 2001 From: Ray Lee Date: Fri, 2 Jun 2017 16:31:50 -0700 Subject: [PATCH] CSPACE-7100: Change structured date parser to prefer month-day-year instead of year-month-day. --- .../antlr/ANTLRStructuredDateEvaluator.java | 322 +++++++++--------- .../src/test/resources/test-dates.yaml | 283 ++++++++------- 2 files changed, 302 insertions(+), 303 deletions(-) diff --git a/services/structureddate/src/main/java/org/collectionspace/services/structureddate/antlr/ANTLRStructuredDateEvaluator.java b/services/structureddate/src/main/java/org/collectionspace/services/structureddate/antlr/ANTLRStructuredDateEvaluator.java index 0374c9960..faba63273 100644 --- a/services/structureddate/src/main/java/org/collectionspace/services/structureddate/antlr/ANTLRStructuredDateEvaluator.java +++ b/services/structureddate/src/main/java/org/collectionspace/services/structureddate/antlr/ANTLRStructuredDateEvaluator.java @@ -86,18 +86,18 @@ import org.collectionspace.services.structureddate.antlr.StructuredDateParser.Ye * and an ANTLR listener to generate a structured date from the resulting parse * tree. */ -public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener implements StructuredDateEvaluator { +public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener implements StructuredDateEvaluator { /** * The result of the evaluation. */ protected StructuredDate result; - + /** * The operation stack. The parse listener methods that are implemented here * pop input parameters off the stack, and push results back on to the stack. */ protected Stack stack; - + public ANTLRStructuredDateEvaluator() { } @@ -115,13 +115,13 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp StructuredDateLexer lexer = new StructuredDateLexer(inputStream); CommonTokenStream tokenStream = new CommonTokenStream(lexer); StructuredDateParser parser = new StructuredDateParser(tokenStream); - + // Don't try to recover from parse errors, just bail. parser.setErrorHandler(new BailErrorStrategy()); - + // Don't print error messages to the console. parser.removeErrorListeners(); - + // Generate our own custom error messages. parser.addParseListener(this); @@ -133,24 +133,24 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // ParseCancellationException is thrown by the BailErrorStrategy when there is a // parse error, with the underlying RecognitionException as the cause. RecognitionException re = (RecognitionException) e.getCause(); - + throw new StructuredDateFormatException(getErrorMessage(re), re); } - + // The parsing was successful. Return the result. return result; } - + @Override public void exitDisplayDate(DisplayDateContext ctx) { if (ctx.exception != null) return; Date latestDate = (Date) stack.pop(); Date earliestDate = (Date) stack.pop(); - + // If the earliest date and the latest date are the same, it's just a "single" date. // There's no need to have the latest, so set it to null. - + if (earliestDate.equals(latestDate)) { latestDate = null; } @@ -167,27 +167,27 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp Date earliestDate = (Date) stack.pop(); // Set null eras to the default. - + if (earliestDate.getEra() == null) { earliestDate.setEra(Date.DEFAULT_ERA); } - + if (latestDate.getEra() == null) { latestDate.setEra(Date.DEFAULT_ERA); } - + // Finalize any deferred calculations. - + if (latestDate instanceof DeferredDate) { ((DeferredDate) latestDate).resolveDate(); } - + if (earliestDate instanceof DeferredDate) { ((DeferredDate) earliestDate).resolveDate(); } - + // Calculate the earliest date or end date. - + if (ctx.BEFORE() != null) { latestDate = earliestDate; earliestDate = DateUtils.getEarliestBeforeDate(earliestDate, latestDate); @@ -212,21 +212,21 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp int latestInterval = DateUtils.getCircaIntervalYears(latestDate.getYear(), latestDate.getEra()); // Express the circa interval as a qualifier. - + // stack.push(earliestDate.withQualifier(QualifierType.MINUS, earliestInterval, QualifierUnit.YEARS)); // stack.push(latestDate.withQualifier(QualifierType.PLUS, latestInterval, QualifierUnit.YEARS)); - + // OR: - + // Express the circa interval as an offset calculated into the year. - + DateUtils.subtractYears(earliestDate, earliestInterval); DateUtils.addYears(latestDate, latestInterval); - + stack.push(earliestDate); stack.push(latestDate); } - + @Override public void exitCertainDate(CertainDateContext ctx) { if (ctx.exception != null) return; @@ -235,25 +235,25 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp Date earliestDate = (Date) stack.pop(); // Set null eras to the default. - + if (earliestDate.getEra() == null) { earliestDate.setEra(Date.DEFAULT_ERA); } - + if (latestDate.getEra() == null) { latestDate.setEra(Date.DEFAULT_ERA); } - + // Finalize any deferred calculations. - + if (latestDate instanceof DeferredDate) { ((DeferredDate) latestDate).resolveDate(); } - + if (earliestDate instanceof DeferredDate) { ((DeferredDate) earliestDate).resolveDate(); } - + stack.push(earliestDate); stack.push(latestDate); } @@ -261,7 +261,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp @Override public void exitHyphenatedRange(HyphenatedRangeContext ctx) { if (ctx.exception != null) return; - + Date latestEndDate = (Date) stack.pop(); stack.pop(); // latestStartDate stack.pop(); // earliestEndDate @@ -273,9 +273,9 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp if (earliestStartDate.getEra() == null && latestEndDate.getEra() != null) { earliestStartDate.setEra(latestEndDate.getEra()); } - + // Finalize any deferred calculations. - + if (earliestStartDate instanceof DeferredDate) { ((DeferredDate) earliestStartDate).resolveDate(); } @@ -291,20 +291,20 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp @Override public void exitNthCenturyRange(NthCenturyRangeContext ctx) { if (ctx.exception != null) return; - + Era era = (Era) stack.pop(); Integer endN = (Integer) stack.pop(); - Part endPart = (Part) stack.pop(); + Part endPart = (Part) stack.pop(); Integer startN = (Integer) stack.pop(); Part startPart = (Part) stack.pop(); - + if (era == null) { era = Date.DEFAULT_ERA; } - + int startYear = DateUtils.nthCenturyToYear(startN); int endYear = DateUtils.nthCenturyToYear(endN); - + stack.push(startPart == null ? DateUtils.getCenturyStartDate(startYear, era) : DateUtils.getPartialCenturyStartDate(startYear, startPart, era)); stack.push(startPart == null ? DateUtils.getCenturyEndDate(startYear, era) : DateUtils.getPartialCenturyEndDate(startYear, startPart, era)); stack.push(endPart == null ? DateUtils.getCenturyStartDate(endYear, era) : DateUtils.getPartialCenturyStartDate(endYear, endPart, era)); @@ -319,13 +319,13 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp Integer year = (Integer) stack.pop(); Integer numMonthEnd = (Integer) stack.pop(); Integer numMonthStart = (Integer) stack.pop(); - + stack.push(new Date(year, numMonthStart, 1, era)); stack.push(new Date(year, numMonthStart, DateUtils.getDaysInMonth(numMonthStart, year, era), era)); stack.push(new Date(year, numMonthEnd, 1, era)); stack.push(new Date(year, numMonthEnd, DateUtils.getDaysInMonth(numMonthEnd, year, era), era)); } - + @Override public void exitQuarterInYearRange(QuarterInYearRangeContext ctx) { if (ctx.exception != null) return; @@ -334,7 +334,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp Integer year = (Integer) stack.pop(); Integer lastQuarter = (Integer) stack.pop(); Integer firstQuarter = (Integer) stack.pop(); - + stack.push(DateUtils.getQuarterYearStartDate(firstQuarter, year).withEra(era)); stack.push(DateUtils.getQuarterYearEndDate(firstQuarter, year, era).withEra(era)); stack.push(DateUtils.getQuarterYearStartDate(lastQuarter, year).withEra(era)); @@ -350,13 +350,13 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp Integer dayOfMonthEnd = (Integer) stack.pop(); Integer dayOfMonthStart = (Integer) stack.pop(); Integer numMonth = (Integer) stack.pop(); - + stack.push(new Date(year, numMonth, dayOfMonthStart, era)); stack.push(new Date(year, numMonth, dayOfMonthStart, era)); stack.push(new Date(year, numMonth, dayOfMonthEnd, era)); stack.push(new Date(year, numMonth, dayOfMonthEnd, era)); } - + @Override public void exitNumDayInMonthRange(NumDayInMonthRangeContext ctx) { if (ctx.exception != null) return; @@ -366,66 +366,66 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp Integer dayOfMonthEnd = (Integer) stack.pop(); Integer dayOfMonthStart = (Integer) stack.pop(); Integer numMonth = (Integer) stack.pop(); - + stack.push(new Date(year, numMonth, dayOfMonthStart, era)); stack.push(new Date(year, numMonth, dayOfMonthStart, era)); stack.push(new Date(year, numMonth, dayOfMonthEnd, era)); stack.push(new Date(year, numMonth, dayOfMonthEnd, era)); } - + @Override public void exitDate(DateContext ctx) { if (ctx.exception != null) return; // Expect the canonical year-month-day-era ordering // to be on the stack. - + Era era = (Era) stack.pop(); Integer dayOfMonth = (Integer) stack.pop(); Integer numMonth = (Integer) stack.pop(); Integer year = (Integer) stack.pop(); - + // For the latest date we could either return null, or a copy of the earliest date, // since the UI doesn't care. Use a copy of the earliest date, since it makes // things easier here if we don't have to test for null up the tree. - + stack.push(new Date(year, numMonth, dayOfMonth, era)); stack.push(new Date(year, numMonth, dayOfMonth, era)); } - - + + @Override public void exitNumDate(NumDateContext ctx) { if (ctx.exception != null) return; - + // This could either be year-month-day, or // month-day-year. Try to determine which, // and reorder the stack into the canonical // year-month-day-era ordering. - + Era era = (Era) stack.pop(); Integer num3 = (Integer) stack.pop(); Integer num2 = (Integer) stack.pop(); Integer num1 = (Integer) stack.pop(); - - // Default to a year-month-day interpretation. - - int year = num1; - int numMonth = num2; - int dayOfMonth = num3; - - if (DateUtils.isValidDate(num1, num2, num3, era)) { - // Interpreting as year-month-day produces a valid date. Go with it. - } - else if (DateUtils.isValidDate(num3, num1, num2, era)) { - // Interpreting as year-month-day doesn't produce a valid date, but - // month-day-year does. Go with month-day-year. - - year = num3; - numMonth = num1; - dayOfMonth = num2; - } - + + // Default to a month-day-year interpretation. + + int numMonth = num1; + int dayOfMonth = num2; + int year = num3; + + if (DateUtils.isValidDate(num3, num1, num2, era)) { + // Interpreting as month-day-year produces a valid date. Go with it. + } + else if (DateUtils.isValidDate(num1, num2, num3, era)) { + // Interpreting as month-day-year doesn't produce a valid date, but + // year-month-day does. Go with year-month-day. + + year = num1; + numMonth = num2; + dayOfMonth = num3; + } + stack.push(year); stack.push(numMonth); stack.push(dayOfMonth); @@ -438,7 +438,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // Reorder the stack into a canonical ordering, // year-month-day-era. - + Era era = (Era) stack.pop(); Integer year = (Integer) stack.pop(); Integer dayOfMonth = (Integer) stack.pop(); @@ -456,12 +456,12 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // Reorder the stack into a canonical ordering, // year-month-day-era. - + Integer dayOfMonth = (Integer) stack.pop(); Integer numMonth = (Integer) stack.pop(); Integer year = (Integer) stack.pop(); Era era = (Era) stack.pop(); - + stack.push(year); stack.push(numMonth); stack.push(dayOfMonth); @@ -475,15 +475,15 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp Era era = (Era) stack.pop(); Integer year = (Integer) stack.pop(); Integer numMonth = (Integer) stack.pop(); - + stack.push(new Date(year, numMonth, 1, era)); stack.push(new Date(year, numMonth, DateUtils.getDaysInMonth(numMonth, year, era), era)); } - + @Override public void exitInvMonthYear(InvMonthYearContext ctx) { if (ctx.exception != null) return; - + // Invert the arguments. Integer numMonth = (Integer) stack.pop(); @@ -494,15 +494,15 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp stack.push(year); stack.push(era); } - + @Override public void exitYearSpanningWinter(YearSpanningWinterContext ctx) { if (ctx.exception != null) return; - + Era era = (Era) stack.pop(); Integer endYear = (Integer) stack.pop(); Integer startYear = (Integer) stack.pop(); - + stack.push(new Date(startYear, 12, 1).withEra(era)); stack.push(DateUtils.getQuarterYearEndDate(1, endYear, era).withEra(era)); } @@ -510,11 +510,11 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp @Override public void exitPartialYear(PartialYearContext ctx) { if (ctx.exception != null) return; - + Era era = (Era) stack.pop(); Integer year = (Integer) stack.pop(); Part part = (Part) stack.pop(); - + stack.push(DateUtils.getPartialYearStartDate(part, year).withEra(era)); stack.push(DateUtils.getPartialYearEndDate(part, year, era).withEra(era)); } @@ -522,7 +522,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp @Override public void exitQuarterYear(QuarterYearContext ctx) { if (ctx.exception != null) return; - + Era era = (Era) stack.pop(); Integer year = (Integer) stack.pop(); Integer quarter = (Integer) stack.pop(); @@ -534,25 +534,25 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp @Override public void exitHalfYear(HalfYearContext ctx) { if (ctx.exception != null) return; - + Era era = (Era) stack.pop(); Integer year = (Integer) stack.pop(); Integer half = (Integer) stack.pop(); stack.push(DateUtils.getHalfYearStartDate(half, year).withEra(era)); stack.push(DateUtils.getHalfYearEndDate(half, year, era).withEra(era)); - } - + } + @Override public void exitInvSeasonYear(InvSeasonYearContext ctx) { if (ctx.exception != null) return; - + // Invert the arguments. - + Integer quarter = (Integer) stack.pop(); Integer year = (Integer) stack.pop(); Era era = (Era) stack.pop(); - + stack.push(quarter); stack.push(year); stack.push(era); @@ -564,7 +564,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp Era era = (Era) stack.pop(); Integer year = (Integer) stack.pop(); - + stack.push(new Date(year, 1, 1, era)); stack.push(new Date(year, 12, 31, era)); } @@ -576,7 +576,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp Era era = (Era) stack.pop(); Integer year = (Integer) stack.pop(); Part part = (Part) stack.pop(); - + if (era != null) { // If the era was explicitly specified, the start and end years // may be calculated now. @@ -591,7 +591,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // range, where the era will be inherited from the era of the end of // the range; this era won't be known until farther up the parse tree, // when both sides of the range will have been parsed. - + stack.push(new DeferredPartialDecadeStartDate(year, part)); stack.push(new DeferredPartialDecadeEndDate(year, part)); } @@ -605,7 +605,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp Integer year = (Integer) stack.pop(); // Calculate the start and end year of the decade, which depends on the era. - + if (era != null) { // If the era was explicitly specified, the start and end years // may be calculated now. @@ -633,7 +633,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp Era era = (Era) stack.pop(); Integer year = (Integer) stack.pop(); Part part = (Part) stack.pop(); - + if (era != null) { // If the era was explicitly specified, the start and end years // may be calculated now. @@ -648,7 +648,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // range, where the era will be inherited from the era of the end of // the range; this era won't be known until farther up the parse tree, // when both sides of the range will have been parsed. - + stack.push(new DeferredPartialCenturyStartDate(year, part)); stack.push(new DeferredPartialCenturyEndDate(year, part)); } @@ -661,7 +661,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp Era era = (Era) stack.pop(); Integer year = (Integer) stack.pop(); Integer quarter = (Integer) stack.pop(); - + if (era != null) { // If the era was explicitly specified, the start and end years // may be calculated now. @@ -676,7 +676,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // range, where the era will be inherited from the era of the end of // the range; this era won't be known until farther up the parse tree, // when both sides of the range will have been parsed. - + stack.push(new DeferredQuarterCenturyStartDate(year, quarter)); stack.push(new DeferredQuarterCenturyEndDate(year, quarter)); } @@ -685,11 +685,11 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp @Override public void exitHalfCentury(HalfCenturyContext ctx) { if (ctx.exception != null) return; - + Era era = (Era) stack.pop(); Integer year = (Integer) stack.pop(); Integer half = (Integer) stack.pop(); - + if (era != null) { // If the era was explicitly specified, the start and end years // may be calculated now. @@ -704,7 +704,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // range, where the era will be inherited from the era of the end of // the range; this era won't be known until farther up the parse tree, // when both sides of the range will have been parsed. - + stack.push(new DeferredHalfCenturyStartDate(year, half)); stack.push(new DeferredHalfCenturyEndDate(year, half)); } @@ -731,7 +731,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // range, where the era will be inherited from the era of the end of // the range; this era won't be known until farther up the parse tree, // when both sides of the range will have been parsed. - + stack.push(new DeferredCenturyStartDate(year)); stack.push(new DeferredCenturyEndDate(year)); } @@ -740,7 +740,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp @Override public void exitMillennium(MillenniumContext ctx) { if (ctx.exception != null) return; - + Era era = (Era) stack.pop(); Integer n = (Integer) stack.pop(); @@ -758,7 +758,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // range, where the era will be inherited from the era of the end of // the range; this era won't be known until farther up the parse tree, // when both sides of the range will have been parsed. - + stack.push(new DeferredMillenniumStartDate(n)); stack.push(new DeferredMillenniumEndDate(n)); } @@ -767,14 +767,14 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp @Override public void exitStrCentury(StrCenturyContext ctx) { if (ctx.exception != null) return; - + Integer n = (Integer) stack.pop(); - + // Convert the nth number to a year number, // and push on the stack. - + Integer year = DateUtils.nthCenturyToYear(n); - + stack.push(year); } @@ -786,11 +786,11 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // and push on the stack. Integer year = new Integer(stripEndLetters(ctx.HUNDREDS().getText())); - + if (year == 0) { throw new StructuredDateFormatException("unexpected century '" + ctx.HUNDREDS().getText() + "'"); } - + stack.push(year); } @@ -816,9 +816,9 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // Convert the string to a number, // and push on the stack. - + Integer year = new Integer(ctx.NUMBER().getText()); - + if (year == 0) { throw new StructuredDateFormatException("unexpected year '" + ctx.NUMBER().getText() + "'"); } @@ -832,13 +832,13 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // Convert the string a number, // and push on the stack. - + Integer month = new Integer(ctx.NUMBER().getText()); - + if (month < 1 || month > 12) { throw new StructuredDateFormatException("unexpected month '" + ctx.NUMBER().getText() + "'"); } - + stack.push(month); } @@ -851,20 +851,20 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // alternative with nth instead of LAST, // the nth handler will already have pushed // a number on the stack. - + if (ctx.LAST() != null) { stack.push(new Integer(2)); } - + // Check for a valid half. - + Integer n = (Integer) stack.peek(); - + if (n < 1 || n > 2) { throw new StructuredDateFormatException("unexpected half '" + n + "'"); } } - + @Override public void exitNthQuarter(NthQuarterContext ctx) { if (ctx.exception != null) return; @@ -874,15 +874,15 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // alternative with nth instead of LAST, // the nth handler will already have pushed // a number on the stack. - + if (ctx.LAST() != null) { stack.push(new Integer(4)); } - + // Check for a valid quarter. - + Integer n = (Integer) stack.peek(); - + if (n < 1 || n > 4) { throw new StructuredDateFormatException("unexpected quarter '" + n + "'"); } @@ -891,12 +891,12 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp @Override public void exitNth(NthContext ctx) { if (ctx.exception != null) return; - + // Convert the string to a number, // and push on the stack. - + Integer n = null; - + if (ctx.NTHSTR() != null) { n = new Integer(stripEndLetters(ctx.NTHSTR().getText())); } @@ -912,37 +912,37 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp else if (ctx.FOURTH() != null) { n = 4; } - + stack.push(n); } @Override public void exitStrMonth(StrMonthContext ctx) { if (ctx.exception != null) return; - + // Convert the month name to a number, // and push on the stack. - + TerminalNode monthNode = ctx.MONTH(); - + if (monthNode == null) { monthNode = ctx.SHORTMONTH(); } - + String monthStr = monthNode.getText(); stack.push(DateUtils.getMonthByName(monthStr)); } - + @Override public void exitStrSeason(StrSeasonContext ctx) { if (ctx.exception != null) return; - + // Convert the season to a quarter number, // and push on the stack. - + Integer quarter = null; - + if (ctx.WINTER() != null) { quarter = 1; } @@ -955,18 +955,18 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp else if (ctx.FALL() != null) { quarter = 4; } - + stack.push(quarter); } @Override public void exitAllOrPartOf(AllOrPartOfContext ctx) { if (ctx.exception != null) return; - + // If a part was specified, it will have been // pushed on the stack in exitPartOf(). If not, // push null on the stack. - + if (ctx.partOf() == null) { stack.push(null); } @@ -975,12 +975,12 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp @Override public void exitPartOf(PartOfContext ctx) { if (ctx.exception != null) return; - + // Convert the token to a Part, // and push on the stack. - + Part part = null; - + if (ctx.EARLY() != null) { part = Part.EARLY; } @@ -990,7 +990,7 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp else if (ctx.LATE() != null) { part = Part.LATE; } - + stack.push(part); } @@ -1000,16 +1000,16 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // Convert the token to an Era, // and push on the stack. - + Era era = null; - + if (ctx.BC() != null) { era = Era.BCE; } else if (ctx.AD() != null) { era = Era.CE; } - + stack.push(era); } @@ -1019,16 +1019,16 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // Convert the numeric string to an Integer, // and push on the stack. - + Integer dayOfMonth = new Integer(ctx.NUMBER().getText()); - + if (dayOfMonth == 0 || dayOfMonth > 31) { throw new StructuredDateFormatException("unexpected day of month '" + ctx.NUMBER().getText() + "'"); } stack.push(dayOfMonth); } - + @Override public void exitNum(NumContext ctx) { if (ctx.exception != null) return; @@ -1037,21 +1037,21 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp // and push on the stack. Integer num = new Integer(ctx.NUMBER().getText()); - + stack.push(num); } protected String getErrorMessage(RecognitionException re) { String message = ""; - + Parser recognizer = (Parser) re.getRecognizer(); TokenStream tokens = recognizer.getInputStream(); - + if (re instanceof NoViableAltException) { NoViableAltException e = (NoViableAltException) re; Token startToken = e.getStartToken(); String input = (startToken.getType() == Token.EOF ) ? "end of text" : quote(tokens.getText(startToken, e.getOffendingToken())); - + message = "no viable date format found at " + input; } else if (re instanceof InputMismatchException) { @@ -1062,26 +1062,26 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp else if (re instanceof FailedPredicateException) { FailedPredicateException e = (FailedPredicateException) re; String ruleName = recognizer.getRuleNames()[recognizer.getContext().getRuleIndex()]; - + message = "failed predicate " + ruleName + ": " + e.getMessage(); } - + return message; } - + protected String quote(String text) { return "'" + text + "'"; } - + protected String getTokenDisplayString(Token token) { String string; - + if (token == null) { string = "[no token]"; } else { String text = token.getText(); - + if (text == null) { if (token.getType() == Token.EOF ) { string = "end of text"; @@ -1094,17 +1094,17 @@ public class ANTLRStructuredDateEvaluator extends StructuredDateBaseListener imp string = quote(text); } } - + return string; } protected String stripEndLetters(String input) { return input.replaceAll("[^\\d]+$", ""); } - + public static void main(String[] args) { StructuredDateEvaluator evaluator = new ANTLRStructuredDateEvaluator(); - + for (String displayDate : args) { try { evaluator.evaluate(displayDate); diff --git a/services/structureddate/src/test/resources/test-dates.yaml b/services/structureddate/src/test/resources/test-dates.yaml index 3a0448d92..d458de693 100644 --- a/services/structureddate/src/test/resources/test-dates.yaml +++ b/services/structureddate/src/test/resources/test-dates.yaml @@ -3,7 +3,7 @@ # Specify an input display date, and an expected output structured date. Fields expected to be null # in the structured date may be omitted. # -# If the structured date's displayDate field is omitted, it will be expected to be equal to the +# If the structured date's displayDate field is omitted, it will be expected to be equal to the # input display date. This is the usual case. # # The StructuredDate's earliestSingleDate and latestDate should be specified as a @@ -14,7 +14,7 @@ # # Input Display Date Expected Structured Date # ======================================================================================================= -# +# # Valid dates # ------------------------------------------------------------------------------------------------------- @@ -65,7 +65,7 @@ '1974 A.D.': # year earliestSingleDate: [1974, 1, 1, CE] latestDate: [1974, 12, 31, CE] - + '1974 a.d.': # year earliestSingleDate: [1974, 1, 1, CE] latestDate: [1974, 12, 31, CE] @@ -101,7 +101,7 @@ "300s-200s BC": # hyphenatedRange, century earliestSingleDate: [ 399, 1, 1, BCE] latestDate: [ 200, 12, 31, BCE] - + "1970's-1980's": # hyphenatedRange, decade earliestSingleDate: [1970, 1, 1, CE] latestDate: [1989, 12, 31, CE] @@ -121,7 +121,7 @@ '30s BC-20s BC': # hyphenatedRange, decade earliestSingleDate: [ 39, 1, 1, BCE] latestDate: [ 20, 12, 31, BCE] - + '1974-2013': # hyphenatedRange, year earliestSingleDate: [1974, 1, 1, CE] latestDate: [2013, 12, 31, CE] @@ -145,7 +145,7 @@ '12 BC - 30': # hyphenatedRange, year earliestSingleDate: [ 12, 1, 1, BCE] latestDate: [ 30, 12, 31, CE] - + 'Spring 1974-Summer 1975': # hyphenatedRange, quarterYear earliestSingleDate: [1974, 4, 1, CE] latestDate: [1975, 9, 30, CE] @@ -172,476 +172,476 @@ '1st half 2000 - 1st half 2001': # hyphenatedRange, halfYear earliestSingleDate: [2000, 1, 1, CE] - latestDate: [2001, 6, 30, CE] + latestDate: [2001, 6, 30, CE] 'second half 1998 - last half 2003': # hyphenatedRange, halfYear earliestSingleDate: [1998, 7, 1, CE] - latestDate: [2003, 12, 31, CE] + latestDate: [2003, 12, 31, CE] 'second half 1998 - last half 2003 ad': # hyphenatedRange, halfYear earliestSingleDate: [1998, 7, 1, CE] - latestDate: [2003, 12, 31, CE] + latestDate: [2003, 12, 31, CE] '2nd half 12 - first half 11 BC': # hyphenatedRange, halfYear earliestSingleDate: [ 12, 7, 1, BCE] - latestDate: [ 11, 6, 30, BCE] + latestDate: [ 11, 6, 30, BCE] '2nd half 12 b.c. - first half 2 AD': # hyphenatedRange, halfYear earliestSingleDate: [ 12, 7, 1, BCE] - latestDate: [ 2, 6, 30, CE] + latestDate: [ 2, 6, 30, CE] '1st half 2000': # halfYear earliestSingleDate: [2000, 1, 1, CE] - latestDate: [2000, 6, 30, CE] - + latestDate: [2000, 6, 30, CE] + '2nd half 2000': # halfYear earliestSingleDate: [2000, 7, 1, CE] - latestDate: [2000, 12, 31, CE] + latestDate: [2000, 12, 31, CE] 'last half 2000': # halfYear earliestSingleDate: [2000, 7, 1, CE] - latestDate: [2000, 12, 31, CE] + latestDate: [2000, 12, 31, CE] 'early 1960s': # partialDecade earliestSingleDate: [1960, 1, 1, CE] - latestDate: [1963, 12, 31, CE] + latestDate: [1963, 12, 31, CE] "mid 1960's": # partialDecade earliestSingleDate: [1964, 1, 1, CE] - latestDate: [1966, 12, 31, CE] + latestDate: [1966, 12, 31, CE] 'late 1960s': # partialDecade earliestSingleDate: [1967, 1, 1, CE] - latestDate: [1969, 12, 31, CE] + latestDate: [1969, 12, 31, CE] 'early 1960s ce': # partialDecade earliestSingleDate: [1960, 1, 1, CE] - latestDate: [1963, 12, 31, CE] + latestDate: [1963, 12, 31, CE] "mid-1960's a.d.": # partialDecade earliestSingleDate: [1964, 1, 1, CE] - latestDate: [1966, 12, 31, CE] + latestDate: [1966, 12, 31, CE] 'late 1960s AD': # partialDecade earliestSingleDate: [1967, 1, 1, CE] - latestDate: [1969, 12, 31, CE] + latestDate: [1969, 12, 31, CE] 'early 530s bc': # partialDecade earliestSingleDate: [ 539, 1, 1, BCE] - latestDate: [ 537, 12, 31, BCE] + latestDate: [ 537, 12, 31, BCE] "middle 530's b.c.": # partialDecade earliestSingleDate: [ 536, 1, 1, BCE] - latestDate: [ 534, 12, 31, BCE] + latestDate: [ 534, 12, 31, BCE] 'late 530s B.C.': # partialDecade earliestSingleDate: [ 533, 1, 1, BCE] - latestDate: [ 530, 12, 31, BCE] + latestDate: [ 530, 12, 31, BCE] "mid 1960's-early 1970's": # hyphenatedRange, partialDecade earliestSingleDate: [1964, 1, 1, CE] - latestDate: [1973, 12, 31, CE] + latestDate: [1973, 12, 31, CE] "mid 1960's-early 1970's a.d.": # hyphenatedRange, partialDecade earliestSingleDate: [1964, 1, 1, CE] - latestDate: [1973, 12, 31, CE] + latestDate: [1973, 12, 31, CE] "mid 520's-early 480's b.c.": # hyphenatedRange, partialDecade earliestSingleDate: [ 526, 1, 1, BCE] - latestDate: [ 487, 12, 31, BCE] + latestDate: [ 487, 12, 31, BCE] '1960s': # decade earliestSingleDate: [1960, 1, 1, CE] - latestDate: [1969, 12, 31, CE] + latestDate: [1969, 12, 31, CE] "1920's": # decade earliestSingleDate: [1920, 1, 1, CE] - latestDate: [1929, 12, 31, CE] + latestDate: [1929, 12, 31, CE] '1920S': # decade earliestSingleDate: [1920, 1, 1, CE] - latestDate: [1929, 12, 31, CE] + latestDate: [1929, 12, 31, CE] "20's BC": # decade earliestSingleDate: [ 29, 1, 1, BCE] - latestDate: [ 20, 12, 31, BCE] + latestDate: [ 20, 12, 31, BCE] '1960s-1980s': # hyphenatedRange, decade earliestSingleDate: [1960, 1, 1, CE] - latestDate: [1989, 12, 31, CE] + latestDate: [1989, 12, 31, CE] '1960s-1980s A.D.': # hyphenatedRange, decade earliestSingleDate: [1960, 1, 1, CE] - latestDate: [1989, 12, 31, CE] + latestDate: [1989, 12, 31, CE] '1960s–1920s B.C.': # hyphenatedRange, decade (en dash) earliestSingleDate: [1969, 1, 1, BCE] - latestDate: [1920, 12, 31, BCE] + latestDate: [1920, 12, 31, BCE] "1960's-early 1980's": # hyphenatedRange, decade, partialDecade earliestSingleDate: [1960, 1, 1, CE] - latestDate: [1983, 12, 31, CE] + latestDate: [1983, 12, 31, CE] "late 1820's - 1880's": # hyphenatedRange, partialDecade, decade earliestSingleDate: [1827, 1, 1, CE] - latestDate: [1889, 12, 31, CE] + latestDate: [1889, 12, 31, CE] 'early 1900s': # partialCentury earliestSingleDate: [1900, 1, 1, CE] - latestDate: [1933, 12, 31, CE] + latestDate: [1933, 12, 31, CE] 'mid 1900s': # partialCentury earliestSingleDate: [1933, 1, 1, CE] - latestDate: [1966, 12, 31, CE] + latestDate: [1966, 12, 31, CE] "Late 1900's": # partialCentury earliestSingleDate: [1966, 1, 1, CE] - latestDate: [1999, 12, 31, CE] + latestDate: [1999, 12, 31, CE] 'early 1900s ad': # partialCentury earliestSingleDate: [1900, 1, 1, CE] - latestDate: [1933, 12, 31, CE] + latestDate: [1933, 12, 31, CE] 'mid 1900s CE': # partialCentury earliestSingleDate: [1933, 1, 1, CE] - latestDate: [1966, 12, 31, CE] + latestDate: [1966, 12, 31, CE] "Late 1900's A.D.": # partialCentury earliestSingleDate: [1966, 1, 1, CE] - latestDate: [1999, 12, 31, CE] + latestDate: [1999, 12, 31, CE] 'early 18th century': # partialCentury earliestSingleDate: [1701, 1, 1, CE] - latestDate: [1734, 12, 31, CE] + latestDate: [1734, 12, 31, CE] 'mid-18th century': # partialCentury earliestSingleDate: [1734, 1, 1, CE] - latestDate: [1767, 12, 31, CE] + latestDate: [1767, 12, 31, CE] 'Late 18th century': # partialCentury earliestSingleDate: [1767, 1, 1, CE] - latestDate: [1800, 12, 31, CE] + latestDate: [1800, 12, 31, CE] 'early 100s b.c.': # partialCentury earliestSingleDate: [ 199, 1, 1, BCE] - latestDate: [ 166, 12, 31, BCE] + latestDate: [ 166, 12, 31, BCE] 'middle 100s bc': # partialCentury earliestSingleDate: [ 166, 1, 1, BCE] - latestDate: [ 133, 12, 31, BCE] + latestDate: [ 133, 12, 31, BCE] "Late 100's B.C.": # partialCentury earliestSingleDate: [ 133, 1, 1, BCE] - latestDate: [ 100, 12, 31, BCE] + latestDate: [ 100, 12, 31, BCE] 'early 2nd century b.c.': # partialCentury earliestSingleDate: [ 200, 1, 1, BCE] - latestDate: [ 167, 12, 31, BCE] + latestDate: [ 167, 12, 31, BCE] 'mid 2nd century bc': # partialCentury earliestSingleDate: [ 167, 1, 1, BCE] - latestDate: [ 134, 12, 31, BCE] + latestDate: [ 134, 12, 31, BCE] 'Late 2nd Century B.C.': # partialCentury earliestSingleDate: [ 134, 1, 1, BCE] - latestDate: [ 101, 12, 31, BCE] + latestDate: [ 101, 12, 31, BCE] 'mid-17th century - late 18th century': # hyphenatedRange, partialCentury earliestSingleDate: [1634, 1, 1, CE] - latestDate: [1800, 12, 31, CE] + latestDate: [1800, 12, 31, CE] 'mid 17th century - late 18th century a.d.': # hyphenatedRange, partialCentury earliestSingleDate: [1634, 1, 1, CE] - latestDate: [1800, 12, 31, CE] + latestDate: [1800, 12, 31, CE] 'middle 17th century AD - late 18th century a.d.': # hyphenatedRange, partialCentury earliestSingleDate: [1634, 1, 1, CE] - latestDate: [1800, 12, 31, CE] + latestDate: [1800, 12, 31, CE] 'late 1800s - early 1900s': # hyphenatedRange, partialCentury earliestSingleDate: [1866, 1, 1, CE] - latestDate: [1933, 12, 31, CE] + latestDate: [1933, 12, 31, CE] 'late 1800s - early 1900s ce': # hyphenatedRange, partialCentury earliestSingleDate: [1866, 1, 1, CE] - latestDate: [1933, 12, 31, CE] + latestDate: [1933, 12, 31, CE] "mid 200s-late 100's BCE": # hyphenatedRange, partialCentury earliestSingleDate: [ 266, 1, 1, BCE] - latestDate: [ 100, 12, 31, BCE] + latestDate: [ 100, 12, 31, BCE] 'late 4th century - early 3rd century bc': # hyphenatedRange, partialCentury earliestSingleDate: [ 334, 1, 1, BCE] - latestDate: [ 267, 12, 31, BCE] + latestDate: [ 267, 12, 31, BCE] 'late 4th century B.C. - early 3rd century BC': # hyphenatedRange, partialCentury earliestSingleDate: [ 334, 1, 1, BCE] - latestDate: [ 267, 12, 31, BCE] + latestDate: [ 267, 12, 31, BCE] 'late 2nd century B.C. - mid 1st century': # hyphenatedRange, partialCentury earliestSingleDate: [ 134, 1, 1, BCE] - latestDate: [ 67, 12, 31, CE] + latestDate: [ 67, 12, 31, CE] 'late 2nd century B.C. - early 3rd century A.D.': # hyphenatedRange, partialCentury earliestSingleDate: [ 134, 1, 1, BCE] - latestDate: [ 234, 12, 31, CE] + latestDate: [ 234, 12, 31, CE] '1st quarter 1900s': # quarterCentury earliestSingleDate: [1900, 1, 1, CE] - latestDate: [1924, 12, 31, CE] + latestDate: [1924, 12, 31, CE] 'second quarter 1900s': # quarterCentury earliestSingleDate: [1925, 1, 1, CE] - latestDate: [1949, 12, 31, CE] + latestDate: [1949, 12, 31, CE] "3rd quarter 1900's": # quarterCentury earliestSingleDate: [1950, 1, 1, CE] - latestDate: [1974, 12, 31, CE] + latestDate: [1974, 12, 31, CE] "fourth quarter 1900's": # quarterCentury earliestSingleDate: [1975, 1, 1, CE] - latestDate: [1999, 12, 31, CE] + latestDate: [1999, 12, 31, CE] 'first quarter 18th century': # quarterCentury earliestSingleDate: [1701, 1, 1, CE] - latestDate: [1725, 12, 31, CE] + latestDate: [1725, 12, 31, CE] '2nd quarter 18th century': # quarterCentury earliestSingleDate: [1726, 1, 1, CE] - latestDate: [1750, 12, 31, CE] + latestDate: [1750, 12, 31, CE] 'third quarter 18th century': # quarterCentury earliestSingleDate: [1751, 1, 1, CE] - latestDate: [1775, 12, 31, CE] + latestDate: [1775, 12, 31, CE] '4th quarter 18th century': # quarterCentury earliestSingleDate: [1776, 1, 1, CE] - latestDate: [1800, 12, 31, CE] + latestDate: [1800, 12, 31, CE] 'first quarter 1st century a.d.': # quarterCentury earliestSingleDate: [ 1, 1, 1, CE] - latestDate: [ 25, 12, 31, CE] + latestDate: [ 25, 12, 31, CE] '4th quarter 22nd century CE': # quarterCentury earliestSingleDate: [2176, 1, 1, CE] - latestDate: [2200, 12, 31, CE] + latestDate: [2200, 12, 31, CE] 'First quarter 300s BC': # quarterCentury earliestSingleDate: [ 399, 1, 1, BCE] - latestDate: [ 375, 12, 31, BCE] + latestDate: [ 375, 12, 31, BCE] "2nd quarter 300's BC": # quarterCentury earliestSingleDate: [ 374, 1, 1, BCE] - latestDate: [ 350, 12, 31, BCE] + latestDate: [ 350, 12, 31, BCE] 'third quarter 300s BC': # quarterCentury earliestSingleDate: [ 349, 1, 1, BCE] - latestDate: [ 325, 12, 31, BCE] + latestDate: [ 325, 12, 31, BCE] '4th quarter 300s B.C.': # quarterCentury earliestSingleDate: [ 324, 1, 1, BCE] - latestDate: [ 300, 12, 31, BCE] + latestDate: [ 300, 12, 31, BCE] 'First quarter 1st century BC': # quarterCentury earliestSingleDate: [ 100, 1, 1, BCE] - latestDate: [ 76, 12, 31, BCE] + latestDate: [ 76, 12, 31, BCE] '2nd quarter 1st century BC': # quarterCentury earliestSingleDate: [ 75, 1, 1, BCE] - latestDate: [ 51, 12, 31, BCE] + latestDate: [ 51, 12, 31, BCE] 'third quarter 1st century BC': # quarterCentury earliestSingleDate: [ 50, 1, 1, BCE] - latestDate: [ 26, 12, 31, BCE] + latestDate: [ 26, 12, 31, BCE] '4th quarter 1st century BC': # quarterCentury earliestSingleDate: [ 25, 1, 1, BCE] - latestDate: [ 1, 12, 31, BCE] + latestDate: [ 1, 12, 31, BCE] '1st quarter 2nd century B.C.': # quarterCentury earliestSingleDate: [ 200, 1, 1, BCE] - latestDate: [ 176, 12, 31, BCE] + latestDate: [ 176, 12, 31, BCE] 'second quarter 2nd century BCE': # quarterCentury earliestSingleDate: [ 175, 1, 1, BCE] - latestDate: [ 151, 12, 31, BCE] + latestDate: [ 151, 12, 31, BCE] '3rd quarter 2nd century b.c.': # quarterCentury earliestSingleDate: [ 150, 1, 1, BCE] - latestDate: [ 126, 12, 31, BCE] + latestDate: [ 126, 12, 31, BCE] 'fourth quarter 2nd century b.c.e.': # quarterCentury earliestSingleDate: [ 125, 1, 1, BCE] - latestDate: [ 101, 12, 31, BCE] + latestDate: [ 101, 12, 31, BCE] 'last quarter 2nd century b.c.e.': # quarterCentury earliestSingleDate: [ 125, 1, 1, BCE] - latestDate: [ 101, 12, 31, BCE] + latestDate: [ 101, 12, 31, BCE] '1st quarter 18th century - 3rd quarter 19th century': # hyphenatedRange, quarterCentury earliestSingleDate: [1701, 1, 1, CE] - latestDate: [1875, 12, 31, CE] + latestDate: [1875, 12, 31, CE] '1st quarter 18th century - 3rd quarter 19th century a.d.': # hyphenatedRange, quarterCentury earliestSingleDate: [1701, 1, 1, CE] - latestDate: [1875, 12, 31, CE] + latestDate: [1875, 12, 31, CE] '4th quarter 3rd century - 3rd quarter 2nd century b.c.': # hyphenatedRange, quarterCentury earliestSingleDate: [ 225, 1, 1, BCE] - latestDate: [ 126, 12, 31, BCE] + latestDate: [ 126, 12, 31, BCE] '4th quarter 1st century b.c.-1st quarter 1st century ce': # hyphenatedRange, quarterCentury earliestSingleDate: [ 25, 1, 1, BCE] - latestDate: [ 25, 12, 31, CE] + latestDate: [ 25, 12, 31, CE] '1st half 1900s': # halfCentury earliestSingleDate: [1900, 1, 1, CE] - latestDate: [1949, 12, 31, CE] + latestDate: [1949, 12, 31, CE] 'second half 1900s': # halfCentury earliestSingleDate: [1950, 1, 1, CE] - latestDate: [1999, 12, 31, CE] + latestDate: [1999, 12, 31, CE] 'last half 1900s': # halfCentury earliestSingleDate: [1950, 1, 1, CE] - latestDate: [1999, 12, 31, CE] + latestDate: [1999, 12, 31, CE] 'first half 20th century': # halfCentury earliestSingleDate: [1901, 1, 1, CE] - latestDate: [1950, 12, 31, CE] + latestDate: [1950, 12, 31, CE] '2nd half 20th century': # halfCentury earliestSingleDate: [1951, 1, 1, CE] - latestDate: [2000, 12, 31, CE] + latestDate: [2000, 12, 31, CE] '1st half 1900s A.D.': # halfCentury earliestSingleDate: [1900, 1, 1, CE] - latestDate: [1949, 12, 31, CE] + latestDate: [1949, 12, 31, CE] "second half 1900's c.e.": # halfCentury earliestSingleDate: [1950, 1, 1, CE] - latestDate: [1999, 12, 31, CE] + latestDate: [1999, 12, 31, CE] '1st half 1900s B.C.': # halfCentury earliestSingleDate: [1999, 1, 1, BCE] - latestDate: [1950, 12, 31, BCE] + latestDate: [1950, 12, 31, BCE] "second half 1900's b.c.e.": # halfCentury earliestSingleDate: [1949, 1, 1, BCE] - latestDate: [1900, 12, 31, BCE] + latestDate: [1900, 12, 31, BCE] 'first half first century b.c.': # halfCentury earliestSingleDate: [ 100, 1, 1, BCE] - latestDate: [ 51, 12, 31, BCE] + latestDate: [ 51, 12, 31, BCE] "second half 1st century BCE": # halfCentury earliestSingleDate: [ 50, 1, 1, BCE] - latestDate: [ 1, 12, 31, BCE] + latestDate: [ 1, 12, 31, BCE] '1st half 1900s - 1st half 2000s': # hyphenatedRange, halfCentury earliestSingleDate: [1900, 1, 1, CE] - latestDate: [2049, 12, 31, CE] + latestDate: [2049, 12, 31, CE] '1st half 1900s - 1st half 2000s ad': # hyphenatedRange, halfCentury earliestSingleDate: [1900, 1, 1, CE] - latestDate: [2049, 12, 31, CE] + latestDate: [2049, 12, 31, CE] '2nd half 900s - 1st half 700s bc': # hyphenatedRange, halfCentury earliestSingleDate: [ 949, 1, 1, BCE] - latestDate: [ 750, 12, 31, BCE] + latestDate: [ 750, 12, 31, BCE] '2nd half 200s bc - 1st half 100s': # hyphenatedRange, halfCentury earliestSingleDate: [ 249, 1, 1, BCE] - latestDate: [ 149, 12, 31, CE] + latestDate: [ 149, 12, 31, CE] '1900s': # century earliestSingleDate: [1900, 1, 1, CE] - latestDate: [1999, 12, 31, CE] + latestDate: [1999, 12, 31, CE] '20th century': # century earliestSingleDate: [1901, 1, 1, CE] - latestDate: [2000, 12, 31, CE] + latestDate: [2000, 12, 31, CE] '20th century AD': # century earliestSingleDate: [1901, 1, 1, CE] - latestDate: [2000, 12, 31, CE] + latestDate: [2000, 12, 31, CE] "1600's": # century earliestSingleDate: [1600, 1, 1, CE] - latestDate: [1699, 12, 31, CE] + latestDate: [1699, 12, 31, CE] '21st century': # century earliestSingleDate: [2001, 1, 1, CE] - latestDate: [2100, 12, 31, CE] + latestDate: [2100, 12, 31, CE] '1st century BC': # century earliestSingleDate: [ 100, 1, 1, BCE] - latestDate: [ 1, 12, 31, BCE] + latestDate: [ 1, 12, 31, BCE] '8th century BC': # century earliestSingleDate: [ 800, 1, 1, BCE] - latestDate: [ 701, 12, 31, BCE] + latestDate: [ 701, 12, 31, BCE] "100's BC": # century earliestSingleDate: [ 199, 1, 1, BCE] - latestDate: [ 100, 12, 31, BCE] + latestDate: [ 100, 12, 31, BCE] '19th century - 20th century': # hyphenatedRange, century earliestSingleDate: [1801, 1, 1, CE] - latestDate: [2000, 12, 31, CE] + latestDate: [2000, 12, 31, CE] '19th century - 20th century ad': # hyphenatedRange, century earliestSingleDate: [1801, 1, 1, CE] - latestDate: [2000, 12, 31, CE] + latestDate: [2000, 12, 31, CE] '3rd century - 2nd century B.C.': # hyphenatedRange, century earliestSingleDate: [ 300, 1, 1, BCE] - latestDate: [ 101, 12, 31, BCE] + latestDate: [ 101, 12, 31, BCE] '3rd century BC - 1st century A.D.': # hyphenatedRange, century earliestSingleDate: [ 300, 1, 1, BCE] - latestDate: [ 100, 12, 31, CE] + latestDate: [ 100, 12, 31, CE] 'late 1880s - early 1900s': # hyphenatedRange, partialDecade, partialCentury earliestSingleDate: [1887, 1, 1, CE] - latestDate: [1933, 12, 31, CE] + latestDate: [1933, 12, 31, CE] '1st millennium': # millennium earliestSingleDate: [ 1, 1, 1, CE] - latestDate: [1000, 12, 31, CE] + latestDate: [1000, 12, 31, CE] '2nd millennium': # millennium earliestSingleDate: [1001, 1, 1, CE] - latestDate: [2000, 12, 31, CE] + latestDate: [2000, 12, 31, CE] '3rd millennium': # millennium earliestSingleDate: [2001, 1, 1, CE] - latestDate: [3000, 12, 31, CE] + latestDate: [3000, 12, 31, CE] '5th millennium': # millennium earliestSingleDate: [4001, 1, 1, CE] - latestDate: [5000, 12, 31, CE] + latestDate: [5000, 12, 31, CE] '1st Millennium BC': # millennium earliestSingleDate: [1000, 1, 1, BCE] - latestDate: [ 1, 12, 31, BCE] + latestDate: [ 1, 12, 31, BCE] '2nd millennium B.C.E.': # millennium earliestSingleDate: [2000, 1, 1, BCE] - latestDate: [1001, 12, 31, BCE] + latestDate: [1001, 12, 31, BCE] '1st millennium-2nd millennium': # hyphenatedRange, millennium earliestSingleDate: [ 1, 1, 1, CE] - latestDate: [2000, 12, 31, CE] + latestDate: [2000, 12, 31, CE] '1st millennium-2nd millennium ad': # hyphenatedRange, millennium earliestSingleDate: [ 1, 1, 1, CE] - latestDate: [2000, 12, 31, CE] + latestDate: [2000, 12, 31, CE] '3rd millennium-2nd millennium bc': # hyphenatedRange, millennium earliestSingleDate: [3000, 1, 1, BCE] - latestDate: [1001, 12, 31, BCE] - + latestDate: [1001, 12, 31, BCE] + 'Winter 2000': # quarterYear, seasonYear earliestSingleDate: [2000, 1, 1, CE] latestDate: [2000, 3, 31, CE] @@ -677,11 +677,11 @@ 'Autumn 2000': # quarterYear, seasonYear earliestSingleDate: [2000, 10, 1, CE] latestDate: [2000, 12, 31, CE] - + 'Aut 2000': # quarterYear, seasonYear earliestSingleDate: [2000, 10, 1, CE] latestDate: [2000, 12, 31, CE] - + 'Sum 12 BC': # quarterYear, seasonYear earliestSingleDate: [ 12, 7, 1, BCE] latestDate: [ 12, 9, 30, BCE] @@ -740,7 +740,7 @@ '1st quarter - 3rd quarter 2000': # hyphenatedRange, quarterYear earliestSingleDate: [2000, 1, 1, CE] - latestDate: [2000, 9, 30, CE] + latestDate: [2000, 9, 30, CE] '2nd quarter - last quarter 2000': # hyphenatedRange, quarterYear earliestSingleDate: [2000, 4, 1, CE] @@ -841,12 +841,12 @@ 'May 130-May 120 BC': # hyphenatedRange, month earliestSingleDate: [ 130, 5, 1, BCE] latestDate: [ 120, 5, 31, BCE] - + '3/12/2013': # date earliestSingleDate: [2013, 3, 12, CE] '03/05/13': # date - earliestSingleDate: [ 3, 5, 13, CE] + earliestSingleDate: [ 13, 3, 5, CE] '7-6-1773': # date earliestSingleDate: [1773, 7, 6, CE] @@ -867,10 +867,10 @@ earliestSingleDate: [ 13, 12, 3, CE] '12-12-3': # date - earliestSingleDate: [ 12, 12, 3, CE] + earliestSingleDate: [ 3, 12, 12, CE] '3-12-12': # date - earliestSingleDate: [ 3, 12, 12, CE] + earliestSingleDate: [ 12, 3, 12, CE] '3-12-32': # date earliestSingleDate: [ 32, 3, 12, CE] @@ -1106,13 +1106,13 @@ "3/4/2000?": # oneDisplayDate - with question mark earliestSingleDate: [2000, 3, 4, CE] -# ------------------------------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------------------------------- # Invalid dates # ------------------------------------------------------------------------------------------------------- '': # empty null - + 'Octo 19, 1821': # invalid month null @@ -1121,22 +1121,22 @@ 'May-Foo 2000': # invalid month null - + 'Something else': # totally not a date - null + null 'BC 12, Sumer': # invalid season null '5th quarter 1900': # invalid quarter number null - + '0th quarter 1900': # invalid quarter number - null + null 'third half 1900': # invalid half number - null - + null + '0th half 1900': # invalid half number null @@ -1148,4 +1148,3 @@ '3/4?/2005': # question mark null - \ No newline at end of file -- 2.47.3