Browse Source

Support full range of Java Long for epoch DateTime

Remove the arbitrary limit on epoch_millis and epoch_seconds of 13 and 10
characters, respectively. Instead allow any character combination that can
be converted to a Java Long.

Update the docs to reflect this change.
G. Richard Bellamy 9 years ago
parent
commit
cf54903580

+ 3 - 9
core/src/main/java/org/elasticsearch/common/joda/Joda.java

@@ -321,20 +321,15 @@ public class Joda {
 
 
     public static class EpochTimeParser implements DateTimeParser {
     public static class EpochTimeParser implements DateTimeParser {
 
 
-        private static final Pattern MILLI_SECOND_PRECISION_PATTERN = Pattern.compile("^-?\\d{1,13}$");
-        private static final Pattern SECOND_PRECISION_PATTERN = Pattern.compile("^-?\\d{1,10}$");
-
         private final boolean hasMilliSecondPrecision;
         private final boolean hasMilliSecondPrecision;
-        private final Pattern pattern;
 
 
         public EpochTimeParser(boolean hasMilliSecondPrecision) {
         public EpochTimeParser(boolean hasMilliSecondPrecision) {
             this.hasMilliSecondPrecision = hasMilliSecondPrecision;
             this.hasMilliSecondPrecision = hasMilliSecondPrecision;
-            this.pattern = hasMilliSecondPrecision ? MILLI_SECOND_PRECISION_PATTERN : SECOND_PRECISION_PATTERN;
         }
         }
 
 
         @Override
         @Override
         public int estimateParsedLength() {
         public int estimateParsedLength() {
-            return hasMilliSecondPrecision ? 13 : 10;
+            return hasMilliSecondPrecision ? 19 : 16;
         }
         }
 
 
         @Override
         @Override
@@ -344,8 +339,7 @@ public class Joda {
 
 
             if ((isPositive && isTooLong) ||
             if ((isPositive && isTooLong) ||
                 // timestamps have to have UTC timezone
                 // timestamps have to have UTC timezone
-                bucket.getZone() != DateTimeZone.UTC ||
-                pattern.matcher(text).matches() == false) {
+                bucket.getZone() != DateTimeZone.UTC) {
                 return -1;
                 return -1;
             }
             }
 
 
@@ -378,7 +372,7 @@ public class Joda {
 
 
         @Override
         @Override
         public int estimatePrintedLength() {
         public int estimatePrintedLength() {
-            return hasMilliSecondPrecision ? 13 : 10;
+            return hasMilliSecondPrecision ? 19 : 16;
         }
         }
 
 
         @Override
         @Override

+ 2 - 0
core/src/test/java/org/elasticsearch/common/joda/DateMathParserTests.java

@@ -196,6 +196,8 @@ public class DateMathParserTests extends ESTestCase {
 
 
     public void testTimestamps() {
     public void testTimestamps() {
         assertDateMathEquals("1418248078000", "2014-12-10T21:47:58.000");
         assertDateMathEquals("1418248078000", "2014-12-10T21:47:58.000");
+        assertDateMathEquals("32484216259000", "2999-05-20T17:24:19.000");
+        assertDateMathEquals("253382837059000", "9999-05-20T17:24:19.000");
 
 
         // datemath still works on timestamps
         // datemath still works on timestamps
         assertDateMathEquals("1418248078000||/m", "2014-12-10T21:47:00.000");
         assertDateMathEquals("1418248078000||/m", "2014-12-10T21:47:00.000");

+ 8 - 2
core/src/test/java/org/elasticsearch/deps/joda/SimpleJodaTests.java

@@ -289,16 +289,18 @@ public class SimpleJodaTests extends ESTestCase {
             formatter.parser().parseDateTime("-100000000");
             formatter.parser().parseDateTime("-100000000");
             formatter.parser().parseDateTime("-999999999999");
             formatter.parser().parseDateTime("-999999999999");
             formatter.parser().parseDateTime("-1234567890123");
             formatter.parser().parseDateTime("-1234567890123");
+            formatter.parser().parseDateTime("-1234567890123456789");
         } else {
         } else {
             formatter.parser().parseDateTime("-100000000");
             formatter.parser().parseDateTime("-100000000");
             formatter.parser().parseDateTime("-1234567890");
             formatter.parser().parseDateTime("-1234567890");
+            formatter.parser().parseDateTime("-1234567890123456");
         }
         }
     }
     }
 
 
     public void testForInvalidDatesInEpochSecond() {
     public void testForInvalidDatesInEpochSecond() {
         FormatDateTimeFormatter formatter = Joda.forPattern("epoch_second");
         FormatDateTimeFormatter formatter = Joda.forPattern("epoch_second");
         try {
         try {
-            formatter.parser().parseDateTime(randomFrom("invalid date", "12345678901", "12345678901234"));
+            formatter.parser().parseDateTime(randomFrom("invalid date", "12345678901234567", "12345678901234567890"));
             fail("Expected IllegalArgumentException");
             fail("Expected IllegalArgumentException");
         } catch (IllegalArgumentException e) {
         } catch (IllegalArgumentException e) {
             assertThat(e.getMessage(), containsString("Invalid format"));
             assertThat(e.getMessage(), containsString("Invalid format"));
@@ -308,7 +310,7 @@ public class SimpleJodaTests extends ESTestCase {
     public void testForInvalidDatesInEpochMillis() {
     public void testForInvalidDatesInEpochMillis() {
         FormatDateTimeFormatter formatter = Joda.forPattern("epoch_millis");
         FormatDateTimeFormatter formatter = Joda.forPattern("epoch_millis");
         try {
         try {
-            formatter.parser().parseDateTime(randomFrom("invalid date", "12345678901234"));
+            formatter.parser().parseDateTime(randomFrom("invalid date", "12345678901234567890"));
             fail("Expected IllegalArgumentException");
             fail("Expected IllegalArgumentException");
         } catch (IllegalArgumentException e) {
         } catch (IllegalArgumentException e) {
             assertThat(e.getMessage(), containsString("Invalid format"));
             assertThat(e.getMessage(), containsString("Invalid format"));
@@ -350,6 +352,8 @@ public class SimpleJodaTests extends ESTestCase {
         assertThat(dateTime.getMillis(), is(1234567890456L));
         assertThat(dateTime.getMillis(), is(1234567890456L));
         dateTime = formatter.parser().parseDateTime("1234567890789");
         dateTime = formatter.parser().parseDateTime("1234567890789");
         assertThat(dateTime.getMillis(), is(1234567890789L));
         assertThat(dateTime.getMillis(), is(1234567890789L));
+        dateTime = formatter.parser().parseDateTime("1234567890123456789");
+        assertThat(dateTime.getMillis(), is(1234567890123456789L));
 
 
         FormatDateTimeFormatter secondsFormatter = Joda.forPattern("epoch_second");
         FormatDateTimeFormatter secondsFormatter = Joda.forPattern("epoch_second");
         DateTime secondsDateTime = secondsFormatter.parser().parseDateTime("1234567890");
         DateTime secondsDateTime = secondsFormatter.parser().parseDateTime("1234567890");
@@ -358,6 +362,8 @@ public class SimpleJodaTests extends ESTestCase {
         assertThat(secondsDateTime.getMillis(), is(1234567890000L));
         assertThat(secondsDateTime.getMillis(), is(1234567890000L));
         secondsDateTime = secondsFormatter.parser().parseDateTime("1234567890");
         secondsDateTime = secondsFormatter.parser().parseDateTime("1234567890");
         assertThat(secondsDateTime.getMillis(), is(1234567890000L));
         assertThat(secondsDateTime.getMillis(), is(1234567890000L));
+        secondsDateTime = secondsFormatter.parser().parseDateTime("1234567890123456");
+        assertThat(secondsDateTime.getMillis(), is(1234567890123456000L));
     }
     }
 
 
     public void testThatDefaultFormatterChecksForCorrectYearLength() throws Exception {
     public void testThatDefaultFormatterChecksForCorrectYearLength() throws Exception {

+ 4 - 6
docs/reference/mapping/params/format.asciidoc

@@ -57,16 +57,14 @@ The following tables lists all the defaults ISO formats supported:
 `epoch_millis`::
 `epoch_millis`::
 
 
     A formatter for the number of milliseconds since the epoch. Note, that
     A formatter for the number of milliseconds since the epoch. Note, that
-    this timestamp allows a max length of 13 chars, so only dates between 1653
-    and 2286 are supported. You should use a different date formatter in
-    that case.
+    this timestamp is subject to the limits of a Java `Long.MIN_VALUE` and
+    `Long.MAX_VALUE`.
 
 
 `epoch_second`::
 `epoch_second`::
 
 
     A formatter for the number of seconds since the epoch. Note, that this
     A formatter for the number of seconds since the epoch. Note, that this
-    timestamp allows a max length of 10 chars, so only dates between 1653 and
-    2286 are supported. You should use a different date formatter in that
-    case.
+    timestamp is subject to the limits of a Java `Long.MIN_VALUE` and `Long.
+    MAX_VALUE` divided by 1000 (the number of milliseconds in a second).
 
 
 [[strict-date-time]]`date_optional_time` or `strict_date_optional_time`::
 [[strict-date-time]]`date_optional_time` or `strict_date_optional_time`::