From 6a76afa38ddf64d3517286b2c33eec3317cff004 Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Wed, 1 Aug 2018 20:35:11 +0300 Subject: [PATCH 01/17] SOLR-12586: ParsingFieldUpdateProcessor use java.time instead of joda-time --- .../ParseDateFieldUpdateProcessorFactory.java | 51 +++++-- ...config-parsing-update-processor-chains.xml | 40 +++--- .../ParsingFieldUpdateProcessorsTest.java | 124 ++++++++++-------- solr/licenses/joda-time-NOTICE.txt | 5 - 4 files changed, 129 insertions(+), 91 deletions(-) delete mode 100644 solr/licenses/joda-time-NOTICE.txt diff --git a/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java b/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java index 234b48bc15e4..1cf13b9b36fa 100644 --- a/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java +++ b/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java @@ -17,11 +17,23 @@ package org.apache.solr.update.processor; import java.lang.invoke.MethodHandles; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.DateTimeParseException; +import java.time.temporal.TemporalAccessor; import java.util.Collection; import java.util.Date; import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; +import java.util.TimeZone; import org.apache.commons.lang.LocaleUtils; import org.apache.solr.common.util.NamedList; @@ -31,10 +43,6 @@ import org.apache.solr.schema.DateValueFieldType; import org.apache.solr.schema.FieldType; import org.apache.solr.schema.IndexSchema; -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,8 +65,8 @@ *

*

* One or more date "format" specifiers must be specified. See - * Joda-time's DateTimeFormat javadocs for a description of format strings. + * Java 8's DateTimeFormatter javadocs for a description of format strings. *

*

