From 9d3e34b9f98ffbe0f40781f34669841035cb8953 Mon Sep 17 00:00:00 2001 From: Alexander Reelsen Date: Mon, 10 Jun 2013 10:55:45 +0200 Subject: [PATCH] Allow date format to supported group of built-in patterns Until now 'named dates' like dateOptionalTime could not be used as a group of dates. This patch allows it to group it arbitrarily like this: * yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||dateOptionalTime * dateOptionalTime||yyyy/MM/dd HH:mm:ss||yyyy/MM/dd * yyyy/MM/dd HH:mm:ss||dateOptionalTime||yyyy/MM/dd * date_time||date_time_no_millis Closes #2132 --- .../org/elasticsearch/common/joda/Joda.java | 40 ++++++++++++++----- .../test/unit/deps/joda/SimpleJodaTests.java | 40 +++++++++++++++++-- 2 files changed, 67 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/elasticsearch/common/joda/Joda.java b/src/main/java/org/elasticsearch/common/joda/Joda.java index d568ad6adf4..a3f9224cca9 100644 --- a/src/main/java/org/elasticsearch/common/joda/Joda.java +++ b/src/main/java/org/elasticsearch/common/joda/Joda.java @@ -41,6 +41,13 @@ public class Joda { * Parses a joda based pattern, including some named ones (similar to the built in Joda ISO ones). */ public static FormatDateTimeFormatter forPattern(String input, Locale locale) { + if (Strings.hasLength(input)) { + input = input.trim(); + } + if (input == null || input.length() == 0) { + throw new IllegalArgumentException("No date pattern provided"); + } + DateTimeFormatter formatter; if ("basicDate".equals(input) || "basic_date".equals(input)) { formatter = ISODateTimeFormat.basicDate(); @@ -126,20 +133,33 @@ public class Joda { formatter = ISODateTimeFormat.yearMonth(); } else if ("yearMonthDay".equals(input) || "year_month_day".equals(input)) { formatter = ISODateTimeFormat.yearMonthDay(); - } else { - String[] formats = Strings.delimitedListToStringArray(input, "||"); - if (formats == null || formats.length == 1) { - formatter = DateTimeFormat.forPattern(input); - } else { + } else if (Strings.hasLength(input) && input.contains("||")) { + String[] formats = Strings.delimitedListToStringArray(input, "||"); DateTimeParser[] parsers = new DateTimeParser[formats.length]; - for (int i = 0; i < formats.length; i++) { - parsers[i] = DateTimeFormat.forPattern(formats[i]).withZone(DateTimeZone.UTC).getParser(); + + if (formats.length == 1) { + formatter = forPattern(input, locale).parser(); + } else { + DateTimeFormatter dateTimeFormatter = null; + for (int i = 0; i < formats.length; i++) { + DateTimeFormatter currentFormatter = forPattern(formats[i], locale).parser(); + if (dateTimeFormatter == null) { + dateTimeFormatter = currentFormatter; + } + parsers[i] = currentFormatter.getParser(); + } + + DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder().append(dateTimeFormatter.withZone(DateTimeZone.UTC).getPrinter(), parsers); + formatter = builder.toFormatter(); } - DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder() - .append(DateTimeFormat.forPattern(formats[0]).withZone(DateTimeZone.UTC).getPrinter(), parsers); - formatter = builder.toFormatter(); + } else { + try { + formatter = DateTimeFormat.forPattern(input); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("Invalid format: [" + input + "]: " + e.getMessage(), e); } } + return new FormatDateTimeFormatter(input, formatter.withZone(DateTimeZone.UTC), locale); } diff --git a/src/test/java/org/elasticsearch/test/unit/deps/joda/SimpleJodaTests.java b/src/test/java/org/elasticsearch/test/unit/deps/joda/SimpleJodaTests.java index 4fbb7c840be..55c6f426ba5 100644 --- a/src/test/java/org/elasticsearch/test/unit/deps/joda/SimpleJodaTests.java +++ b/src/test/java/org/elasticsearch/test/unit/deps/joda/SimpleJodaTests.java @@ -30,7 +30,10 @@ import org.testng.annotations.Test; import java.util.Date; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.testng.AssertJUnit.fail; /** * @@ -145,10 +148,41 @@ public class SimpleJodaTests { public void testMultipleFormats() { FormatDateTimeFormatter formatter = Joda.forPattern("yyyy/MM/dd HH:mm:ss||yyyy/MM/dd"); long millis = formatter.parser().parseMillis("1970/01/01 00:00:00"); - millis = formatter.parser().parseMillis("1970/01/01"); -// System.out.println("" + millis); + assertThat("1970/01/01 00:00:00", is(formatter.printer().print(millis))); + } - System.out.println(formatter.printer().print(millis)); + @Test + public void testMultipleDifferentFormats() { + FormatDateTimeFormatter formatter = Joda.forPattern("yyyy/MM/dd HH:mm:ss||yyyy/MM/dd"); + String input = "1970/01/01 00:00:00"; + long millis = formatter.parser().parseMillis(input); + assertThat(input, is(formatter.printer().print(millis))); + + Joda.forPattern("yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||dateOptionalTime"); + Joda.forPattern("dateOptionalTime||yyyy/MM/dd HH:mm:ss||yyyy/MM/dd"); + Joda.forPattern("yyyy/MM/dd HH:mm:ss||dateOptionalTime||yyyy/MM/dd"); + Joda.forPattern("date_time||date_time_no_millis"); + Joda.forPattern(" date_time || date_time_no_millis"); + } + + @Test + public void testInvalidPatterns() { + expectInvalidPattern("does_not_exist_pattern", "Invalid format: [does_not_exist_pattern]: Illegal pattern component: o"); + expectInvalidPattern("OOOOO", "Invalid format: [OOOOO]: Illegal pattern component: OOOOO"); + expectInvalidPattern(null, "No date pattern provided"); + expectInvalidPattern("", "No date pattern provided"); + expectInvalidPattern(" ", "No date pattern provided"); + expectInvalidPattern("||date_time_no_millis", "No date pattern provided"); + expectInvalidPattern("date_time_no_millis||", "No date pattern provided"); + } + + private void expectInvalidPattern(String pattern, String errorMessage) { + try { + Joda.forPattern(pattern); + fail("Pattern " + pattern + " should have thrown an exception but did not"); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), containsString(errorMessage)); + } } @Test