* A default time zone name or offset may optionally be specified for those dates @@ -115,9 +123,10 @@ protected Object mutateValue(Object srcVal) { for (Map.Entry format : formats.entrySet()) { DateTimeFormatter parser = format.getValue(); try { - DateTime dateTime = parser.parseDateTime(srcStringVal); - return dateTime.withZone(DateTimeZone.UTC).toDate(); - } catch (IllegalArgumentException e) { + TemporalAccessor parsedTemporalDate = parser.parseBest(srcStringVal, OffsetDateTime::from, + ZonedDateTime::from, LocalDateTime::from, LocalDate::from, Instant::from); + return temporalToDate(parsedTemporalDate, parser.getZone()); + } catch (DateTimeParseException e) { log.debug("value '{}' is not parseable with format '{}'", new Object[] { srcStringVal, format.getKey() }); } @@ -144,15 +153,19 @@ public void init(NamedList args) { } Object defaultTimeZoneParam = args.remove(DEFAULT_TIME_ZONE_PARAM); - DateTimeZone defaultTimeZone = DateTimeZone.UTC; + ZoneId defaultTimeZone = ZoneOffset.UTC; if (null != defaultTimeZoneParam) { - defaultTimeZone = DateTimeZone.forID(defaultTimeZoneParam.toString()); + TimeZone.getTimeZone(defaultTimeZoneParam.toString()); + defaultTimeZone = ZoneId.of(defaultTimeZoneParam.toString()); } Collection formatsParam = args.removeConfigArgs(FORMATS_PARAM); if (null != formatsParam) { for (String value : formatsParam) { - formats.put(value, DateTimeFormat.forPattern(value).withZone(defaultTimeZone).withLocale(locale)); + DateTimeFormatter formatter = new DateTimeFormatterBuilder().parseCaseInsensitive() + .appendPattern(value).toFormatter(locale).withZone(defaultTimeZone); + formats.put(value, formatter); + // formats.put(value, DateTimeFormat.forPattern(value).withZone(defaultTimeZone).withLocale(locale)); } } super.init(args); @@ -172,4 +185,18 @@ public void init(NamedList args) { return (null == type) || type instanceof DateValueFieldType; }; } + + private Date temporalToDate(TemporalAccessor in, ZoneId timeZoneId) { + if(in instanceof OffsetDateTime) { + return Date.from(((OffsetDateTime) in).toInstant()); + } else if(in instanceof ZonedDateTime) { + return Date.from(((ZonedDateTime) in).withZoneSameInstant(timeZoneId).toInstant()); + } else if(in instanceof LocalDateTime) { + return Date.from(((LocalDateTime) in).atZone(timeZoneId).toInstant()); + } else if(in instanceof Instant) { + return Date.from((Instant) in); + } else { + return Date.from(((LocalDate) in).atStartOfDay(timeZoneId).toInstant()); + } + } } diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml index 5930d37d7756..da359b8db06b 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml @@ -29,35 +29,35 @@ - yyyy-MM-dd'T'HH:mm:ss.SSSZ + yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ - yyyy-MM-dd'T'HH:mm:ss.SSSZ + yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ false - yyyy-MM-dd'T'HH:mm:ss.SSSZ + yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ solr.DatePointField - yyyy-MM-dd'T'HH:mm:ss.SSSZ + yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ solr.TrieDateField - yyyy-MM-dd'T'HH:mm:ss.SSSZ + yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ @@ -65,7 +65,7 @@ America/New_York en_US - yyyy-MM-dd'T'HH:mm:ss.SSSZ + yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ yyyy-MM-dd'T'HH:mm:ss.SSS @@ -75,7 +75,7 @@ America/Los_Angeles - MM/dd/yyyy + M/d/yyyy @@ -85,30 +85,30 @@ UTC en_US - yyyy-MM-dd'T'HH:mm:ss.SSSZ - yyyy-MM-dd'T'HH:mm:ss,SSSZ + yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ + yyyy-MM-dd'T'HH:mm:ss,SSSZZZZZ yyyy-MM-dd'T'HH:mm:ss.SSS yyyy-MM-dd'T'HH:mm:ss,SSS - yyyy-MM-dd'T'HH:mm:ssZ + yyyy-MM-dd'T'HH:mm:ssZZZZZ yyyy-MM-dd'T'HH:mm:ss - yyyy-MM-dd'T'HH:mmZ + yyyy-MM-dd'T'HH:mmZZZZZ yyyy-MM-dd'T'HH:mm - yyyy-MM-dd HH:mm:ss.SSSZ - yyyy-MM-dd HH:mm:ss,SSSZ + yyyy-MM-dd HH:mm:ss.SSSZZZZZ + yyyy-MM-dd HH:mm:ss,SSSZZZZZ yyyy-MM-dd HH:mm:ss.SSS yyyy-MM-dd HH:mm:ss,SSS - yyyy-MM-dd HH:mm:ssZ + yyyy-MM-dd HH:mm:ssZZZZZ yyyy-MM-dd HH:mm:ss - yyyy-MM-dd HH:mmZ + yyyy-MM-dd HH:mmZZZZZ yyyy-MM-dd HH:mm yyyy-MM-dd hh:mm a yyyy-MM-dd hh:mma yyyy-MM-dd - EEE MMM dd HH:mm:ss Z yyyy - EEE MMM dd HH:mm:ss yyyy Z + EEE MMM dd HH:mm:ss ZZZ yyyy + EEE MMM dd HH:mm:ss yyyy ZZZZZ EEE MMM dd HH:mm:ss yyyy - EEE, dd MMM yyyy HH:mm:ss Z - EEEE, dd-MMM-yy HH:mm:ss Z + EEE, dd MMM yyyy HH:mm:ss ZZZZZ + EEEE, dd-MMM-yy HH:mm:ss ZZZZZ EEEE, MMMM dd, yyyy MMMM dd, yyyy MMM. dd, yyyy @@ -229,7 +229,7 @@ yyyy-MM-dd - yyyy-MM-dd'T'HH:mm:ss.SSSZ + yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ yyyy-MM-dd'T'HH:mm diff --git a/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java b/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java index 3aeb1fbfccfb..b5af7d5110b6 100644 --- a/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java +++ b/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java @@ -18,13 +18,17 @@ import org.apache.solr.common.SolrInputDocument; import org.apache.solr.schema.IndexSchema; -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; -import org.joda.time.format.ISODateTimeFormat; import org.junit.BeforeClass; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAccessor; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -50,10 +54,9 @@ public void testParseDateRoundTrip() throws Exception { String dateString = "2010-11-12T13:14:15.168Z"; SolrInputDocument d = processAdd("parse-date", doc(f("id", "9"), f("date_dt", dateString))); assertNotNull(d); - DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime(); - DateTime dateTime = dateTimeFormatter.parseDateTime(dateString); + ZonedDateTime localDateTime = ZonedDateTime.parse(dateString, DateTimeFormatter.ISO_DATE_TIME); assertTrue(d.getFieldValue("date_dt") instanceof Date); - assertEquals(dateTime.getMillis(), ((Date) d.getFieldValue("date_dt")).getTime()); + assertEquals(localDateTime.withZoneSameInstant(ZoneOffset.UTC).toInstant().toEpochMilli(), ((Date) d.getFieldValue("date_dt")).getTime()); assertU(commit()); assertQ(req("id:9"), "//date[@name='date_dt'][.='" + dateString + "']"); } @@ -64,10 +67,9 @@ public void testParseTrieDateRoundTrip() throws Exception { String dateString = "2010-11-12T13:14:15.168Z"; SolrInputDocument d = processAdd("parse-date", doc(f("id", "39"), f("date_tdt", dateString))); assertNotNull(d); - DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime(); - DateTime dateTime = dateTimeFormatter.parseDateTime(dateString); + ZonedDateTime localDateTime = ZonedDateTime.parse(dateString, DateTimeFormatter.ISO_DATE_TIME); assertTrue(d.getFieldValue("date_tdt") instanceof Date); - assertEquals(dateTime.getMillis(), ((Date) d.getFieldValue("date_tdt")).getTime()); + assertEquals(localDateTime.withZoneSameInstant(ZoneOffset.UTC).toInstant().toEpochMilli(), ((Date) d.getFieldValue("date_tdt")).getTime()); assertU(commit()); assertQ(req("id:39"), "//date[@name='date_tdt'][.='" + dateString + "']"); } @@ -77,14 +79,13 @@ public void testParseDateFieldNotInSchema() throws Exception { IndexSchema schema = h.getCore().getLatestSchema(); assertNull(schema.getFieldOrNull("not_in_schema")); String dateString = "2010-11-12T13:14:15.168Z"; - DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime(); - DateTime dateTime = dateTimeFormatter.parseDateTime(dateString); + ZonedDateTime localDateTime = ZonedDateTime.parse(dateString, DateTimeFormatter.ISO_DATE_TIME); SolrInputDocument d = processAdd("parse-date-no-run-processor", doc(f("id", "18"), f("not_in_schema", dateString))); assertNotNull(d); assertTrue(d.getFieldValue("not_in_schema") instanceof Date); - assertEquals(dateTime.getMillis(), ((Date)d.getFieldValue("not_in_schema")).getTime()); + assertEquals(localDateTime.withZoneSameInstant(ZoneOffset.UTC).toInstant().toEpochMilli(), ((Date)d.getFieldValue("not_in_schema")).getTime()); d = processAdd("parse-date-no-run-processor", doc(f("id", "36"), f("not_in_schema", "not a date", dateString))); @@ -116,12 +117,12 @@ public void testParseDateNonUTCdefaultTimeZoneRoundTrip() throws Exception { ("parse-date-non-UTC-defaultTimeZone", doc(f("id", "99"), f("dateUTC_dt", dateStringUTC), f("dateNoTimeZone_dt", dateStringNoTimeZone))); assertNotNull(d); - String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; - DateTimeFormatter dateTimeFormatterUTC = DateTimeFormat.forPattern(pattern); - DateTime dateTimeUTC = dateTimeFormatterUTC.parseDateTime(dateStringUTC); + String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"; + DateTimeFormatter UTCForamatter = DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.of("America/New_York")); + OffsetDateTime dateTimeOffsetUTC = OffsetDateTime.parse(dateStringUTC, UTCForamatter); assertTrue(d.getFieldValue("dateUTC_dt") instanceof Date); assertTrue(d.getFieldValue("dateNoTimeZone_dt") instanceof Date); - assertEquals(dateTimeUTC.getMillis(), ((Date) d.getFieldValue("dateUTC_dt")).getTime()); + assertEquals(dateTimeOffsetUTC.toInstant().toEpochMilli(), ((Date) d.getFieldValue("dateUTC_dt")).getTime()); assertU(commit()); assertQ(req("id:99") ,"//date[@name='dateUTC_dt'][.='" + dateStringUTC + "']" @@ -132,22 +133,20 @@ public void testParseDateExplicitNotInSchemaSelector() throws Exception { IndexSchema schema = h.getCore().getLatestSchema(); assertNull(schema.getFieldOrNull("not_in_schema")); String dateString = "2010-11-12T13:14:15.168Z"; - DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime(); - DateTime dateTime = dateTimeFormatter.parseDateTime(dateString); + ZonedDateTime localDateTime = ZonedDateTime.parse(dateString, DateTimeFormatter.ISO_DATE_TIME); SolrInputDocument d = processAdd("parse-date-explicit-not-in-schema-selector-no-run-processor", doc(f("id", "88"), f("not_in_schema", dateString))); assertNotNull(d); assertTrue(d.getFieldValue("not_in_schema") instanceof Date); - assertEquals(dateTime.getMillis(), ((Date)d.getFieldValue("not_in_schema")).getTime()); + assertEquals(localDateTime.withZoneSameInstant(ZoneOffset.UTC).toInstant().toEpochMilli(), ((Date)d.getFieldValue("not_in_schema")).getTime()); } public void testParseDateExplicitTypeClassSelector() throws Exception { IndexSchema schema = h.getCore().getLatestSchema(); assertNotNull(schema.getFieldOrNull("date_dt")); String dateString = "2010-11-12T13:14:15.168Z"; - DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime(); - DateTime dateTime = dateTimeFormatter.parseDateTime(dateString); + ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateString, DateTimeFormatter.ISO_DATE_TIME); SolrInputDocument d; if (schema.getField("date_dt").getType().isPointField()) { d = processAdd("parse-date-explicit-typeclass-point-selector-no-run-processor", @@ -159,7 +158,7 @@ public void testParseDateExplicitTypeClassSelector() throws Exception { assertNotNull(d); assertTrue(d.getFieldValue("date_dt") instanceof Date); - assertEquals(dateTime.getMillis(), ((Date)d.getFieldValue("date_dt")).getTime()); + assertEquals(zonedDateTime.withZoneSameInstant(ZoneOffset.UTC).toInstant().toEpochMilli(), ((Date)d.getFieldValue("date_dt")).getTime()); } public void testParseUSPacificDate() throws Exception { @@ -171,36 +170,36 @@ public void testParseUSPacificDate() throws Exception { doc(f("id", "288"), f("not_in_schema", dateString))); assertNotNull(d); assertTrue(d.getFieldValue("not_in_schema") instanceof Date); - assertEquals(dateStringUTC, - (new DateTime(((Date)d.getFieldValue("not_in_schema")).getTime(),DateTimeZone.UTC)).toString()); + assertEquals(dateStringUTC, + (ZonedDateTime.ofInstant(((Date)d.getFieldValue("not_in_schema")).toInstant(), ZoneOffset.UTC)).format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"))); } public void testParseDateFormats() throws Exception { String[] formatExamples = { - "yyyy-MM-dd'T'HH:mm:ss.SSSZ", "2010-01-15T00:00:00.000Z", - "yyyy-MM-dd'T'HH:mm:ss,SSSZ", "2010-01-15T00:00:00,000Z", + "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ", "2010-01-15T00:00:00.000Z", + "yyyy-MM-dd'T'HH:mm:ss,SSSZZZZZ", "2010-01-15T00:00:00,000Z", "yyyy-MM-dd'T'HH:mm:ss.SSS", "2010-01-15T00:00:00.000", "yyyy-MM-dd'T'HH:mm:ss,SSS", "2010-01-15T00:00:00,000", - "yyyy-MM-dd'T'HH:mm:ssZ", "2010-01-15T00:00:00Z", + "yyyy-MM-dd'T'HH:mm:ssZZZZZ", "2010-01-15T00:00:00Z", "yyyy-MM-dd'T'HH:mm:ss", "2010-01-15T00:00:00", - "yyyy-MM-dd'T'HH:mmZ", "2010-01-15T00:00Z", + "yyyy-MM-dd'T'HH:mmZZZZZ", "2010-01-15T00:00Z", "yyyy-MM-dd'T'HH:mm", "2010-01-15T00:00", - "yyyy-MM-dd HH:mm:ss.SSSZ", "2010-01-15 00:00:00.000Z", - "yyyy-MM-dd HH:mm:ss,SSSZ", "2010-01-15 00:00:00,000Z", + "yyyy-MM-dd HH:mm:ss.SSSZZZZZ", "2010-01-15 00:00:00.000Z", + "yyyy-MM-dd HH:mm:ss,SSSZZZZZ", "2010-01-15 00:00:00,000Z", "yyyy-MM-dd HH:mm:ss.SSS", "2010-01-15 00:00:00.000", "yyyy-MM-dd HH:mm:ss,SSS", "2010-01-15 00:00:00,000", - "yyyy-MM-dd HH:mm:ssZ", "2010-01-15 00:00:00Z", + "yyyy-MM-dd HH:mm:ssZZZZZ", "2010-01-15 00:00:00Z", "yyyy-MM-dd HH:mm:ss", "2010-01-15 00:00:00", - "yyyy-MM-dd HH:mmZ", "2010-01-15 00:00Z", + "yyyy-MM-dd HH:mmZZZZZ", "2010-01-15 00:00Z", "yyyy-MM-dd HH:mm", "2010-01-15 00:00", "yyyy-MM-dd hh:mm a", "2010-01-15 12:00 AM", "yyyy-MM-dd hh:mma", "2010-01-15 12:00AM", "yyyy-MM-dd", "2010-01-15", - "EEE MMM dd HH:mm:ss Z yyyy", "Fri Jan 15 00:00:00 +0000 2010", - "EEE MMM dd HH:mm:ss yyyy Z", "Fri Jan 15 00:00:00 2010 +00:00", + "EEE MMM dd HH:mm:ss ZZZ yyyy", "Fri Jan 15 00:00:00 +0000 2010", + "EEE MMM dd HH:mm:ss yyyy ZZZZZ", "Fri Jan 15 00:00:00 2010 +00:00", "EEE MMM dd HH:mm:ss yyyy", "Fri Jan 15 00:00:00 2010", - "EEE, dd MMM yyyy HH:mm:ss Z", "Fri, 15 Jan 2010 00:00:00 +00:00", - "EEEE, dd-MMM-yy HH:mm:ss Z", "Friday, 15-Jan-10 00:00:00 +00:00", + "EEE, dd MMM yyyy HH:mm:ss ZZZZZ", "Fri, 15 Jan 2010 00:00:00 +00:00", + "EEEE, dd-MMM-yy HH:mm:ss ZZZZZ", "Friday, 15-Jan-10 00:00:00 +00:00", "EEEE, MMMM dd, yyyy", "Friday, January 15, 2010", "MMMM dd, yyyy", "January 15, 2010", "MMM. dd, yyyy", "Jan. 15, 2010" @@ -209,9 +208,9 @@ public void testParseDateFormats() throws Exception { IndexSchema schema = h.getCore().getLatestSchema(); assertNotNull(schema.getFieldOrNull("dateUTC_dt")); // should match "*_dt" dynamic field - String dateTimePattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; - DateTimeFormatter dateTimeFormatterUTC = DateTimeFormat.forPattern(dateTimePattern); - DateTime dateTimeUTC = dateTimeFormatterUTC.parseDateTime(formatExamples[1]); + String dateTimePattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"; + DateTimeFormatter UTCDateTimeFormatter = DateTimeFormatter.ofPattern(dateTimePattern); + ZonedDateTime UTCDateTIme = ZonedDateTime.parse(formatExamples[1], UTCDateTimeFormatter); for (int i = 0 ; i < formatExamples.length ; i += 2) { String format = formatExamples[i]; @@ -220,10 +219,10 @@ public void testParseDateFormats() throws Exception { SolrInputDocument d = processAdd("parse-date-UTC-defaultTimeZone-no-run-processor", doc(f("id", id), f("dateUTC_dt", dateString))); assertNotNull(d); - assertTrue("date '" + dateString + "' with format '" + format + "' is not mutated to a Date", - d.getFieldValue("dateUTC_dt") instanceof Date); + assertTrue("index: " + i + " date '" + dateString + "' with format '" + format + + "' is not mutated to a Date", d.getFieldValue("dateUTC_dt") instanceof Date); assertEquals("date '" + dateString + "' with format '" + format + "' mismatched milliseconds", - dateTimeUTC.getMillis(), ((Date)d.getFieldValue("dateUTC_dt")).getTime()); + UTCDateTIme.toInstant().toEpochMilli(), ((Date)d.getFieldValue("dateUTC_dt")).getTime()); } } @@ -232,23 +231,23 @@ public void testParseFrenchDate() throws Exception { assertNull(schema.getFieldOrNull("not_in_schema")); String frenchDateString = "le vendredi 15 janvier 2010"; String dateString = "2010-01-15T00:00:00.000Z"; - DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime(); - DateTime dateTime = dateTimeFormatter.parseDateTime(dateString); + LocalDateTime localDateTime = LocalDateTime.parse(dateString, DateTimeFormatter.ISO_DATE_TIME); SolrInputDocument d = processAdd("parse-french-date-UTC-defaultTimeZone-no-run-processor", doc(f("id", "88"), f("not_in_schema", frenchDateString))); assertNotNull(d); assertTrue(d.getFieldValue("not_in_schema") instanceof Date); - assertEquals(dateTime.getMillis(), ((Date)d.getFieldValue("not_in_schema")).getTime()); + assertEquals(localDateTime.atZone(ZoneOffset.UTC).toInstant().toEpochMilli(), ((Date)d.getFieldValue("not_in_schema")).getTime()); } public void testFailedParseMixedDate() throws Exception { IndexSchema schema = h.getCore().getLatestSchema(); assertNull(schema.getFieldOrNull("not_in_schema")); - DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateOptionalTimeParser().withZoneUTC(); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm][:ss.SSSZZZZZ]").withZone(ZoneOffset.UTC); Map mixed = new HashMap<>(); String[] dateStrings = { "2020-05-13T18:47", "1989-12-14", "1682-07-22T18:33:00.000Z" }; for (String dateString : dateStrings) { - mixed.put(dateTimeFormatter.parseDateTime(dateString).toDate(), dateString); + mixed.put(temporalToDate(dateTimeFormatter.parseBest(dateString, OffsetDateTime::from, + ZonedDateTime::from, LocalDateTime::from, LocalDate::from, Instant::from), dateTimeFormatter.getZone()), dateString); } Double extraDouble = 29.554d; mixed.put(extraDouble, extraDouble); // Double-typed field value @@ -805,11 +804,12 @@ public void testCascadingParsers() throws Exception { longs.remove(o); } - DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateOptionalTimeParser().withZoneUTC(); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm][:ss.SSSZZZZZ]").withZone(ZoneOffset.UTC); Map dates = new HashMap<>(); String[] dateStrings = { "2020-05-13T18:47", "1989-12-14", "1682-07-22T18:33:00.000Z" }; for (String dateString : dateStrings) { - dates.put(dateTimeFormatter.parseDateTime(dateString).toDate(), dateString); + dates.put(temporalToDate(dateTimeFormatter.parseBest(dateString, OffsetDateTime::from, + ZonedDateTime::from, LocalDateTime::from, LocalDate::from, Instant::from), dateTimeFormatter.getZone()), dateString); } d = processAdd(chain, doc(f("id", "343"), f(fieldName, dates.values()))); assertNotNull(d); @@ -896,13 +896,15 @@ public void testCascadingParsers() throws Exception { } assertTrue(mixedBooleans.isEmpty()); - dateTimeFormatter = ISODateTimeFormat.dateOptionalTimeParser().withZoneUTC(); + dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm][:ss.SSSZZZZZ]").withZone(ZoneOffset.UTC); Map mixedDates = new HashMap<>(); dateStrings = new String[] { "2020-05-13T18:47", "1989-12-14", "1682-07-22T18:33:00.000Z" }; for (String dateString : dateStrings) { - mixedDates.put(dateTimeFormatter.parseDateTime(dateString).toDate(), dateString); + mixedDates.put(temporalToDate(dateTimeFormatter.parseBest(dateString, OffsetDateTime::from, + ZonedDateTime::from, LocalDateTime::from, LocalDate::from, Instant::from), dateTimeFormatter.getZone()), dateString); } - Date extraDate = dateTimeFormatter.parseDateTime("2003-04-24").toDate(); + Date extraDate = temporalToDate(dateTimeFormatter.parseBest("2003-04-24", OffsetDateTime::from, + ZonedDateTime::from, LocalDateTime::from, LocalDate::from, Instant::from), dateTimeFormatter.getZone()); mixedDates.put(extraDate, extraDate); // Date-typed field value d = processAdd(chain, doc(f("id", "3395"), f(fieldName, mixedDates.values()))); assertNotNull(d); @@ -912,4 +914,18 @@ public void testCascadingParsers() throws Exception { } assertTrue(mixedDates.isEmpty()); } + + private Date temporalToDate(TemporalAccessor in, ZoneId timeZoneId) { + if(in instanceof OffsetDateTime) { + return Date.from(((OffsetDateTime) in).toInstant()); + } else if(in instanceof ZonedDateTime) { + return Date.from(((ZonedDateTime) in).withZoneSameInstant(timeZoneId).toInstant()); + } else if(in instanceof LocalDateTime) { + return Date.from(((LocalDateTime) in).atZone(timeZoneId).toInstant()); + } else if(in instanceof Instant) { + return Date.from((Instant) in); + } else { + return Date.from(((LocalDate) in).atStartOfDay(timeZoneId).toInstant()); + } + } } diff --git a/solr/licenses/joda-time-NOTICE.txt b/solr/licenses/joda-time-NOTICE.txt deleted file mode 100644 index dffbcf31cacf..000000000000 --- a/solr/licenses/joda-time-NOTICE.txt +++ /dev/null @@ -1,5 +0,0 @@ -============================================================================= -= NOTICE file corresponding to section 4d of the Apache License Version 2.0 = -============================================================================= -This product includes software developed by -Joda.org (http://www.joda.org/). From 6b9f2c9e033129fed6fa4b5072a15f66992511db Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Wed, 1 Aug 2018 20:39:16 +0300 Subject: [PATCH 02/17] SOLR-12586: ConfigSetService use java.time instead of joda-time --- .../apache/solr/core/ConfigSetService.java | 9 ++++---- ...chemaFieldsUpdateProcessorFactoryTest.java | 22 +++++++++---------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/core/ConfigSetService.java b/solr/core/src/java/org/apache/solr/core/ConfigSetService.java index 13ac9ce1db4b..82db53262c67 100644 --- a/solr/core/src/java/org/apache/solr/core/ConfigSetService.java +++ b/solr/core/src/java/org/apache/solr/core/ConfigSetService.java @@ -21,6 +21,9 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.Locale; import java.util.concurrent.ExecutionException; @@ -33,8 +36,6 @@ import org.apache.solr.common.util.NamedList; import org.apache.solr.schema.IndexSchema; import org.apache.solr.schema.IndexSchemaFactory; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -212,12 +213,12 @@ public SchemaCaching(SolrResourceLoader loader, Path configSetBase) { super(loader, configSetBase); } - public static final DateTimeFormatter cacheKeyFormatter = DateTimeFormat.forPattern("yyyyMMddHHmmss"); + public static final DateTimeFormatter cacheKeyFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); public static String cacheName(Path schemaFile) throws IOException { long lastModified = Files.getLastModifiedTime(schemaFile).toMillis(); return String.format(Locale.ROOT, "%s:%s", - schemaFile.toString(), cacheKeyFormatter.print(lastModified)); + schemaFile.toString(), Instant.ofEpochMilli(lastModified).atZone(ZoneId.systemDefault()).format(cacheKeyFormatter)); } @Override diff --git a/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java b/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java index d1a3a535a48d..cb3887494465 100644 --- a/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java +++ b/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java @@ -17,6 +17,10 @@ package org.apache.solr.update.processor; import java.io.File; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.Collections; import java.util.Date; @@ -24,10 +28,6 @@ import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.schema.IndexSchema; -import org.joda.time.DateTime; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; -import org.joda.time.format.ISODateTimeFormat; import org.junit.After; import org.junit.Before; @@ -63,8 +63,8 @@ public void testSingleField() throws Exception { final String fieldName = "newfield1"; assertNull(schema.getFieldOrNull(fieldName)); String dateString = "2010-11-12T13:14:15.168Z"; - DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime(); - Date date = dateTimeFormatter.parseDateTime(dateString).toDate(); + LocalDateTime localDateTime = LocalDateTime.parse(dateString, DateTimeFormatter.ISO_DATE_TIME); + Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); SolrInputDocument d = processAdd("add-fields-no-run-processor", doc(f("id", "1"), f(fieldName, date))); assertNotNull(d); schema = h.getCore().getLatestSchema(); @@ -202,11 +202,11 @@ public void testParseAndAddMultipleFieldsRoundTrip() throws Exception { String field3String2 = "-5.28E-3"; Double field3Value2 = -5.28E-3; String field4String1 = "1999-04-17 17:42"; - DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm").withZoneUTC(); - DateTime dateTime = dateTimeFormatter.parseDateTime(field4String1); - Date field4Value1 = dateTime.toDate(); - DateTimeFormatter dateTimeFormatter2 = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss").withZoneUTC(); - String field4Value1String = dateTimeFormatter2.print(dateTime) + "Z"; + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").withZone(ZoneOffset.UTC); + LocalDateTime dateTime = LocalDateTime.parse(field4String1, dateTimeFormatter); + Date field4Value1 = Date.from(dateTime.atZone(ZoneOffset.UTC).toInstant()); + DateTimeFormatter dateTimeFormatter2 = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss").withZone(ZoneOffset.UTC); + String field4Value1String = dateTime.format(dateTimeFormatter2) + "Z"; SolrInputDocument d = processAdd ("parse-and-add-fields", doc(f("id", "6"), f(fieldName1, field1String1, field1String2, field1String3), From 7a036f7c3187c1219d0cce288ff629981b6d8479 Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Wed, 1 Aug 2018 20:39:51 +0300 Subject: [PATCH 03/17] SOLR-12586: remove joda-time from ant dependencies and licenses --- lucene/ivy-versions.properties | 1 - solr/core/ivy.xml | 1 - 2 files changed, 2 deletions(-) diff --git a/lucene/ivy-versions.properties b/lucene/ivy-versions.properties index 9d5303dfe21a..81ebb7ce1700 100644 --- a/lucene/ivy-versions.properties +++ b/lucene/ivy-versions.properties @@ -78,7 +78,6 @@ io.prometheus.version = 0.2.0 /javax.activation/activation = 1.1.1 /javax.servlet/javax.servlet-api = 3.1.0 -/joda-time/joda-time = 2.2 /junit/junit = 4.10 /mecab/mecab-ipadic = 2.7.0-20070801 diff --git a/solr/core/ivy.xml b/solr/core/ivy.xml index ee6fe80db731..5a0fd091301f 100644 --- a/solr/core/ivy.xml +++ b/solr/core/ivy.xml @@ -44,7 +44,6 @@ - From bef9d7c48dbe34bdb3f6e3581669b740850b0f25 Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Thu, 2 Aug 2018 02:13:39 +0300 Subject: [PATCH 04/17] SOLR-12586: use ZoneOffset.UTC in ConfigServiceSet --- solr/core/src/java/org/apache/solr/core/ConfigSetService.java | 4 ++-- .../processor/AddSchemaFieldsUpdateProcessorFactoryTest.java | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/core/ConfigSetService.java b/solr/core/src/java/org/apache/solr/core/ConfigSetService.java index 82db53262c67..3a1f9d724278 100644 --- a/solr/core/src/java/org/apache/solr/core/ConfigSetService.java +++ b/solr/core/src/java/org/apache/solr/core/ConfigSetService.java @@ -22,7 +22,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.time.Instant; -import java.time.ZoneId; +import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.Locale; import java.util.concurrent.ExecutionException; @@ -218,7 +218,7 @@ public SchemaCaching(SolrResourceLoader loader, Path configSetBase) { public static String cacheName(Path schemaFile) throws IOException { long lastModified = Files.getLastModifiedTime(schemaFile).toMillis(); return String.format(Locale.ROOT, "%s:%s", - schemaFile.toString(), Instant.ofEpochMilli(lastModified).atZone(ZoneId.systemDefault()).format(cacheKeyFormatter)); + schemaFile.toString(), Instant.ofEpochMilli(lastModified).atZone(ZoneOffset.UTC).format(cacheKeyFormatter)); } @Override diff --git a/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java b/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java index cb3887494465..b736f4630096 100644 --- a/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java +++ b/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java @@ -18,7 +18,6 @@ import java.io.File; import java.time.LocalDateTime; -import java.time.ZoneId; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.Collections; @@ -64,7 +63,7 @@ public void testSingleField() throws Exception { assertNull(schema.getFieldOrNull(fieldName)); String dateString = "2010-11-12T13:14:15.168Z"; LocalDateTime localDateTime = LocalDateTime.parse(dateString, DateTimeFormatter.ISO_DATE_TIME); - Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); + Date date = Date.from(localDateTime.atZone(ZoneOffset.UTC).toInstant()); SolrInputDocument d = processAdd("add-fields-no-run-processor", doc(f("id", "1"), f(fieldName, date))); assertNotNull(d); schema = h.getCore().getLatestSchema(); From 3a15630742ccbb7e2bee42a839bc79fd0d0023c4 Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Fri, 3 Aug 2018 09:29:08 +0300 Subject: [PATCH 05/17] SOLR-12586: parse date's using TemporalAccessor.query --- .../ParseDateFieldUpdateProcessorFactory.java | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java b/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java index 1cf13b9b36fa..8c94874c89a6 100644 --- a/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java +++ b/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java @@ -19,21 +19,19 @@ import java.lang.invoke.MethodHandles; import java.time.Instant; import java.time.LocalDate; -import java.time.LocalDateTime; import java.time.OffsetDateTime; import java.time.ZoneId; import java.time.ZoneOffset; -import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoField; import java.time.temporal.TemporalAccessor; import java.util.Collection; import java.util.Date; import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; -import java.util.TimeZone; import org.apache.commons.lang.LocaleUtils; import org.apache.solr.common.util.NamedList; @@ -123,9 +121,7 @@ protected Object mutateValue(Object srcVal) { for (Map.Entry format : formats.entrySet()) { DateTimeFormatter parser = format.getValue(); try { - TemporalAccessor parsedTemporalDate = parser.parseBest(srcStringVal, OffsetDateTime::from, - ZonedDateTime::from, LocalDateTime::from, LocalDate::from, Instant::from); - return temporalToDate(parsedTemporalDate, parser.getZone()); + return Date.from(parseInstant(parser, srcStringVal, parser.getZone())); } catch (DateTimeParseException e) { log.debug("value '{}' is not parseable with format '{}'", new Object[] { srcStringVal, format.getKey() }); @@ -155,7 +151,6 @@ public void init(NamedList args) { Object defaultTimeZoneParam = args.remove(DEFAULT_TIME_ZONE_PARAM); ZoneId defaultTimeZone = ZoneOffset.UTC; if (null != defaultTimeZoneParam) { - TimeZone.getTimeZone(defaultTimeZoneParam.toString()); defaultTimeZone = ZoneId.of(defaultTimeZoneParam.toString()); } @@ -165,7 +160,6 @@ public void init(NamedList args) { DateTimeFormatter formatter = new DateTimeFormatterBuilder().parseCaseInsensitive() .appendPattern(value).toFormatter(locale).withZone(defaultTimeZone); formats.put(value, formatter); - // formats.put(value, DateTimeFormat.forPattern(value).withZone(defaultTimeZone).withLocale(locale)); } } super.init(args); @@ -186,17 +180,19 @@ public void init(NamedList args) { }; } - private Date temporalToDate(TemporalAccessor in, ZoneId timeZoneId) { - if(in instanceof OffsetDateTime) { - return Date.from(((OffsetDateTime) in).toInstant()); - } else if(in instanceof ZonedDateTime) { - return Date.from(((ZonedDateTime) in).withZoneSameInstant(timeZoneId).toInstant()); - } else if(in instanceof LocalDateTime) { - return Date.from(((LocalDateTime) in).atZone(timeZoneId).toInstant()); - } else if(in instanceof Instant) { - return Date.from((Instant) in); - } else { - return Date.from(((LocalDate) in).atStartOfDay(timeZoneId).toInstant()); + private static Instant parseInstant(DateTimeFormatter formatter, String dateStr, ZoneId timeZoneId) { + final TemporalAccessor temporalAccessor = formatter.parse(dateStr); + // parsed successfully. But is it a full instant or just to the day? + if(temporalAccessor.isSupported(ChronoField.OFFSET_SECONDS)) { + return temporalAccessor.query(OffsetDateTime::from).toInstant(); + } else if (temporalAccessor.isSupported(ChronoField.INSTANT_SECONDS)) { // has time + return temporalAccessor.query(Instant::from); + } else { // no time, just date + if (temporalAccessor.isSupported(ChronoField.HOUR_OF_DAY) || temporalAccessor.isSupported(ChronoField.HOUR_OF_AMPM)) { + // TODO should we check for others? + throw new IllegalArgumentException("Pattern only has partial time?: " + formatter); + } + return temporalAccessor.query(LocalDate::from).atStartOfDay(timeZoneId).toInstant(); } } } From eba0f391225c1abf318a352201edf0aa0322cd54 Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Fri, 3 Aug 2018 10:33:37 +0300 Subject: [PATCH 06/17] SOLR-12586: parse date's using formatter zone or default to UTC --- .../processor/ParseDateFieldUpdateProcessorFactory.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java b/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java index 8c94874c89a6..cb6d83a4caa7 100644 --- a/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java +++ b/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java @@ -121,7 +121,7 @@ protected Object mutateValue(Object srcVal) { for (Map.Entry format : formats.entrySet()) { DateTimeFormatter parser = format.getValue(); try { - return Date.from(parseInstant(parser, srcStringVal, parser.getZone())); + return Date.from(parseInstant(parser, srcStringVal)); } catch (DateTimeParseException e) { log.debug("value '{}' is not parseable with format '{}'", new Object[] { srcStringVal, format.getKey() }); @@ -180,7 +180,7 @@ public void init(NamedList args) { }; } - private static Instant parseInstant(DateTimeFormatter formatter, String dateStr, ZoneId timeZoneId) { + private static Instant parseInstant(DateTimeFormatter formatter, String dateStr) { final TemporalAccessor temporalAccessor = formatter.parse(dateStr); // parsed successfully. But is it a full instant or just to the day? if(temporalAccessor.isSupported(ChronoField.OFFSET_SECONDS)) { @@ -192,7 +192,8 @@ private static Instant parseInstant(DateTimeFormatter formatter, String dateStr, // TODO should we check for others? throw new IllegalArgumentException("Pattern only has partial time?: " + formatter); } - return temporalAccessor.query(LocalDate::from).atStartOfDay(timeZoneId).toInstant(); + ZoneId formatterZone = formatter.getZone(); + return temporalAccessor.query(LocalDate::from).atStartOfDay(formatterZone==null? ZoneOffset.UTC: formatterZone).toInstant(); } } } From 012780732b909d3948ac637a3acf368bcf31fa1d Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Fri, 3 Aug 2018 11:14:28 +0300 Subject: [PATCH 07/17] SOLR-12586: ant precommit pass -> use Locale.ROOT for date patterns --- .../java/org/apache/solr/core/ConfigSetService.java | 2 +- .../AddSchemaFieldsUpdateProcessorFactoryTest.java | 5 +++-- .../processor/ParsingFieldUpdateProcessorsTest.java | 13 +++++++------ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/core/ConfigSetService.java b/solr/core/src/java/org/apache/solr/core/ConfigSetService.java index 3a1f9d724278..98b8ddeaf168 100644 --- a/solr/core/src/java/org/apache/solr/core/ConfigSetService.java +++ b/solr/core/src/java/org/apache/solr/core/ConfigSetService.java @@ -213,7 +213,7 @@ public SchemaCaching(SolrResourceLoader loader, Path configSetBase) { super(loader, configSetBase); } - public static final DateTimeFormatter cacheKeyFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + public static final DateTimeFormatter cacheKeyFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss", Locale.ROOT); public static String cacheName(Path schemaFile) throws IOException { long lastModified = Files.getLastModifiedTime(schemaFile).toMillis(); diff --git a/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java b/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java index b736f4630096..3e3cf2d648b1 100644 --- a/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java +++ b/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java @@ -22,6 +22,7 @@ import java.time.format.DateTimeFormatter; import java.util.Collections; import java.util.Date; +import java.util.Locale; import org.apache.commons.io.FileUtils; import org.apache.solr.common.SolrInputDocument; @@ -201,10 +202,10 @@ public void testParseAndAddMultipleFieldsRoundTrip() throws Exception { String field3String2 = "-5.28E-3"; Double field3Value2 = -5.28E-3; String field4String1 = "1999-04-17 17:42"; - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").withZone(ZoneOffset.UTC); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm", Locale.ROOT).withZone(ZoneOffset.UTC); LocalDateTime dateTime = LocalDateTime.parse(field4String1, dateTimeFormatter); Date field4Value1 = Date.from(dateTime.atZone(ZoneOffset.UTC).toInstant()); - DateTimeFormatter dateTimeFormatter2 = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss").withZone(ZoneOffset.UTC); + DateTimeFormatter dateTimeFormatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss", Locale.ROOT).withZone(ZoneOffset.UTC); String field4Value1String = dateTime.format(dateTimeFormatter2) + "Z"; SolrInputDocument d = processAdd diff --git a/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java b/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java index b5af7d5110b6..6aa2db4d64b7 100644 --- a/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java +++ b/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java @@ -33,6 +33,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.Locale; import java.util.Map; import java.util.Set; @@ -118,7 +119,7 @@ public void testParseDateNonUTCdefaultTimeZoneRoundTrip() throws Exception { f("dateNoTimeZone_dt", dateStringNoTimeZone))); assertNotNull(d); String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"; - DateTimeFormatter UTCForamatter = DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.of("America/New_York")); + DateTimeFormatter UTCForamatter = DateTimeFormatter.ofPattern(pattern, Locale.ROOT).withZone(ZoneId.of("America/New_York")); OffsetDateTime dateTimeOffsetUTC = OffsetDateTime.parse(dateStringUTC, UTCForamatter); assertTrue(d.getFieldValue("dateUTC_dt") instanceof Date); assertTrue(d.getFieldValue("dateNoTimeZone_dt") instanceof Date); @@ -171,7 +172,7 @@ public void testParseUSPacificDate() throws Exception { assertNotNull(d); assertTrue(d.getFieldValue("not_in_schema") instanceof Date); assertEquals(dateStringUTC, - (ZonedDateTime.ofInstant(((Date)d.getFieldValue("not_in_schema")).toInstant(), ZoneOffset.UTC)).format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"))); + (ZonedDateTime.ofInstant(((Date)d.getFieldValue("not_in_schema")).toInstant(), ZoneOffset.UTC)).format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ", Locale.ROOT))); } public void testParseDateFormats() throws Exception { @@ -209,7 +210,7 @@ public void testParseDateFormats() throws Exception { assertNotNull(schema.getFieldOrNull("dateUTC_dt")); // should match "*_dt" dynamic field String dateTimePattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"; - DateTimeFormatter UTCDateTimeFormatter = DateTimeFormatter.ofPattern(dateTimePattern); + DateTimeFormatter UTCDateTimeFormatter = DateTimeFormatter.ofPattern(dateTimePattern, Locale.ROOT); ZonedDateTime UTCDateTIme = ZonedDateTime.parse(formatExamples[1], UTCDateTimeFormatter); for (int i = 0 ; i < formatExamples.length ; i += 2) { @@ -242,7 +243,7 @@ public void testParseFrenchDate() throws Exception { public void testFailedParseMixedDate() throws Exception { IndexSchema schema = h.getCore().getLatestSchema(); assertNull(schema.getFieldOrNull("not_in_schema")); - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm][:ss.SSSZZZZZ]").withZone(ZoneOffset.UTC); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm][:ss.SSSZZZZZ]", Locale.ROOT).withZone(ZoneOffset.UTC); Map mixed = new HashMap<>(); String[] dateStrings = { "2020-05-13T18:47", "1989-12-14", "1682-07-22T18:33:00.000Z" }; for (String dateString : dateStrings) { @@ -804,7 +805,7 @@ public void testCascadingParsers() throws Exception { longs.remove(o); } - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm][:ss.SSSZZZZZ]").withZone(ZoneOffset.UTC); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm][:ss.SSSZZZZZ]", Locale.ROOT).withZone(ZoneOffset.UTC); Map dates = new HashMap<>(); String[] dateStrings = { "2020-05-13T18:47", "1989-12-14", "1682-07-22T18:33:00.000Z" }; for (String dateString : dateStrings) { @@ -896,7 +897,7 @@ public void testCascadingParsers() throws Exception { } assertTrue(mixedBooleans.isEmpty()); - dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm][:ss.SSSZZZZZ]").withZone(ZoneOffset.UTC); + dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm][:ss.SSSZZZZZ]", Locale.ROOT).withZone(ZoneOffset.UTC); Map mixedDates = new HashMap<>(); dateStrings = new String[] { "2020-05-13T18:47", "1989-12-14", "1682-07-22T18:33:00.000Z" }; for (String dateString : dateStrings) { From 795b97f6b66da5247667b0f5a57d6811924ec5e0 Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Sat, 4 Aug 2018 03:01:25 +0300 Subject: [PATCH 08/17] SOLR-1286: remove joda license files --- solr/licenses/joda-time-2.2.jar.sha1 | 1 - solr/licenses/joda-time-LICENSE-ASL.txt | 202 ------------------------ 2 files changed, 203 deletions(-) delete mode 100644 solr/licenses/joda-time-2.2.jar.sha1 delete mode 100644 solr/licenses/joda-time-LICENSE-ASL.txt diff --git a/solr/licenses/joda-time-2.2.jar.sha1 b/solr/licenses/joda-time-2.2.jar.sha1 deleted file mode 100644 index 5e68639267ac..000000000000 --- a/solr/licenses/joda-time-2.2.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -a5f29a7acaddea3f4af307e8cf2d0cc82645fd7d diff --git a/solr/licenses/joda-time-LICENSE-ASL.txt b/solr/licenses/joda-time-LICENSE-ASL.txt deleted file mode 100644 index d64569567334..000000000000 --- a/solr/licenses/joda-time-LICENSE-ASL.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. From 06917698699e2c52a435a01003c82d47645b04ff Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Sat, 4 Aug 2018 03:01:38 +0300 Subject: [PATCH 09/17] SOLR-12586: refactor code for pr --- .../apache/solr/core/ConfigSetService.java | 4 +--- .../ParseDateFieldUpdateProcessorFactory.java | 21 ++++++++++++++++--- ...chemaFieldsUpdateProcessorFactoryTest.java | 5 ++--- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/core/ConfigSetService.java b/solr/core/src/java/org/apache/solr/core/ConfigSetService.java index 98b8ddeaf168..a0bb90c9187a 100644 --- a/solr/core/src/java/org/apache/solr/core/ConfigSetService.java +++ b/solr/core/src/java/org/apache/solr/core/ConfigSetService.java @@ -213,12 +213,10 @@ public SchemaCaching(SolrResourceLoader loader, Path configSetBase) { super(loader, configSetBase); } - public static final DateTimeFormatter cacheKeyFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss", Locale.ROOT); - public static String cacheName(Path schemaFile) throws IOException { long lastModified = Files.getLastModifiedTime(schemaFile).toMillis(); return String.format(Locale.ROOT, "%s:%s", - schemaFile.toString(), Instant.ofEpochMilli(lastModified).atZone(ZoneOffset.UTC).format(cacheKeyFormatter)); + schemaFile.toString(), Instant.ofEpochMilli(lastModified).toString()); } @Override diff --git a/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java b/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java index cb6d83a4caa7..c58191031f07 100644 --- a/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java +++ b/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java @@ -34,6 +34,7 @@ import java.util.Map; import org.apache.commons.lang.LocaleUtils; +import org.apache.solr.common.SolrException; import org.apache.solr.common.util.NamedList; import org.apache.solr.core.SolrCore; import org.apache.solr.request.SolrQueryRequest; @@ -159,6 +160,7 @@ public void init(NamedList args) { for (String value : formatsParam) { DateTimeFormatter formatter = new DateTimeFormatterBuilder().parseCaseInsensitive() .appendPattern(value).toFormatter(locale).withZone(defaultTimeZone); + validateFormatter(formatter); formats.put(value, formatter); } } @@ -180,12 +182,24 @@ public void init(NamedList args) { }; } + public static void validateFormatter(DateTimeFormatter formatter) { + // check it's valid via round-trip + try { + parseInstant(formatter, formatter.format(Instant.now())); + } catch (Exception e) { + throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, + "Bad or unsupported pattern: " + formatter.toFormat().toString(), e); + } + } + private static Instant parseInstant(DateTimeFormatter formatter, String dateStr) { final TemporalAccessor temporalAccessor = formatter.parse(dateStr); // parsed successfully. But is it a full instant or just to the day? - if(temporalAccessor.isSupported(ChronoField.OFFSET_SECONDS)) { - return temporalAccessor.query(OffsetDateTime::from).toInstant(); - } else if (temporalAccessor.isSupported(ChronoField.INSTANT_SECONDS)) { // has time + if (temporalAccessor.isSupported(ChronoField.INSTANT_SECONDS)) { // has time + // has offset time + if(temporalAccessor.isSupported(ChronoField.OFFSET_SECONDS)) { + return temporalAccessor.query(OffsetDateTime::from).toInstant(); + } return temporalAccessor.query(Instant::from); } else { // no time, just date if (temporalAccessor.isSupported(ChronoField.HOUR_OF_DAY) || temporalAccessor.isSupported(ChronoField.HOUR_OF_AMPM)) { @@ -193,6 +207,7 @@ private static Instant parseInstant(DateTimeFormatter formatter, String dateStr) throw new IllegalArgumentException("Pattern only has partial time?: " + formatter); } ZoneId formatterZone = formatter.getZone(); + // use default time zone if none was specified return temporalAccessor.query(LocalDate::from).atStartOfDay(formatterZone==null? ZoneOffset.UTC: formatterZone).toInstant(); } } diff --git a/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java b/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java index 3e3cf2d648b1..96cc6766e939 100644 --- a/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java +++ b/solr/core/src/test/org/apache/solr/update/processor/AddSchemaFieldsUpdateProcessorFactoryTest.java @@ -17,6 +17,7 @@ package org.apache.solr.update.processor; import java.io.File; +import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; @@ -62,9 +63,7 @@ public void testSingleField() throws Exception { IndexSchema schema = h.getCore().getLatestSchema(); final String fieldName = "newfield1"; assertNull(schema.getFieldOrNull(fieldName)); - String dateString = "2010-11-12T13:14:15.168Z"; - LocalDateTime localDateTime = LocalDateTime.parse(dateString, DateTimeFormatter.ISO_DATE_TIME); - Date date = Date.from(localDateTime.atZone(ZoneOffset.UTC).toInstant()); + Date date = Date.from(Instant.now()); SolrInputDocument d = processAdd("add-fields-no-run-processor", doc(f("id", "1"), f(fieldName, date))); assertNotNull(d); schema = h.getCore().getLatestSchema(); From 3368cba589f918bf876f1e50172c0b96a73a0035 Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Sat, 4 Aug 2018 03:10:11 +0300 Subject: [PATCH 10/17] SOLR-12586: simplify date assert in tests using Instant comparison --- .../ParsingFieldUpdateProcessorsTest.java | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java b/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java index 6aa2db4d64b7..f88555bdfae2 100644 --- a/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java +++ b/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java @@ -55,9 +55,8 @@ public void testParseDateRoundTrip() throws Exception { String dateString = "2010-11-12T13:14:15.168Z"; SolrInputDocument d = processAdd("parse-date", doc(f("id", "9"), f("date_dt", dateString))); assertNotNull(d); - ZonedDateTime localDateTime = ZonedDateTime.parse(dateString, DateTimeFormatter.ISO_DATE_TIME); assertTrue(d.getFieldValue("date_dt") instanceof Date); - assertEquals(localDateTime.withZoneSameInstant(ZoneOffset.UTC).toInstant().toEpochMilli(), ((Date) d.getFieldValue("date_dt")).getTime()); + assertEquals(Instant.parse(dateString), ((Date) d.getFieldValue("date_dt")).toInstant()); assertU(commit()); assertQ(req("id:9"), "//date[@name='date_dt'][.='" + dateString + "']"); } @@ -68,9 +67,8 @@ public void testParseTrieDateRoundTrip() throws Exception { String dateString = "2010-11-12T13:14:15.168Z"; SolrInputDocument d = processAdd("parse-date", doc(f("id", "39"), f("date_tdt", dateString))); assertNotNull(d); - ZonedDateTime localDateTime = ZonedDateTime.parse(dateString, DateTimeFormatter.ISO_DATE_TIME); assertTrue(d.getFieldValue("date_tdt") instanceof Date); - assertEquals(localDateTime.withZoneSameInstant(ZoneOffset.UTC).toInstant().toEpochMilli(), ((Date) d.getFieldValue("date_tdt")).getTime()); + assertEquals(Instant.parse(dateString), ((Date) d.getFieldValue("date_tdt")).toInstant()); assertU(commit()); assertQ(req("id:39"), "//date[@name='date_tdt'][.='" + dateString + "']"); } @@ -80,13 +78,12 @@ public void testParseDateFieldNotInSchema() throws Exception { IndexSchema schema = h.getCore().getLatestSchema(); assertNull(schema.getFieldOrNull("not_in_schema")); String dateString = "2010-11-12T13:14:15.168Z"; - ZonedDateTime localDateTime = ZonedDateTime.parse(dateString, DateTimeFormatter.ISO_DATE_TIME); SolrInputDocument d = processAdd("parse-date-no-run-processor", doc(f("id", "18"), f("not_in_schema", dateString))); assertNotNull(d); assertTrue(d.getFieldValue("not_in_schema") instanceof Date); - assertEquals(localDateTime.withZoneSameInstant(ZoneOffset.UTC).toInstant().toEpochMilli(), ((Date)d.getFieldValue("not_in_schema")).getTime()); + assertEquals(Instant.parse(dateString), ((Date)d.getFieldValue("not_in_schema")).toInstant()); d = processAdd("parse-date-no-run-processor", doc(f("id", "36"), f("not_in_schema", "not a date", dateString))); @@ -118,12 +115,9 @@ public void testParseDateNonUTCdefaultTimeZoneRoundTrip() throws Exception { ("parse-date-non-UTC-defaultTimeZone", doc(f("id", "99"), f("dateUTC_dt", dateStringUTC), f("dateNoTimeZone_dt", dateStringNoTimeZone))); assertNotNull(d); - String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"; - DateTimeFormatter UTCForamatter = DateTimeFormatter.ofPattern(pattern, Locale.ROOT).withZone(ZoneId.of("America/New_York")); - OffsetDateTime dateTimeOffsetUTC = OffsetDateTime.parse(dateStringUTC, UTCForamatter); assertTrue(d.getFieldValue("dateUTC_dt") instanceof Date); assertTrue(d.getFieldValue("dateNoTimeZone_dt") instanceof Date); - assertEquals(dateTimeOffsetUTC.toInstant().toEpochMilli(), ((Date) d.getFieldValue("dateUTC_dt")).getTime()); + assertEquals(Instant.parse(dateStringUTC), ((Date) d.getFieldValue("dateUTC_dt")).toInstant()); assertU(commit()); assertQ(req("id:99") ,"//date[@name='dateUTC_dt'][.='" + dateStringUTC + "']" @@ -134,20 +128,18 @@ public void testParseDateExplicitNotInSchemaSelector() throws Exception { IndexSchema schema = h.getCore().getLatestSchema(); assertNull(schema.getFieldOrNull("not_in_schema")); String dateString = "2010-11-12T13:14:15.168Z"; - ZonedDateTime localDateTime = ZonedDateTime.parse(dateString, DateTimeFormatter.ISO_DATE_TIME); SolrInputDocument d = processAdd("parse-date-explicit-not-in-schema-selector-no-run-processor", doc(f("id", "88"), f("not_in_schema", dateString))); assertNotNull(d); assertTrue(d.getFieldValue("not_in_schema") instanceof Date); - assertEquals(localDateTime.withZoneSameInstant(ZoneOffset.UTC).toInstant().toEpochMilli(), ((Date)d.getFieldValue("not_in_schema")).getTime()); + assertEquals(Instant.parse(dateString), ((Date)d.getFieldValue("not_in_schema")).toInstant()); } public void testParseDateExplicitTypeClassSelector() throws Exception { IndexSchema schema = h.getCore().getLatestSchema(); assertNotNull(schema.getFieldOrNull("date_dt")); String dateString = "2010-11-12T13:14:15.168Z"; - ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateString, DateTimeFormatter.ISO_DATE_TIME); SolrInputDocument d; if (schema.getField("date_dt").getType().isPointField()) { d = processAdd("parse-date-explicit-typeclass-point-selector-no-run-processor", @@ -159,7 +151,7 @@ public void testParseDateExplicitTypeClassSelector() throws Exception { assertNotNull(d); assertTrue(d.getFieldValue("date_dt") instanceof Date); - assertEquals(zonedDateTime.withZoneSameInstant(ZoneOffset.UTC).toInstant().toEpochMilli(), ((Date)d.getFieldValue("date_dt")).getTime()); + assertEquals(Instant.parse(dateString), ((Date)d.getFieldValue("date_dt")).toInstant()); } public void testParseUSPacificDate() throws Exception { @@ -210,8 +202,7 @@ public void testParseDateFormats() throws Exception { assertNotNull(schema.getFieldOrNull("dateUTC_dt")); // should match "*_dt" dynamic field String dateTimePattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"; - DateTimeFormatter UTCDateTimeFormatter = DateTimeFormatter.ofPattern(dateTimePattern, Locale.ROOT); - ZonedDateTime UTCDateTIme = ZonedDateTime.parse(formatExamples[1], UTCDateTimeFormatter); + Instant UTCInstant = Instant.parse(formatExamples[1]); for (int i = 0 ; i < formatExamples.length ; i += 2) { String format = formatExamples[i]; @@ -223,7 +214,7 @@ public void testParseDateFormats() throws Exception { assertTrue("index: " + i + " date '" + dateString + "' with format '" + format + "' is not mutated to a Date", d.getFieldValue("dateUTC_dt") instanceof Date); assertEquals("date '" + dateString + "' with format '" + format + "' mismatched milliseconds", - UTCDateTIme.toInstant().toEpochMilli(), ((Date)d.getFieldValue("dateUTC_dt")).getTime()); + UTCInstant, ((Date)d.getFieldValue("dateUTC_dt")).toInstant()); } } @@ -232,12 +223,11 @@ public void testParseFrenchDate() throws Exception { assertNull(schema.getFieldOrNull("not_in_schema")); String frenchDateString = "le vendredi 15 janvier 2010"; String dateString = "2010-01-15T00:00:00.000Z"; - LocalDateTime localDateTime = LocalDateTime.parse(dateString, DateTimeFormatter.ISO_DATE_TIME); SolrInputDocument d = processAdd("parse-french-date-UTC-defaultTimeZone-no-run-processor", doc(f("id", "88"), f("not_in_schema", frenchDateString))); assertNotNull(d); assertTrue(d.getFieldValue("not_in_schema") instanceof Date); - assertEquals(localDateTime.atZone(ZoneOffset.UTC).toInstant().toEpochMilli(), ((Date)d.getFieldValue("not_in_schema")).getTime()); + assertEquals(Instant.parse(dateString), ((Date)d.getFieldValue("not_in_schema")).toInstant()); } public void testFailedParseMixedDate() throws Exception { From 27203a4bf03151b13ee057d68df4b63a0cedf422 Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Sat, 4 Aug 2018 03:13:18 +0300 Subject: [PATCH 11/17] SOLR-12586: remove uneeded assert in ParsingFieldUpdateProcessorsTest#testParseDateNonUTCdefaultTimeZoneRoundTrip --- .../solr/update/processor/ParsingFieldUpdateProcessorsTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java b/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java index f88555bdfae2..6b483c356b8d 100644 --- a/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java +++ b/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java @@ -117,7 +117,6 @@ public void testParseDateNonUTCdefaultTimeZoneRoundTrip() throws Exception { assertNotNull(d); assertTrue(d.getFieldValue("dateUTC_dt") instanceof Date); assertTrue(d.getFieldValue("dateNoTimeZone_dt") instanceof Date); - assertEquals(Instant.parse(dateStringUTC), ((Date) d.getFieldValue("dateUTC_dt")).toInstant()); assertU(commit()); assertQ(req("id:99") ,"//date[@name='dateUTC_dt'][.='" + dateStringUTC + "']" From de42bae83961a56b8c1503b9dd63805d2a7970b9 Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Sat, 4 Aug 2018 09:50:04 +0300 Subject: [PATCH 12/17] SOLR-12586: remove uneeded steps in ParsingFieldUpdateProcessorsTest#temporalToDate --- .../update/processor/ParsingFieldUpdateProcessorsTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java b/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java index 6b483c356b8d..fbe1bcfc61b4 100644 --- a/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java +++ b/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java @@ -200,8 +200,7 @@ public void testParseDateFormats() throws Exception { IndexSchema schema = h.getCore().getLatestSchema(); assertNotNull(schema.getFieldOrNull("dateUTC_dt")); // should match "*_dt" dynamic field - String dateTimePattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"; - Instant UTCInstant = Instant.parse(formatExamples[1]); + Instant expectedInstant = Instant.parse(formatExamples[1]); for (int i = 0 ; i < formatExamples.length ; i += 2) { String format = formatExamples[i]; @@ -213,7 +212,7 @@ public void testParseDateFormats() throws Exception { assertTrue("index: " + i + " date '" + dateString + "' with format '" + format + "' is not mutated to a Date", d.getFieldValue("dateUTC_dt") instanceof Date); assertEquals("date '" + dateString + "' with format '" + format + "' mismatched milliseconds", - UTCInstant, ((Date)d.getFieldValue("dateUTC_dt")).toInstant()); + expectedInstant, ((Date)d.getFieldValue("dateUTC_dt")).toInstant()); } } @@ -909,7 +908,7 @@ private Date temporalToDate(TemporalAccessor in, ZoneId timeZoneId) { if(in instanceof OffsetDateTime) { return Date.from(((OffsetDateTime) in).toInstant()); } else if(in instanceof ZonedDateTime) { - return Date.from(((ZonedDateTime) in).withZoneSameInstant(timeZoneId).toInstant()); + return Date.from(((ZonedDateTime) in).toInstant()); } else if(in instanceof LocalDateTime) { return Date.from(((LocalDateTime) in).atZone(timeZoneId).toInstant()); } else if(in instanceof Instant) { From 6b29c1f879478e8e815625ef323fdfc7f55b8faa Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Sun, 5 Aug 2018 19:56:40 +0300 Subject: [PATCH 13/17] SOLR-12586: use TemporalQuery to parse date from TemporalAccessor --- .../ParseDateFieldUpdateProcessorFactory.java | 46 +++++++++++++------ ...config-parsing-update-processor-chains.xml | 26 +++++------ .../ParsingFieldUpdateProcessorsTest.java | 31 +++++++------ 3 files changed, 60 insertions(+), 43 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java b/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java index c58191031f07..846741f21c97 100644 --- a/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java +++ b/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java @@ -19,6 +19,8 @@ import java.lang.invoke.MethodHandles; import java.time.Instant; import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.OffsetDateTime; import java.time.ZoneId; import java.time.ZoneOffset; @@ -27,6 +29,7 @@ import java.time.format.DateTimeParseException; import java.time.temporal.ChronoField; import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalQueries; import java.util.Collection; import java.util.Date; import java.util.LinkedHashMap; @@ -193,22 +196,35 @@ public static void validateFormatter(DateTimeFormatter formatter) { } private static Instant parseInstant(DateTimeFormatter formatter, String dateStr) { - final TemporalAccessor temporalAccessor = formatter.parse(dateStr); - // parsed successfully. But is it a full instant or just to the day? - if (temporalAccessor.isSupported(ChronoField.INSTANT_SECONDS)) { // has time - // has offset time - if(temporalAccessor.isSupported(ChronoField.OFFSET_SECONDS)) { - return temporalAccessor.query(OffsetDateTime::from).toInstant(); - } - return temporalAccessor.query(Instant::from); - } else { // no time, just date - if (temporalAccessor.isSupported(ChronoField.HOUR_OF_DAY) || temporalAccessor.isSupported(ChronoField.HOUR_OF_AMPM)) { - // TODO should we check for others? - throw new IllegalArgumentException("Pattern only has partial time?: " + formatter); + final TemporalAccessor temporal = formatter.parse(dateStr); + // Get Date; mandatory + LocalDate date = temporal.query(TemporalQueries.localDate());//mandatory + if (date == null) { + throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, + "Date (year, month, day) is mandatory: " + formatter.toFormat().toString()); + } + // Get Time; optional + LocalTime time = temporal.query(TemporalQueries.localTime()); + if (time == null) { + time = LocalTime.MIN; + } + + final LocalDateTime localDateTime = LocalDateTime.of(date, time); + + // Get Zone Offset; optional + ZoneOffset offset = temporal.query(TemporalQueries.offset()); + if (offset == null) { + // no Zone offset; get Zone ID + ZoneId zoneId = temporal.query(TemporalQueries.zone()); + if (zoneId == null) { + zoneId = formatter.getZone(); + if (zoneId == null) { + zoneId = ZoneOffset.UTC; + } } - ZoneId formatterZone = formatter.getZone(); - // use default time zone if none was specified - return temporalAccessor.query(LocalDate::from).atStartOfDay(formatterZone==null? ZoneOffset.UTC: formatterZone).toInstant(); + return localDateTime.atZone(zoneId).toInstant(); + } else { + return localDateTime.toInstant(offset); } } } diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml index da359b8db06b..c8cf8f0d1005 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml @@ -65,7 +65,7 @@ America/New_York en_US - yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ + yyyy-MM-dd'T'HH:mm:ss.SSSz yyyy-MM-dd'T'HH:mm:ss.SSS @@ -85,30 +85,30 @@ UTC en_US - yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ - yyyy-MM-dd'T'HH:mm:ss,SSSZZZZZ + yyyy-MM-dd'T'HH:mm:ss.SSSz + yyyy-MM-dd'T'HH:mm:ss,SSSz yyyy-MM-dd'T'HH:mm:ss.SSS yyyy-MM-dd'T'HH:mm:ss,SSS - yyyy-MM-dd'T'HH:mm:ssZZZZZ + yyyy-MM-dd'T'HH:mm:ssz yyyy-MM-dd'T'HH:mm:ss - yyyy-MM-dd'T'HH:mmZZZZZ + yyyy-MM-dd'T'HH:mmz yyyy-MM-dd'T'HH:mm - yyyy-MM-dd HH:mm:ss.SSSZZZZZ - yyyy-MM-dd HH:mm:ss,SSSZZZZZ + yyyy-MM-dd HH:mm:ss.SSSz + yyyy-MM-dd HH:mm:ss,SSSz yyyy-MM-dd HH:mm:ss.SSS yyyy-MM-dd HH:mm:ss,SSS - yyyy-MM-dd HH:mm:ssZZZZZ + yyyy-MM-dd HH:mm:ssz yyyy-MM-dd HH:mm:ss - yyyy-MM-dd HH:mmZZZZZ + yyyy-MM-dd HH:mmz yyyy-MM-dd HH:mm yyyy-MM-dd hh:mm a yyyy-MM-dd hh:mma yyyy-MM-dd EEE MMM dd HH:mm:ss ZZZ yyyy - EEE MMM dd HH:mm:ss yyyy ZZZZZ + EEE MMM dd HH:mm:ss yyyy z EEE MMM dd HH:mm:ss yyyy - EEE, dd MMM yyyy HH:mm:ss ZZZZZ - EEEE, dd-MMM-yy HH:mm:ss ZZZZZ + EEE, dd MMM yyyy HH:mm:ss z + EEEE, dd-MMM-yy HH:mm:ss z EEEE, MMMM dd, yyyy MMMM dd, yyyy MMM. dd, yyyy @@ -229,7 +229,7 @@ yyyy-MM-dd - yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ + yyyy-MM-dd'T'HH:mm:ss.SSSz yyyy-MM-dd'T'HH:mm diff --git a/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java b/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java index fbe1bcfc61b4..7ba195304fa5 100644 --- a/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java +++ b/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java @@ -163,35 +163,36 @@ public void testParseUSPacificDate() throws Exception { assertNotNull(d); assertTrue(d.getFieldValue("not_in_schema") instanceof Date); assertEquals(dateStringUTC, - (ZonedDateTime.ofInstant(((Date)d.getFieldValue("not_in_schema")).toInstant(), ZoneOffset.UTC)).format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ", Locale.ROOT))); + (ZonedDateTime.ofInstant(((Date)d.getFieldValue("not_in_schema")).toInstant(), ZoneOffset.UTC)).format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSz", Locale.ROOT))); } public void testParseDateFormats() throws Exception { + // format examples are duplicated from config in solrconfig-parsing-update-processor-chains.xml String[] formatExamples = { - "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ", "2010-01-15T00:00:00.000Z", - "yyyy-MM-dd'T'HH:mm:ss,SSSZZZZZ", "2010-01-15T00:00:00,000Z", + "yyyy-MM-dd'T'HH:mm:ss.SSSz", "2010-01-15T00:00:00.000Z", + "yyyy-MM-dd'T'HH:mm:ss,SSSz", "2010-01-15T00:00:00,000Z", "yyyy-MM-dd'T'HH:mm:ss.SSS", "2010-01-15T00:00:00.000", "yyyy-MM-dd'T'HH:mm:ss,SSS", "2010-01-15T00:00:00,000", - "yyyy-MM-dd'T'HH:mm:ssZZZZZ", "2010-01-15T00:00:00Z", + "yyyy-MM-dd'T'HH:mm:ssz", "2010-01-15T00:00:00Z", "yyyy-MM-dd'T'HH:mm:ss", "2010-01-15T00:00:00", - "yyyy-MM-dd'T'HH:mmZZZZZ", "2010-01-15T00:00Z", + "yyyy-MM-dd'T'HH:mmz", "2010-01-15T00:00Z", "yyyy-MM-dd'T'HH:mm", "2010-01-15T00:00", - "yyyy-MM-dd HH:mm:ss.SSSZZZZZ", "2010-01-15 00:00:00.000Z", - "yyyy-MM-dd HH:mm:ss,SSSZZZZZ", "2010-01-15 00:00:00,000Z", + "yyyy-MM-dd HH:mm:ss.SSSz", "2010-01-15 00:00:00.000Z", + "yyyy-MM-dd HH:mm:ss,SSSz", "2010-01-15 00:00:00,000Z", "yyyy-MM-dd HH:mm:ss.SSS", "2010-01-15 00:00:00.000", "yyyy-MM-dd HH:mm:ss,SSS", "2010-01-15 00:00:00,000", - "yyyy-MM-dd HH:mm:ssZZZZZ", "2010-01-15 00:00:00Z", + "yyyy-MM-dd HH:mm:ssz", "2010-01-15 00:00:00Z", "yyyy-MM-dd HH:mm:ss", "2010-01-15 00:00:00", - "yyyy-MM-dd HH:mmZZZZZ", "2010-01-15 00:00Z", + "yyyy-MM-dd HH:mmz", "2010-01-15 00:00Z", "yyyy-MM-dd HH:mm", "2010-01-15 00:00", "yyyy-MM-dd hh:mm a", "2010-01-15 12:00 AM", "yyyy-MM-dd hh:mma", "2010-01-15 12:00AM", "yyyy-MM-dd", "2010-01-15", "EEE MMM dd HH:mm:ss ZZZ yyyy", "Fri Jan 15 00:00:00 +0000 2010", - "EEE MMM dd HH:mm:ss yyyy ZZZZZ", "Fri Jan 15 00:00:00 2010 +00:00", + "EEE MMM dd HH:mm:ss yyyy z", "Fri Jan 15 00:00:00 2010 +00:00", "EEE MMM dd HH:mm:ss yyyy", "Fri Jan 15 00:00:00 2010", - "EEE, dd MMM yyyy HH:mm:ss ZZZZZ", "Fri, 15 Jan 2010 00:00:00 +00:00", - "EEEE, dd-MMM-yy HH:mm:ss ZZZZZ", "Friday, 15-Jan-10 00:00:00 +00:00", + "EEE, dd MMM yyyy HH:mm:ss z", "Fri, 15 Jan 2010 00:00:00 +00:00", + "EEEE, dd-MMM-yy HH:mm:ss z", "Friday, 15-Jan-10 00:00:00 +00:00", "EEEE, MMMM dd, yyyy", "Friday, January 15, 2010", "MMMM dd, yyyy", "January 15, 2010", "MMM. dd, yyyy", "Jan. 15, 2010" @@ -231,7 +232,7 @@ public void testParseFrenchDate() throws Exception { public void testFailedParseMixedDate() throws Exception { IndexSchema schema = h.getCore().getLatestSchema(); assertNull(schema.getFieldOrNull("not_in_schema")); - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm][:ss.SSSZZZZZ]", Locale.ROOT).withZone(ZoneOffset.UTC); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm][:ss.SSSz]", Locale.ROOT).withZone(ZoneOffset.UTC); Map mixed = new HashMap<>(); String[] dateStrings = { "2020-05-13T18:47", "1989-12-14", "1682-07-22T18:33:00.000Z" }; for (String dateString : dateStrings) { @@ -793,7 +794,7 @@ public void testCascadingParsers() throws Exception { longs.remove(o); } - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm][:ss.SSSZZZZZ]", Locale.ROOT).withZone(ZoneOffset.UTC); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm][:ss.SSSz]", Locale.ROOT).withZone(ZoneOffset.UTC); Map dates = new HashMap<>(); String[] dateStrings = { "2020-05-13T18:47", "1989-12-14", "1682-07-22T18:33:00.000Z" }; for (String dateString : dateStrings) { @@ -885,7 +886,7 @@ public void testCascadingParsers() throws Exception { } assertTrue(mixedBooleans.isEmpty()); - dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm][:ss.SSSZZZZZ]", Locale.ROOT).withZone(ZoneOffset.UTC); + dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd['T'HH:mm][:ss.SSSz]", Locale.ROOT).withZone(ZoneOffset.UTC); Map mixedDates = new HashMap<>(); dateStrings = new String[] { "2020-05-13T18:47", "1989-12-14", "1682-07-22T18:33:00.000Z" }; for (String dateString : dateStrings) { From fdaab3e40364c92f3c9223d79f988dc15ee61b09 Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Sun, 5 Aug 2018 22:03:05 +0300 Subject: [PATCH 14/17] SOLR-12586: ant precommit remove unused imports --- solr/core/src/java/org/apache/solr/core/ConfigSetService.java | 2 -- .../update/processor/ParseDateFieldUpdateProcessorFactory.java | 2 -- 2 files changed, 4 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/core/ConfigSetService.java b/solr/core/src/java/org/apache/solr/core/ConfigSetService.java index a0bb90c9187a..104bb7381158 100644 --- a/solr/core/src/java/org/apache/solr/core/ConfigSetService.java +++ b/solr/core/src/java/org/apache/solr/core/ConfigSetService.java @@ -22,8 +22,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.time.Instant; -import java.time.ZoneOffset; -import java.time.format.DateTimeFormatter; import java.util.Locale; import java.util.concurrent.ExecutionException; diff --git a/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java b/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java index 846741f21c97..575643bfb93c 100644 --- a/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java +++ b/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java @@ -21,13 +21,11 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.OffsetDateTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.DateTimeParseException; -import java.time.temporal.ChronoField; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalQueries; import java.util.Collection; From 3f16f67a98770a549756906716f030c833d50145 Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Sun, 5 Aug 2018 22:07:48 +0300 Subject: [PATCH 15/17] SOLR-12586: change conf to use single lower case z for date format strings --- .../solrconfig-parsing-update-processor-chains.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml index c8cf8f0d1005..f5d09a4ebff0 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml @@ -29,35 +29,35 @@ - yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ + yyyy-MM-dd'T'HH:mm:ss.SSSz - yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ + yyyy-MM-dd'T'HH:mm:ss.SSSz false - yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ + yyyy-MM-dd'T'HH:mm:ss.SSSz solr.DatePointField - yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ + yyyy-MM-dd'T'HH:mm:ss.SSSz solr.TrieDateField - yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ + yyyy-MM-dd'T'HH:mm:ss.SSSz @@ -104,7 +104,7 @@ yyyy-MM-dd hh:mm a yyyy-MM-dd hh:mma yyyy-MM-dd - EEE MMM dd HH:mm:ss ZZZ yyyy + EEE MMM dd HH:mm:ss z yyyy EEE MMM dd HH:mm:ss yyyy z EEE MMM dd HH:mm:ss yyyy EEE, dd MMM yyyy HH:mm:ss z From 11d1519bf79f9ad92fd0d774c6ff29da5c6e7c3b Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Mon, 6 Aug 2018 21:43:08 +0300 Subject: [PATCH 16/17] SOLR-12586: add comment about java 8 Instant::Parse bug --- .../processor/ParseDateFieldUpdateProcessorFactory.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java b/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java index 575643bfb93c..f0ea5d257204 100644 --- a/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java +++ b/solr/core/src/java/org/apache/solr/update/processor/ParseDateFieldUpdateProcessorFactory.java @@ -193,6 +193,11 @@ public static void validateFormatter(DateTimeFormatter formatter) { } } + // see https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8177021 which is fixed in Java 9. + // The upshot is that trying to use parse(Instant::from) is unreliable in the event that + // the input string contains a timezone/offset that differs from the "override zone" + // (which we configure in DEFAULT_TIME_ZONE). Besides, we need the code below which handles + // the optionality of time. Were it not for that, we truly could do formatter.parse(Instant::from). private static Instant parseInstant(DateTimeFormatter formatter, String dateStr) { final TemporalAccessor temporal = formatter.parse(dateStr); // Get Date; mandatory From 24e7aadc9853e47cf461b23855d0fca12256809b Mon Sep 17 00:00:00 2001 From: Bar Rotstein Date: Mon, 6 Aug 2018 21:49:32 +0300 Subject: [PATCH 17/17] SOLR-12586: change conf and adocs to use more efficient java.time optional patterns --- .../collection1/conf/solrconfig.xml | 20 ++---- ...-schema-fields-update-processor-chains.xml | 20 ++---- ...config-parsing-update-processor-chains.xml | 31 +++------ .../conf/solrconfig-schemaless.xml | 20 ++---- .../configsets/_default/conf/solrconfig.xml | 20 ++---- .../ParsingFieldUpdateProcessorsTest.java | 68 +++++++++---------- solr/example/files/conf/solrconfig.xml | 20 ++---- .../configsets/_default/conf/solrconfig.xml | 20 ++---- solr/solr-ref-guide/src/schemaless-mode.adoc | 20 ++---- 9 files changed, 69 insertions(+), 170 deletions(-) diff --git a/solr/contrib/prometheus-exporter/src/test-files/configsets/collection1/conf/solrconfig.xml b/solr/contrib/prometheus-exporter/src/test-files/configsets/collection1/conf/solrconfig.xml index 72c54304f246..37c41d8909c3 100644 --- a/solr/contrib/prometheus-exporter/src/test-files/configsets/collection1/conf/solrconfig.xml +++ b/solr/contrib/prometheus-exporter/src/test-files/configsets/collection1/conf/solrconfig.xml @@ -164,22 +164,10 @@ - yyyy-MM-dd'T'HH:mm:ss.SSSZ - yyyy-MM-dd'T'HH:mm:ss,SSSZ - yyyy-MM-dd'T'HH:mm:ss.SSS - yyyy-MM-dd'T'HH:mm:ss,SSS - yyyy-MM-dd'T'HH:mm:ssZ - yyyy-MM-dd'T'HH:mm:ss - yyyy-MM-dd'T'HH:mmZ - yyyy-MM-dd'T'HH:mm - yyyy-MM-dd HH:mm:ss.SSSZ - yyyy-MM-dd HH:mm:ss,SSSZ - yyyy-MM-dd HH:mm:ss.SSS - yyyy-MM-dd HH:mm:ss,SSS - yyyy-MM-dd HH:mm:ssZ - yyyy-MM-dd HH:mm:ss - yyyy-MM-dd HH:mmZ - yyyy-MM-dd HH:mm + yyyy-MM-dd'T'HH:mm[:ss[.SSS]][z + yyyy-MM-dd'T'HH:mm[:ss[,SSS]][z + yyyy-MM-dd HH:mm[:ss[.SSS]][z + yyyy-MM-dd HH:mm[:ss[,SSS]][z yyyy-MM-dd diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-add-schema-fields-update-processor-chains.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-add-schema-fields-update-processor-chains.xml index b0b63dfbb6e5..4394d5c7a6e9 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-add-schema-fields-update-processor-chains.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-add-schema-fields-update-processor-chains.xml @@ -179,22 +179,10 @@ - yyyy-MM-dd'T'HH:mm:ss.SSSZ - yyyy-MM-dd'T'HH:mm:ss,SSSZ - yyyy-MM-dd'T'HH:mm:ss.SSS - yyyy-MM-dd'T'HH:mm:ss,SSS - yyyy-MM-dd'T'HH:mm:ssZ - yyyy-MM-dd'T'HH:mm:ss - yyyy-MM-dd'T'HH:mmZ - yyyy-MM-dd'T'HH:mm - yyyy-MM-dd HH:mm:ss.SSSZ - yyyy-MM-dd HH:mm:ss,SSSZ - yyyy-MM-dd HH:mm:ss.SSS - yyyy-MM-dd HH:mm:ss,SSS - yyyy-MM-dd HH:mm:ssZ - yyyy-MM-dd HH:mm:ss - yyyy-MM-dd HH:mmZ - yyyy-MM-dd HH:mm + yyyy-MM-dd'T'HH:mm[:ss[.SSS]][z + yyyy-MM-dd'T'HH:mm[:ss[,SSS]][z + yyyy-MM-dd HH:mm[:ss[.SSS]][z + yyyy-MM-dd HH:mm[:ss[,SSS]][z yyyy-MM-dd diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml index f5d09a4ebff0..83be4eef7892 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml @@ -65,8 +65,7 @@ America/New_York en_US - yyyy-MM-dd'T'HH:mm:ss.SSSz - yyyy-MM-dd'T'HH:mm:ss.SSS + yyyy-MM-dd'T'HH:mm:ss.SSS[z] @@ -85,28 +84,14 @@ UTC en_US - yyyy-MM-dd'T'HH:mm:ss.SSSz - yyyy-MM-dd'T'HH:mm:ss,SSSz - yyyy-MM-dd'T'HH:mm:ss.SSS - yyyy-MM-dd'T'HH:mm:ss,SSS - yyyy-MM-dd'T'HH:mm:ssz - yyyy-MM-dd'T'HH:mm:ss - yyyy-MM-dd'T'HH:mmz - yyyy-MM-dd'T'HH:mm - yyyy-MM-dd HH:mm:ss.SSSz - yyyy-MM-dd HH:mm:ss,SSSz - yyyy-MM-dd HH:mm:ss.SSS - yyyy-MM-dd HH:mm:ss,SSS - yyyy-MM-dd HH:mm:ssz - yyyy-MM-dd HH:mm:ss - yyyy-MM-dd HH:mmz - yyyy-MM-dd HH:mm - yyyy-MM-dd hh:mm a - yyyy-MM-dd hh:mma + yyyy-MM-dd'T'HH:mm[:ss[.SSS]][z + yyyy-MM-dd'T'HH:mm[:ss[,SSS]][z + yyyy-MM-dd HH:mm[:ss[.SSS]][z + yyyy-MM-dd HH:mm[:ss[,SSS]][z yyyy-MM-dd - EEE MMM dd HH:mm:ss z yyyy - EEE MMM dd HH:mm:ss yyyy z - EEE MMM dd HH:mm:ss yyyy + yyyy-MM-dd hh:mm[ ]a + EEE MMM dd HH:mm:ss ZZZ yyyy + EEE MMM dd HH:mm:ss yyyy[ z] EEE, dd MMM yyyy HH:mm:ss z EEEE, dd-MMM-yy HH:mm:ss z EEEE, MMMM dd, yyyy diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-schemaless.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-schemaless.xml index 4f10a8e0e62f..446f3f0feb2d 100644 --- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-schemaless.xml +++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-schemaless.xml @@ -61,22 +61,10 @@ - yyyy-MM-dd'T'HH:mm:ss.SSSZ - yyyy-MM-dd'T'HH:mm:ss,SSSZ - yyyy-MM-dd'T'HH:mm:ss.SSS - yyyy-MM-dd'T'HH:mm:ss,SSS - yyyy-MM-dd'T'HH:mm:ssZ - yyyy-MM-dd'T'HH:mm:ss - yyyy-MM-dd'T'HH:mmZ - yyyy-MM-dd'T'HH:mm - yyyy-MM-dd HH:mm:ss.SSSZ - yyyy-MM-dd HH:mm:ss,SSSZ - yyyy-MM-dd HH:mm:ss.SSS - yyyy-MM-dd HH:mm:ss,SSS - yyyy-MM-dd HH:mm:ssZ - yyyy-MM-dd HH:mm:ss - yyyy-MM-dd HH:mmZ - yyyy-MM-dd HH:mm + yyyy-MM-dd'T'HH:mm[:ss[.SSS]][z + yyyy-MM-dd'T'HH:mm[:ss[,SSS]][z + yyyy-MM-dd HH:mm[:ss[.SSS]][z + yyyy-MM-dd HH:mm[:ss[,SSS]][z yyyy-MM-dd diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/solrconfig.xml b/solr/core/src/test-files/solr/configsets/_default/conf/solrconfig.xml index 51f2c639c649..d393316f2074 100644 --- a/solr/core/src/test-files/solr/configsets/_default/conf/solrconfig.xml +++ b/solr/core/src/test-files/solr/configsets/_default/conf/solrconfig.xml @@ -1141,22 +1141,10 @@ - yyyy-MM-dd'T'HH:mm:ss.SSSZ - yyyy-MM-dd'T'HH:mm:ss,SSSZ - yyyy-MM-dd'T'HH:mm:ss.SSS - yyyy-MM-dd'T'HH:mm:ss,SSS - yyyy-MM-dd'T'HH:mm:ssZ - yyyy-MM-dd'T'HH:mm:ss - yyyy-MM-dd'T'HH:mmZ - yyyy-MM-dd'T'HH:mm - yyyy-MM-dd HH:mm:ss.SSSZ - yyyy-MM-dd HH:mm:ss,SSSZ - yyyy-MM-dd HH:mm:ss.SSS - yyyy-MM-dd HH:mm:ss,SSS - yyyy-MM-dd HH:mm:ssZ - yyyy-MM-dd HH:mm:ss - yyyy-MM-dd HH:mmZ - yyyy-MM-dd HH:mm + yyyy-MM-dd'T'HH:mm[:ss[.SSS]][z + yyyy-MM-dd'T'HH:mm[:ss[,SSS]][z + yyyy-MM-dd HH:mm[:ss[.SSS]][z + yyyy-MM-dd HH:mm[:ss[,SSS]][z yyyy-MM-dd diff --git a/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java b/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java index 7ba195304fa5..9dcb55987c6f 100644 --- a/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java +++ b/solr/core/src/test/org/apache/solr/update/processor/ParsingFieldUpdateProcessorsTest.java @@ -167,52 +167,50 @@ public void testParseUSPacificDate() throws Exception { } public void testParseDateFormats() throws Exception { - // format examples are duplicated from config in solrconfig-parsing-update-processor-chains.xml String[] formatExamples = { - "yyyy-MM-dd'T'HH:mm:ss.SSSz", "2010-01-15T00:00:00.000Z", - "yyyy-MM-dd'T'HH:mm:ss,SSSz", "2010-01-15T00:00:00,000Z", - "yyyy-MM-dd'T'HH:mm:ss.SSS", "2010-01-15T00:00:00.000", - "yyyy-MM-dd'T'HH:mm:ss,SSS", "2010-01-15T00:00:00,000", - "yyyy-MM-dd'T'HH:mm:ssz", "2010-01-15T00:00:00Z", - "yyyy-MM-dd'T'HH:mm:ss", "2010-01-15T00:00:00", - "yyyy-MM-dd'T'HH:mmz", "2010-01-15T00:00Z", - "yyyy-MM-dd'T'HH:mm", "2010-01-15T00:00", - "yyyy-MM-dd HH:mm:ss.SSSz", "2010-01-15 00:00:00.000Z", - "yyyy-MM-dd HH:mm:ss,SSSz", "2010-01-15 00:00:00,000Z", - "yyyy-MM-dd HH:mm:ss.SSS", "2010-01-15 00:00:00.000", - "yyyy-MM-dd HH:mm:ss,SSS", "2010-01-15 00:00:00,000", - "yyyy-MM-dd HH:mm:ssz", "2010-01-15 00:00:00Z", - "yyyy-MM-dd HH:mm:ss", "2010-01-15 00:00:00", - "yyyy-MM-dd HH:mmz", "2010-01-15 00:00Z", - "yyyy-MM-dd HH:mm", "2010-01-15 00:00", - "yyyy-MM-dd hh:mm a", "2010-01-15 12:00 AM", - "yyyy-MM-dd hh:mma", "2010-01-15 12:00AM", - "yyyy-MM-dd", "2010-01-15", - "EEE MMM dd HH:mm:ss ZZZ yyyy", "Fri Jan 15 00:00:00 +0000 2010", - "EEE MMM dd HH:mm:ss yyyy z", "Fri Jan 15 00:00:00 2010 +00:00", - "EEE MMM dd HH:mm:ss yyyy", "Fri Jan 15 00:00:00 2010", - "EEE, dd MMM yyyy HH:mm:ss z", "Fri, 15 Jan 2010 00:00:00 +00:00", - "EEEE, dd-MMM-yy HH:mm:ss z", "Friday, 15-Jan-10 00:00:00 +00:00", - "EEEE, MMMM dd, yyyy", "Friday, January 15, 2010", - "MMMM dd, yyyy", "January 15, 2010", - "MMM. dd, yyyy", "Jan. 15, 2010" + "2010-01-15T00:00:00.000Z", + "2010-01-15T00:00:00,000Z", + "2010-01-15T00:00:00.000", + "2010-01-15T00:00:00,000", + "2010-01-15T00:00:00Z", + "2010-01-15T00:00:00", + "2010-01-15T00:00Z", + "2010-01-15T00:00", + "2010-01-15 00:00:00.000Z", + "2010-01-15 00:00:00,000Z", + "2010-01-15 00:00:00.000", + "2010-01-15 00:00:00,000", + "2010-01-15 00:00:00Z", + "2010-01-15 00:00:00", + "2010-01-15 00:00Z", + "2010-01-15 00:00", + "2010-01-15 12:00 AM", + "2010-01-15 12:00AM", + "2010-01-15", + "Fri Jan 15 00:00:00 +0000 2010", + "Fri Jan 15 00:00:00 2010 +00:00", + "Fri Jan 15 00:00:00 2010", + "Fri, 15 Jan 2010 00:00:00 +00:00", + "Friday, 15-Jan-10 00:00:00 +00:00", + "Friday, January 15, 2010", + "January 15, 2010", + "Jan. 15, 2010" }; IndexSchema schema = h.getCore().getLatestSchema(); assertNotNull(schema.getFieldOrNull("dateUTC_dt")); // should match "*_dt" dynamic field - Instant expectedInstant = Instant.parse(formatExamples[1]); + Instant expectedInstant = Instant.parse(formatExamples[0]); - for (int i = 0 ; i < formatExamples.length ; i += 2) { - String format = formatExamples[i]; - String dateString = formatExamples[i + 1]; + for (int i = 0 ; i < formatExamples.length ; ++i) { + String dateString = formatExamples[i]; String id = "95" + i; SolrInputDocument d = processAdd("parse-date-UTC-defaultTimeZone-no-run-processor", doc(f("id", id), f("dateUTC_dt", dateString))); assertNotNull(d); - assertTrue("index: " + i + " date '" + dateString + "' with format '" + format + - "' is not mutated to a Date", d.getFieldValue("dateUTC_dt") instanceof Date); - assertEquals("date '" + dateString + "' with format '" + format + "' mismatched milliseconds", + assertTrue("index: " + i + " date '" + dateString + "' is not mutated to a Date", + d.getFieldValue("dateUTC_dt") instanceof Date); + assertEquals("date '" + dateString + "' mismatched milliseconds", expectedInstant, ((Date)d.getFieldValue("dateUTC_dt")).toInstant()); } } diff --git a/solr/example/files/conf/solrconfig.xml b/solr/example/files/conf/solrconfig.xml index bca0df802865..7bc8d3472962 100644 --- a/solr/example/files/conf/solrconfig.xml +++ b/solr/example/files/conf/solrconfig.xml @@ -1161,22 +1161,10 @@ - yyyy-MM-dd'T'HH:mm:ss.SSSZ - yyyy-MM-dd'T'HH:mm:ss,SSSZ - yyyy-MM-dd'T'HH:mm:ss.SSS - yyyy-MM-dd'T'HH:mm:ss,SSS - yyyy-MM-dd'T'HH:mm:ssZ - yyyy-MM-dd'T'HH:mm:ss - yyyy-MM-dd'T'HH:mmZ - yyyy-MM-dd'T'HH:mm - yyyy-MM-dd HH:mm:ss.SSSZ - yyyy-MM-dd HH:mm:ss,SSSZ - yyyy-MM-dd HH:mm:ss.SSS - yyyy-MM-dd HH:mm:ss,SSS - yyyy-MM-dd HH:mm:ssZ - yyyy-MM-dd HH:mm:ss - yyyy-MM-dd HH:mmZ - yyyy-MM-dd HH:mm + yyyy-MM-dd'T'HH:mm[:ss[.SSS]][z + yyyy-MM-dd'T'HH:mm[:ss[,SSS]][z + yyyy-MM-dd HH:mm[:ss[.SSS]][z + yyyy-MM-dd HH:mm[:ss[,SSS]][z yyyy-MM-dd diff --git a/solr/server/solr/configsets/_default/conf/solrconfig.xml b/solr/server/solr/configsets/_default/conf/solrconfig.xml index 51f2c639c649..d393316f2074 100644 --- a/solr/server/solr/configsets/_default/conf/solrconfig.xml +++ b/solr/server/solr/configsets/_default/conf/solrconfig.xml @@ -1141,22 +1141,10 @@ - yyyy-MM-dd'T'HH:mm:ss.SSSZ - yyyy-MM-dd'T'HH:mm:ss,SSSZ - yyyy-MM-dd'T'HH:mm:ss.SSS - yyyy-MM-dd'T'HH:mm:ss,SSS - yyyy-MM-dd'T'HH:mm:ssZ - yyyy-MM-dd'T'HH:mm:ss - yyyy-MM-dd'T'HH:mmZ - yyyy-MM-dd'T'HH:mm - yyyy-MM-dd HH:mm:ss.SSSZ - yyyy-MM-dd HH:mm:ss,SSSZ - yyyy-MM-dd HH:mm:ss.SSS - yyyy-MM-dd HH:mm:ss,SSS - yyyy-MM-dd HH:mm:ssZ - yyyy-MM-dd HH:mm:ss - yyyy-MM-dd HH:mmZ - yyyy-MM-dd HH:mm + yyyy-MM-dd'T'HH:mm[:ss[.SSS]][z + yyyy-MM-dd'T'HH:mm[:ss[,SSS]][z + yyyy-MM-dd HH:mm[:ss[.SSS]][z + yyyy-MM-dd HH:mm[:ss[,SSS]][z yyyy-MM-dd diff --git a/solr/solr-ref-guide/src/schemaless-mode.adoc b/solr/solr-ref-guide/src/schemaless-mode.adoc index b62a92ee0c36..0a2f555bc1bf 100644 --- a/solr/solr-ref-guide/src/schemaless-mode.adoc +++ b/solr/solr-ref-guide/src/schemaless-mode.adoc @@ -103,22 +103,10 @@ To start, you should define it as follows (see the javadoc links below for updat - yyyy-MM-dd'T'HH:mm:ss.SSSZ - yyyy-MM-dd'T'HH:mm:ss,SSSZ - yyyy-MM-dd'T'HH:mm:ss.SSS - yyyy-MM-dd'T'HH:mm:ss,SSS - yyyy-MM-dd'T'HH:mm:ssZ - yyyy-MM-dd'T'HH:mm:ss - yyyy-MM-dd'T'HH:mmZ - yyyy-MM-dd'T'HH:mm - yyyy-MM-dd HH:mm:ss.SSSZ - yyyy-MM-dd HH:mm:ss,SSSZ - yyyy-MM-dd HH:mm:ss.SSS - yyyy-MM-dd HH:mm:ss,SSS - yyyy-MM-dd HH:mm:ssZ - yyyy-MM-dd HH:mm:ss - yyyy-MM-dd HH:mmZ - yyyy-MM-dd HH:mm + yyyy-MM-dd'T'HH:mm[:ss[.SSS]][z + yyyy-MM-dd'T'HH:mm[:ss[,SSS]][z + yyyy-MM-dd HH:mm[:ss[.SSS]][z + yyyy-MM-dd HH:mm[:ss[,SSS]][z yyyy-MM-dd