You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ds...@apache.org on 2016/03/30 20:48:00 UTC

[1/2] lucene-solr:branch_6_0: SOLR-8904: switch from SimpleDateFormat to Instant.parse and format. [value] and ms() and contrib/analytics now call DateMathParser to parse. DateFormatUtil is now removed. (cherry picked from commit 72f5eac)

Repository: lucene-solr
Updated Branches:
  refs/heads/branch_6_0 0db92bf6c -> a47a0baa8


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java b/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java
index 3b99eb8..1bb860e 100644
--- a/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java
+++ b/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java
@@ -36,7 +36,6 @@ import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.schema.SchemaField;
-import org.apache.solr.util.DateFormatUtil;
 import org.apache.solr.util.TimeZoneUtils;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
@@ -790,8 +789,8 @@ public class SimpleFacetsTest extends SolrTestCaseJ4 {
     //note: add_doc duplicates bday to bday_drf and a_tdt to a_drf (date range field)
     add_doc(i, "201",  f, "1976-07-04T12:08:56.235Z", ff, "1900-01-01T"+ooo);
     add_doc(i, "202",  f, "1976-07-05T00:00:00.000Z", ff, "1976-07-01T"+ooo);
-    add_doc(i, "203",  f, "1976-07-15T00:07:67.890Z", ff, "1976-07-04T"+ooo);
-    add_doc(i, "204",  f, "1976-07-21T00:07:67.890Z", ff, "1976-07-05T"+ooo);
+    add_doc(i, "203",  f, "1976-07-15T00:07:57.890Z", ff, "1976-07-04T"+ooo);
+    add_doc(i, "204",  f, "1976-07-21T00:07:57.890Z", ff, "1976-07-05T"+ooo);
     add_doc(i, "205",  f, "1976-07-13T12:12:25.255Z", ff, "1976-07-05T"+xxx);
     add_doc(i, "206",  f, "1976-07-03T17:01:23.456Z", ff, "1976-07-07T"+ooo);
     add_doc(i, "207",  f, "1976-07-12T12:12:25.255Z", ff, "1976-07-13T"+ooo);
@@ -3006,8 +3005,8 @@ public class SimpleFacetsTest extends SolrTestCaseJ4 {
     }
     int gapNum = random().nextInt(100) + 1;
     
-    params.add(FacetParams.FACET_RANGE_START, DateFormatUtil.formatExternal(dates[0]));
-    params.add(FacetParams.FACET_RANGE_END, DateFormatUtil.formatExternal(dates[1]));
+    params.add(FacetParams.FACET_RANGE_START, dates[0].toInstant().toString());
+    params.add(FacetParams.FACET_RANGE_END, dates[1].toInstant().toString());
     params.add(FacetParams.FACET_RANGE_GAP, String.format(Locale.ROOT, "+%d%s", gapNum, gapUnit));
     addCommonRandomRangeParams(params);
     params.add(FacetParams.FACET_RANGE, field);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/test/org/apache/solr/response/TestCSVResponseWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/response/TestCSVResponseWriter.java b/solr/core/src/test/org/apache/solr/response/TestCSVResponseWriter.java
index c9b59d6..d10ea71 100644
--- a/solr/core/src/test/org/apache/solr/response/TestCSVResponseWriter.java
+++ b/solr/core/src/test/org/apache/solr/response/TestCSVResponseWriter.java
@@ -16,16 +16,18 @@
  */
 package org.apache.solr.response;
 
+import java.io.StringWriter;
+import java.time.Instant;
+import java.util.Arrays;
+import java.util.Date;
+
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrDocumentList;
-import org.apache.solr.common.util.DateUtil;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.search.SolrReturnFields;
-import org.junit.*;
-
-import java.io.StringWriter;
-import java.util.Arrays;
+import org.junit.BeforeClass;
+import org.junit.Test;
 
 public class TestCSVResponseWriter extends SolrTestCaseJ4 {
   @BeforeClass
@@ -123,7 +125,7 @@ public class TestCSVResponseWriter extends SolrTestCaseJ4 {
     d.addField("foo_b",false);
     d.addField("foo_f",1.414f);
     d.addField("foo_d",-1.0E300);
-    d.addField("foo_dt", DateUtil.parseDate("2000-01-02T03:04:05Z"));
+    d.addField("foo_dt", new Date(Instant.parse("2000-01-02T03:04:05Z").toEpochMilli()));
     d.addField("score", "2.718");
 
     d = new SolrDocument();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/test/org/apache/solr/schema/DateFieldTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/DateFieldTest.java b/solr/core/src/test/org/apache/solr/schema/DateFieldTest.java
index 8b6ad1d..9e88b6e 100644
--- a/solr/core/src/test/org/apache/solr/schema/DateFieldTest.java
+++ b/solr/core/src/test/org/apache/solr/schema/DateFieldTest.java
@@ -18,24 +18,18 @@ package org.apache.solr.schema;
 
 import java.io.File;
 import java.nio.file.Paths;
-import java.text.ParseException;
 import java.util.Collections;
 import java.util.Date;
-import java.util.Locale;
 
 import org.apache.lucene.index.IndexableField;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.core.SolrConfig;
 import org.apache.solr.core.SolrResourceLoader;
-import org.apache.solr.util.DateFormatUtil;
-import org.apache.solr.util.DateMathParser;
-import org.junit.Ignore;
 
 public class DateFieldTest extends SolrTestCaseJ4 {
   private final String testInstanceDir = TEST_HOME() + File.separator + "collection1";
   private final String testConfHome = testInstanceDir + File.separator + "conf"+ File.separator;
   private TrieDateField f = null;
-  private DateMathParser p = new DateMathParser(DateFormatUtil.UTC, Locale.ROOT);
 
   @Override
   public void setUp()  throws Exception {
@@ -50,142 +44,20 @@ public class DateFieldTest extends SolrTestCaseJ4 {
     f.init(schema, Collections.<String,String>emptyMap());
   }
 
-  public void assertFormatParsed(String expected, String input) throws ParseException {
-    assertEquals("Input: " + input, expected, DateFormatUtil.formatDate(DateFormatUtil.parseMath(new Date(), input)));
-  }
-  
-  public void assertFormatDate(String expected, long input) {
-    assertEquals("Input: " + input, expected, DateFormatUtil.formatDate(new Date(input)));
-  }
-
-  public void testToInternal() throws Exception {
-    assertFormatParsed("1995-12-31T23:59:59.999", "1995-12-31T23:59:59.999666Z");
-    assertFormatParsed("1995-12-31T23:59:59.999", "1995-12-31T23:59:59.999Z");
-    assertFormatParsed("1995-12-31T23:59:59.99", "1995-12-31T23:59:59.99Z");
-    assertFormatParsed("1995-12-31T23:59:59.9", "1995-12-31T23:59:59.9Z");
-    assertFormatParsed("1995-12-31T23:59:59", "1995-12-31T23:59:59Z");
-
-    // here the input isn't in the canonical form, but we should be forgiving
-    assertFormatParsed("1995-12-31T23:59:59.99", "1995-12-31T23:59:59.990Z");
-    assertFormatParsed("1995-12-31T23:59:59.9", "1995-12-31T23:59:59.900Z");
-    assertFormatParsed("1995-12-31T23:59:59.9", "1995-12-31T23:59:59.90Z");
-    assertFormatParsed("1995-12-31T23:59:59", "1995-12-31T23:59:59.000Z");
-    assertFormatParsed("1995-12-31T23:59:59", "1995-12-31T23:59:59.00Z");
-    assertFormatParsed("1995-12-31T23:59:59", "1995-12-31T23:59:59.0Z");
-
-    // kind of kludgy, but we have other tests for the actual date math
-    assertFormatParsed(DateFormatUtil.formatDate(p.parseMath("/DAY")), "NOW/DAY");
-
-    // as of Solr 1.3
-    assertFormatParsed("1995-12-31T00:00:00", "1995-12-31T23:59:59Z/DAY");
-    assertFormatParsed("1995-12-31T00:00:00", "1995-12-31T23:59:59.123Z/DAY");
-    assertFormatParsed("1995-12-31T00:00:00", "1995-12-31T23:59:59.123999Z/DAY");
-  }
-  
-  public void testToInternalObj() throws Exception {
-    assertFormatDate("1995-12-31T23:59:59.999", 820454399999l);
-    assertFormatDate("1995-12-31T23:59:59.99", 820454399990l);
-    assertFormatDate("1995-12-31T23:59:59.9", 820454399900l);
-    assertFormatDate("1995-12-31T23:59:59", 820454399000l);
-  }
-    
-  public void assertParseMath(long expected, String input) {
-    Date d = new Date(0);
-    assertEquals("Input: "+input, expected, DateFormatUtil.parseMath(d, input).getTime());
-  }
-  
-  // as of Solr1.3
-  public void testParseMath() {
-    assertParseMath(820454699999l, "1995-12-31T23:59:59.999765Z+5MINUTES");
-    assertParseMath(820454699999l, "1995-12-31T23:59:59.999Z+5MINUTES");
-    assertParseMath(820454699990l, "1995-12-31T23:59:59.99Z+5MINUTES");
-    assertParseMath(194918400000l, "1976-03-06T03:06:00Z/DAY");
-    
-    // here the input isn't in the canonical form, but we should be forgiving
-    assertParseMath(820454699990l, "1995-12-31T23:59:59.990Z+5MINUTES");
-    assertParseMath(194918400000l, "1976-03-06T03:06:00.0Z/DAY");
-    assertParseMath(194918400000l, "1976-03-06T03:06:00.00Z/DAY");
-    assertParseMath(194918400000l, "1976-03-06T03:06:00.000Z/DAY");
-  }
-
-  public void testFormatter() {
-    // just after epoch
-    assertFormat("1970-01-01T00:00:00.005", 5L);
-    assertFormat("1970-01-01T00:00:00",     0L);
-    assertFormat("1970-01-01T00:00:00.37",  370L);
-    assertFormat("1970-01-01T00:00:00.9",   900L);
-
-    // well after epoch
-    assertFormat("1999-12-31T23:59:59.005", 946684799005L);
-    assertFormat("1999-12-31T23:59:59",     946684799000L);
-    assertFormat("1999-12-31T23:59:59.37",  946684799370L);
-    assertFormat("1999-12-31T23:59:59.9",   946684799900L);
-
-    // waaaay after epoch
-    assertFormat("12345-12-31T23:59:59.005", 327434918399005L);
-    assertFormat("12345-12-31T23:59:59",     327434918399000L);
-    assertFormat("12345-12-31T23:59:59.37",  327434918399370L);
-    assertFormat("12345-12-31T23:59:59.9",   327434918399900L);
-
-    // well before epoch
-    assertFormat("0299-12-31T23:59:59",     -52700112001000L);
-    assertFormat("0299-12-31T23:59:59.123", -52700112000877L);
-    assertFormat("0299-12-31T23:59:59.09",  -52700112000910L);
-
-  }
-
-  /** 
-   * Using dates in the canonical format, verify that parsing+formating 
-   * is an identify function
-   */
-  public void testRoundTrip() throws Exception {
-
-    // typical dates, various precision
-    assertRoundTrip("1995-12-31T23:59:59.987Z");
-    assertRoundTrip("1995-12-31T23:59:59.98Z");
-    assertRoundTrip("1995-12-31T23:59:59.9Z");
-    assertRoundTrip("1995-12-31T23:59:59Z");
-    assertRoundTrip("1976-03-06T03:06:00Z");
-
-    // dates with atypical years
-    assertRoundTrip("0001-01-01T01:01:01Z");
-    assertRoundTrip("12021-12-01T03:03:03Z");
-  }
-
-  @Ignore("SOLR-2773: Non-Positive years don't work")
-  public void testRoundTripNonPositiveYear() throws Exception {
-
-    // :TODO: ambiguity about year zero
-    // assertRoundTrip("0000-04-04T04:04:04Z");
-    
-    // dates with negative years
-    assertRoundTrip("-0005-05-05T05:05:05Z");
-    assertRoundTrip("-2021-12-01T04:04:04Z");
-    assertRoundTrip("-12021-12-01T02:02:02Z");
-    
-    // :TODO: assertFormat and assertToObject some negative years
-
-  }
-
-  protected void assertFormat(final String expected, final long millis) {
-    assertEquals(expected, DateFormatUtil.formatDate(new Date(millis)));
-  }
-
-  protected void assertRoundTrip(String canonicalDate) throws Exception {
-    Date d = DateFormatUtil.parseDate(canonicalDate);
-    String result = DateFormatUtil.formatExternal(d);
-    assertEquals("d:" + d.getTime(), canonicalDate, result);
-
-  }
-
+  // NOTE: Many other tests were moved to DateMathParserTest
 
   public void testCreateField() {
     int props = FieldProperties.INDEXED ^ FieldProperties.STORED;
     SchemaField sf = new SchemaField( "test", f, props, null );
+    // String
     IndexableField out = f.createField(sf, "1995-12-31T23:59:59Z", 1.0f );
-    assertEquals(820454399000l, f.toObject( out ).getTime() );
-    
-    out = f.createField(sf, new Date(820454399000l), 1.0f );
-    assertEquals(820454399000l, f.toObject( out ).getTime() );
+    assertEquals(820454399000L, f.toObject( out ).getTime() );
+    // Date obj
+    out = f.createField(sf, new Date(820454399000L), 1.0f );
+    assertEquals(820454399000L, f.toObject( out ).getTime() );
+    // Date math
+    out = f.createField(sf, "1995-12-31T23:59:59.99Z+5MINUTES", 1.0f);
+    assertEquals(820454699990L, f.toObject( out ).getTime() );
   }
+
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/test/org/apache/solr/schema/TestUseDocValuesAsStored.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/TestUseDocValuesAsStored.java b/solr/core/src/test/org/apache/solr/schema/TestUseDocValuesAsStored.java
index 6352e99..f80e2bb 100644
--- a/solr/core/src/test/org/apache/solr/schema/TestUseDocValuesAsStored.java
+++ b/solr/core/src/test/org/apache/solr/schema/TestUseDocValuesAsStored.java
@@ -22,14 +22,12 @@ import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathFactory;
 import java.io.File;
-
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.time.Instant;
 import java.time.LocalDateTime;
 import java.time.Month;
 import java.time.ZoneOffset;
-import java.time.format.DateTimeFormatter;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Set;
@@ -71,9 +69,9 @@ public class TestUseDocValuesAsStored extends AbstractBadConfigTestBase {
   private static final Pattern STORED_FIELD_NAME_PATTERN = Pattern.compile("_dv$");
 
   static {
-    START_RANDOM_EPOCH_MILLIS = LocalDateTime.of(1970, Month.JANUARY, 1, 0, 0)
+    START_RANDOM_EPOCH_MILLIS = LocalDateTime.of(-11000, Month.JANUARY, 1, 0, 0)// BC
         .toInstant(ZoneOffset.UTC).toEpochMilli();
-    END_RANDOM_EPOCH_MILLIS = LocalDateTime.of(2030, Month.DECEMBER, 31, 23, 59, 59, 999_000_000)
+    END_RANDOM_EPOCH_MILLIS = LocalDateTime.of(11000, Month.DECEMBER, 31, 23, 59, 59, 999_000_000) // AD, 5 digit year
         .toInstant(ZoneOffset.UTC).toEpochMilli();
     try {
       DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
@@ -216,8 +214,7 @@ public class TestUseDocValuesAsStored extends AbstractBadConfigTestBase {
         }
         case "date": {
           long epochMillis = TestUtil.nextLong(random(), START_RANDOM_EPOCH_MILLIS, END_RANDOM_EPOCH_MILLIS);
-          LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(epochMillis), ZoneOffset.UTC);
-          values[i] = dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + 'Z';
+          values[i] = Instant.ofEpochMilli(epochMillis).toString();
           break;
         }
         default: throw new Exception("unknown type '" + valueType + "'");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/test/org/apache/solr/update/processor/AtomicUpdatesTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/update/processor/AtomicUpdatesTest.java b/solr/core/src/test/org/apache/solr/update/processor/AtomicUpdatesTest.java
index 09fa721..e1726f8 100644
--- a/solr/core/src/test/org/apache/solr/update/processor/AtomicUpdatesTest.java
+++ b/solr/core/src/test/org/apache/solr/update/processor/AtomicUpdatesTest.java
@@ -24,7 +24,7 @@ import com.google.common.collect.ImmutableMap;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.schema.TrieDateField;
-import org.apache.solr.util.DateFormatUtil;
+import org.apache.solr.util.DateMathParser;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
@@ -597,45 +597,45 @@ public class AtomicUpdatesTest extends SolrTestCaseJ4 {
     doc = new SolrInputDocument();
     doc.setField("id", "10001");
     TrieDateField trieDF = new TrieDateField();
-    Date tempDate = DateFormatUtil.parseMath(null, "2014-02-01T12:00:00Z");
-    doc.setField("dateRemove", new Date[]{DateFormatUtil.parseMath(null, "2014-02-01T12:00:00Z"), 
-        DateFormatUtil.parseMath(null, "2014-07-02T12:00:00Z"),
-        DateFormatUtil.parseMath(null, "2014-02-03T12:00:00Z"),
-        DateFormatUtil.parseMath(null, "2014-02-03T12:00:00Z"),
-        DateFormatUtil.parseMath(null, "2014-02-04T12:00:00Z")
+    Date tempDate = DateMathParser.parseMath(null, "2014-02-01T12:00:00Z");
+    doc.setField("dateRemove", new Date[]{DateMathParser.parseMath(null, "2014-02-01T12:00:00Z"),
+        DateMathParser.parseMath(null, "2014-07-02T12:00:00Z"),
+        DateMathParser.parseMath(null, "2014-02-03T12:00:00Z"),
+        DateMathParser.parseMath(null, "2014-02-03T12:00:00Z"),
+        DateMathParser.parseMath(null, "2014-02-04T12:00:00Z")
         });
     assertU(adoc(doc));
 
     doc = new SolrInputDocument();
     doc.setField("id", "10002");
-    doc.setField("dateRemove", new Date[]{DateFormatUtil.parseMath(null, "2014-02-01T12:00:00Z"), 
-        DateFormatUtil.parseMath(null, "2014-07-02T12:00:00Z"),
-        DateFormatUtil.parseMath(null, "2014-02-02T12:00:00Z"),
-        DateFormatUtil.parseMath(null, "2014-02-03T12:00:00Z"),
-        DateFormatUtil.parseMath(null, "2014-02-04T12:00:00Z")
+    doc.setField("dateRemove", new Date[]{DateMathParser.parseMath(null, "2014-02-01T12:00:00Z"),
+        DateMathParser.parseMath(null, "2014-07-02T12:00:00Z"),
+        DateMathParser.parseMath(null, "2014-02-02T12:00:00Z"),
+        DateMathParser.parseMath(null, "2014-02-03T12:00:00Z"),
+        DateMathParser.parseMath(null, "2014-02-04T12:00:00Z")
         });
     assertU(adoc(doc));
 
     doc = new SolrInputDocument();
     doc.setField("id", "10020");
-    doc.setField("dateRemove", new Date[]{DateFormatUtil.parseMath(null, "2014-02-01T12:00:00Z"), 
-        DateFormatUtil.parseMath(null, "2014-02-03T12:00:00Z"),
-        DateFormatUtil.parseMath(null, "2014-02-04T12:00:00Z")
+    doc.setField("dateRemove", new Date[]{DateMathParser.parseMath(null, "2014-02-01T12:00:00Z"),
+        DateMathParser.parseMath(null, "2014-02-03T12:00:00Z"),
+        DateMathParser.parseMath(null, "2014-02-04T12:00:00Z")
         });
     assertU(adoc(doc));
 
     doc = new SolrInputDocument();
     doc.setField("id", "10021");
-    doc.setField("dateRemove", new Date[]{DateFormatUtil.parseMath(null, "2014-02-01T12:00:00Z"), 
-        DateFormatUtil.parseMath(null, "2014-02-02T12:00:00Z"),
-        DateFormatUtil.parseMath(null, "2014-02-04T12:00:00Z")
+    doc.setField("dateRemove", new Date[]{DateMathParser.parseMath(null, "2014-02-01T12:00:00Z"),
+        DateMathParser.parseMath(null, "2014-02-02T12:00:00Z"),
+        DateMathParser.parseMath(null, "2014-02-04T12:00:00Z")
         });
     assertU(adoc(doc));
 
     assertU(commit());
 
     assertQ(req("q", "dateRemove:*", "indent", "true"), "//result[@numFound = '4']");
-    String dateString = DateFormatUtil.parseMath(null, "2014-02-02T12:00:00Z").toString();
+    String dateString = DateMathParser.parseMath(null, "2014-02-02T12:00:00Z").toString();
 //    assertQ(req("q", "dateRemove:"+URLEncoder.encode(dateString, "UTF-8"), "indent", "true"), "//result[@numFound = '3']");
 //    assertQ(req("q", "dateRemove:\"2014-09-02T12:00:00Z\"", "indent", "true"), "//result[@numFound = '3']");
 //    assertQ(req("q", "dateRemove:"+dateString, "indent", "true"), "//result[@numFound = '3']"); //Sun Feb 02 10:00:00 FNT 2014
@@ -645,8 +645,8 @@ public class AtomicUpdatesTest extends SolrTestCaseJ4 {
     doc = new SolrInputDocument();
     doc.setField("id", "10001");
     List<Date> removeList = new ArrayList<Date>();
-    removeList.add(DateFormatUtil.parseMath(null, "2014-09-02T12:00:00Z"));
-    removeList.add(DateFormatUtil.parseMath(null, "2014-09-03T12:00:00Z"));
+    removeList.add(DateMathParser.parseMath(null, "2014-09-02T12:00:00Z"));
+    removeList.add(DateMathParser.parseMath(null, "2014-09-03T12:00:00Z"));
 
     doc.setField("dateRemove", ImmutableMap.of("remove", removeList)); //behavior when hitting Solr through ZK
     assertU(adoc(doc));
@@ -658,8 +658,8 @@ public class AtomicUpdatesTest extends SolrTestCaseJ4 {
     doc = new SolrInputDocument();
     doc.setField("id", "10021");
     removeList = new ArrayList<Date>();
-    removeList.add(DateFormatUtil.parseMath(null, "2014-09-02T12:00:00Z"));
-    removeList.add(DateFormatUtil.parseMath(null, "2014-09-03T12:00:00Z"));
+    removeList.add(DateMathParser.parseMath(null, "2014-09-02T12:00:00Z"));
+    removeList.add(DateMathParser.parseMath(null, "2014-09-03T12:00:00Z"));
     doc.setField("dateRemove", ImmutableMap.of("remove", removeList)); //behavior when hitting Solr through ZK
     assertU(adoc(doc));
     assertU(commit());
@@ -669,7 +669,7 @@ public class AtomicUpdatesTest extends SolrTestCaseJ4 {
 
     doc = new SolrInputDocument();
     doc.setField("id", "10001");
-    doc.setField("dateRemove", ImmutableMap.of("remove", DateFormatUtil.parseMath(null, "2014-09-01T12:00:00Z"))); //behavior when hitting Solr directly
+    doc.setField("dateRemove", ImmutableMap.of("remove", DateMathParser.parseMath(null, "2014-09-01T12:00:00Z"))); //behavior when hitting Solr directly
 
     assertU(adoc(doc));
     assertU(commit());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/test/org/apache/solr/util/DateMathParserTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/util/DateMathParserTest.java b/solr/core/src/test/org/apache/solr/util/DateMathParserTest.java
index c3623e8..726c71c 100644
--- a/solr/core/src/test/org/apache/solr/util/DateMathParserTest.java
+++ b/solr/core/src/test/org/apache/solr/util/DateMathParserTest.java
@@ -16,20 +16,20 @@
  */
 package org.apache.solr.util;
 
-import static org.apache.solr.util.DateFormatUtil.UTC;
-
-import org.apache.lucene.util.LuceneTestCase;
-import org.apache.solr.util.DateMathParser;
-
-import java.text.SimpleDateFormat;
 import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.Instant;
 import java.util.Calendar;
 import java.util.Date;
-import java.util.TimeZone;
+import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
-import java.util.HashMap;
-import java.text.ParseException;
+import java.util.TimeZone;
+
+import org.apache.lucene.util.LuceneTestCase;
+
+import static org.apache.solr.util.DateMathParser.UTC;
 
 /**
  * Tests that the functions in DateMathParser
@@ -333,6 +333,111 @@ public class DateMathParserTest extends LuceneTestCase {
     }
     
   }
-    
+
+  /*
+  PARSING / FORMATTING (without date math)  Formerly in DateFieldTest.
+   */
+
+
+  public void testFormatter() {
+    assertFormat("1995-12-31T23:59:59.999Z", 820454399999l);
+    assertFormat("1995-12-31T23:59:59.990Z", 820454399990l);
+    assertFormat("1995-12-31T23:59:59.900Z", 820454399900l);
+    assertFormat("1995-12-31T23:59:59Z", 820454399000l);
+
+    // just after epoch
+    assertFormat("1970-01-01T00:00:00.005Z", 5L);
+    assertFormat("1970-01-01T00:00:00Z",     0L);
+    assertFormat("1970-01-01T00:00:00.370Z",  370L);
+    assertFormat("1970-01-01T00:00:00.900Z",   900L);
+
+    // well after epoch
+    assertFormat("1999-12-31T23:59:59.005Z", 946684799005L);
+    assertFormat("1999-12-31T23:59:59Z",     946684799000L);
+    assertFormat("1999-12-31T23:59:59.370Z",  946684799370L);
+    assertFormat("1999-12-31T23:59:59.900Z",   946684799900L);
+
+    // waaaay after epoch  ('+' is required for more than 4 digits in a year)
+    assertFormat("+12345-12-31T23:59:59.005Z", 327434918399005L);
+    assertFormat("+12345-12-31T23:59:59Z",     327434918399000L);
+    assertFormat("+12345-12-31T23:59:59.370Z",  327434918399370L);
+    assertFormat("+12345-12-31T23:59:59.900Z",   327434918399900L);
+
+    // well before epoch
+    assertFormat("0299-12-31T23:59:59Z",     -52700112001000L);
+    assertFormat("0299-12-31T23:59:59.123Z", -52700112000877L);
+    assertFormat("0299-12-31T23:59:59.090Z",  -52700112000910L);
+
+    // BC (negative years)
+    assertFormat("-12021-12-01T02:02:02Z", Instant.parse("-12021-12-01T02:02:02Z").toEpochMilli());
+  }
+
+  private void assertFormat(final String expected, final long millis) {
+    assertEquals(expected, Instant.ofEpochMilli(millis).toString());
+  }
+
+  /**
+   * Using dates in the canonical format, verify that parsing+formatting
+   * is an identify function
+   */
+  public void testRoundTrip() throws Exception {
+    // NOTE: the 2nd arg is what the round trip result looks like (may be null if same as input)
+
+    assertParseFormatEquals("1995-12-31T23:59:59.999666Z",  "1995-12-31T23:59:59.999Z"); // beyond millis is truncated
+    assertParseFormatEquals("1995-12-31T23:59:59.999Z",     "1995-12-31T23:59:59.999Z");
+    assertParseFormatEquals("1995-12-31T23:59:59.99Z",      "1995-12-31T23:59:59.990Z");
+    assertParseFormatEquals("1995-12-31T23:59:59.9Z",       "1995-12-31T23:59:59.900Z");
+    assertParseFormatEquals("1995-12-31T23:59:59Z",         "1995-12-31T23:59:59Z");
+
+    // here the input isn't in the canonical form, but we should be forgiving
+    assertParseFormatEquals("1995-12-31T23:59:59.990Z", "1995-12-31T23:59:59.990Z");
+    assertParseFormatEquals("1995-12-31T23:59:59.900Z", "1995-12-31T23:59:59.900Z");
+    assertParseFormatEquals("1995-12-31T23:59:59.90Z",  "1995-12-31T23:59:59.900Z");
+    assertParseFormatEquals("1995-12-31T23:59:59.000Z", "1995-12-31T23:59:59Z");
+    assertParseFormatEquals("1995-12-31T23:59:59.00Z",  "1995-12-31T23:59:59Z");
+    assertParseFormatEquals("1995-12-31T23:59:59.0Z",   "1995-12-31T23:59:59Z");
+
+    // kind of kludgy, but we have other tests for the actual date math
+    //assertParseFormatEquals("NOW/DAY", p.parseMath("/DAY").toInstant().toString());
+
+    // as of Solr 1.3
+    assertParseFormatEquals("1995-12-31T23:59:59Z/DAY", "1995-12-31T00:00:00Z");
+    assertParseFormatEquals("1995-12-31T23:59:59.123Z/DAY", "1995-12-31T00:00:00Z");
+    assertParseFormatEquals("1995-12-31T23:59:59.123999Z/DAY", "1995-12-31T00:00:00Z");
+
+    // typical dates, various precision  (0,1,2,3 digits of millis)
+    assertParseFormatEquals("1995-12-31T23:59:59.987Z", null);
+    assertParseFormatEquals("1995-12-31T23:59:59.98Z", "1995-12-31T23:59:59.980Z");//add 0 ms
+    assertParseFormatEquals("1995-12-31T23:59:59.9Z",  "1995-12-31T23:59:59.900Z");//add 00 ms
+    assertParseFormatEquals("1995-12-31T23:59:59Z", null);
+    assertParseFormatEquals("1976-03-06T03:06:00Z", null);
+    assertParseFormatEquals("1995-12-31T23:59:59.987654Z", "1995-12-31T23:59:59.987Z");//truncate nanoseconds off
+
+    // dates with atypical years
+    assertParseFormatEquals("0001-01-01T01:01:01Z", null);
+    assertParseFormatEquals("+12021-12-01T03:03:03Z", null);
+
+    assertParseFormatEquals("0000-04-04T04:04:04Z", null); // note: 0 AD is also known as 1 BC
+
+    // dates with negative years (BC)
+    assertParseFormatEquals("-0005-05-05T05:05:05Z", null);
+    assertParseFormatEquals("-2021-12-01T04:04:04Z", null);
+    assertParseFormatEquals("-12021-12-01T02:02:02Z", null);
+  }
+
+  public void testParseLenient() throws Exception {
+    // dates that only parse thanks to lenient mode of DateTimeFormatter
+    assertParseFormatEquals("10995-12-31T23:59:59.990Z", "+10995-12-31T23:59:59.990Z"); // missing '+' 5 digit year
+    assertParseFormatEquals("995-1-2T3:4:5Z", "0995-01-02T03:04:05Z"); // wasn't 0 padded
+  }
+
+  private void assertParseFormatEquals(String inputStr, String expectedStr) {
+    if (expectedStr == null) {
+      expectedStr = inputStr;
+    }
+    Date inputDate = DateMathParser.parseMath(null, inputStr);
+    String resultStr = inputDate.toInstant().toString();
+    assertEquals("d:" + inputDate.getTime(), expectedStr, resultStr);
+  }
 }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/solrj/src/java/org/apache/solr/client/solrj/SolrQuery.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/SolrQuery.java b/solr/solrj/src/java/org/apache/solr/client/solrj/SolrQuery.java
index d41673d..be70210 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/SolrQuery.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/SolrQuery.java
@@ -16,14 +16,6 @@
  */
 package org.apache.solr.client.solrj;
 
-import org.apache.solr.common.params.CommonParams;
-import org.apache.solr.common.params.FacetParams;
-import org.apache.solr.common.params.HighlightParams;
-import org.apache.solr.common.params.ModifiableSolrParams;
-import org.apache.solr.common.params.StatsParams;
-import org.apache.solr.common.params.TermsParams;
-import org.apache.solr.common.util.DateUtil;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
@@ -31,6 +23,13 @@ import java.util.List;
 import java.util.Locale;
 import java.util.regex.Pattern;
 
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.FacetParams;
+import org.apache.solr.common.params.HighlightParams;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.params.StatsParams;
+import org.apache.solr.common.params.TermsParams;
+
 
 /**
  * This is an augmented SolrParams with get/set/add fields for common fields used
@@ -266,9 +265,9 @@ public class SolrQuery extends ModifiableSolrParams
    */
   public SolrQuery addDateRangeFacet(String field, Date start, Date end, String gap) {
     add(FacetParams.FACET_RANGE, field);
-    add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_START), DateUtil.getThreadLocalDateFormat().format(start));
-    add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_END), DateUtil.getThreadLocalDateFormat().format(end));
-    add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_GAP), gap);
+    add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_START), start.toInstant().toString());
+    add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_END),   end.toInstant().toString());
+    add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_GAP),   gap);
     this.set(FacetParams.FACET, true);
     return this;
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/solrj/src/java/org/apache/solr/client/solrj/impl/XMLResponseParser.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/XMLResponseParser.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/XMLResponseParser.java
index e794dab..272335a 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/XMLResponseParser.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/XMLResponseParser.java
@@ -16,31 +16,30 @@
  */
 package org.apache.solr.client.solrj.impl;
 
-import org.apache.solr.client.solrj.ResponseParser;
-import org.apache.solr.common.SolrDocument;
-import org.apache.solr.common.SolrDocumentList;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.util.DateUtil;
-import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.solr.common.util.XMLErrorLogger;
-import org.apache.solr.common.EmptyEntityResolver;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamConstants;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
-
 import java.io.InputStream;
 import java.io.Reader;
 import java.lang.invoke.MethodHandles;
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Locale;
 
+import org.apache.solr.client.solrj.ResponseParser;
+import org.apache.solr.common.EmptyEntityResolver;
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.common.SolrDocumentList;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.common.util.XMLErrorLogger;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 /**
  * 
  *
@@ -173,7 +172,7 @@ public class XMLResponseParser extends ResponseParser
       @Override 
       public Date read( String txt ) { 
         try {
-          return DateUtil.parseDate(txt);      
+          return new Date(Instant.parse(txt).toEpochMilli());
         }
         catch( Exception ex ) {
           ex.printStackTrace();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java b/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java
index 31d54a8..beed40e 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java
@@ -16,16 +16,6 @@
  */
 package org.apache.solr.client.solrj.util;
 
-import org.apache.solr.common.SolrDocument;
-import org.apache.solr.common.SolrInputDocument;
-import org.apache.solr.common.SolrInputField;
-import org.apache.solr.common.cloud.Slice;
-import org.apache.solr.common.util.Base64;
-import org.apache.solr.common.util.ContentStream;
-import org.apache.solr.common.util.ContentStreamBase;
-import org.apache.solr.common.util.DateUtil;
-import org.apache.solr.common.util.XML;
-
 import java.io.IOException;
 import java.io.StringWriter;
 import java.io.Writer;
@@ -36,6 +26,14 @@ import java.util.Date;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import org.apache.solr.common.SolrInputDocument;
+import org.apache.solr.common.SolrInputField;
+import org.apache.solr.common.cloud.Slice;
+import org.apache.solr.common.util.Base64;
+import org.apache.solr.common.util.ContentStream;
+import org.apache.solr.common.util.ContentStreamBase;
+import org.apache.solr.common.util.XML;
+
 
 /**
  *
@@ -111,7 +109,7 @@ public class ClientUtils
 
   private static void writeVal(Writer writer, float boost, String name, Object v, String update) throws IOException {
     if (v instanceof Date) {
-      v = DateUtil.getThreadLocalDateFormat().format( (Date)v );
+      v = ((Date)v).toInstant().toString();
     } else if (v instanceof byte[]) {
       byte[] bytes = (byte[]) v;
       v = Base64.byteArrayToBase64(bytes, 0, bytes.length);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/solrj/src/test/org/apache/solr/client/solrj/SolrQueryTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrQueryTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrQueryTest.java
index 43fdff4..816a2cc 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrQueryTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrQueryTest.java
@@ -16,14 +16,6 @@
  */
 package org.apache.solr.client.solrj;
 
-import org.apache.lucene.util.LuceneTestCase;
-import org.apache.solr.client.solrj.SolrQuery.SortClause;
-import org.apache.solr.common.params.CommonParams;
-import org.apache.solr.common.params.FacetParams;
-
-import junit.framework.Assert;
-import org.apache.solr.common.util.DateUtil;
-
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.ObjectOutputStream;
@@ -33,6 +25,12 @@ import java.util.Date;
 import java.util.Locale;
 import java.util.TimeZone;
 
+import junit.framework.Assert;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.solr.client.solrj.SolrQuery.SortClause;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.FacetParams;
+
 /**
  * 
  *
@@ -301,8 +299,8 @@ public class SolrQueryTest extends LuceneTestCase {
     q.addDateRangeFacet("field", start, end, "+1MONTH");
     assertEquals("true", q.get(FacetParams.FACET));
     assertEquals("field", q.get(FacetParams.FACET_RANGE));
-    assertEquals(DateUtil.getThreadLocalDateFormat().format(start), q.get("f.field." + FacetParams.FACET_RANGE_START));
-    assertEquals(DateUtil.getThreadLocalDateFormat().format(end), q.get("f.field." + FacetParams.FACET_RANGE_END));
+    assertEquals(start.toInstant().toString(), q.get("f.field." + FacetParams.FACET_RANGE_START));
+    assertEquals(end.toInstant().toString(), q.get("f.field." + FacetParams.FACET_RANGE_END));
     assertEquals("+1MONTH", q.get("f.field." + FacetParams.FACET_RANGE_GAP));
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java
index 1eea454..7a69815 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/response/QueryResponseTest.java
@@ -20,6 +20,8 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.nio.charset.StandardCharsets;
+import java.time.Instant;
+import java.util.Date;
 import java.util.List;
 
 import junit.framework.Assert;
@@ -27,7 +29,6 @@ import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.TestRuleLimitSysouts.Limit;
 import org.apache.solr.client.solrj.impl.XMLResponseParser;
 import org.apache.solr.common.SolrDocumentList;
-import org.apache.solr.common.util.DateUtil;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.core.SolrResourceLoader;
 import org.junit.Test;
@@ -82,8 +83,8 @@ public class QueryResponseTest extends LuceneTestCase {
     assertEquals("4.0", price.getCounts().get(4).getValue());
     assertEquals(0, price.getCounts().get(4).getCount());
 
-    assertEquals(DateUtil.parseDate("2005-02-13T15:26:37Z"), manufacturedateDt.getStart());
-    assertEquals(DateUtil.parseDate("2008-02-13T15:26:37Z"), manufacturedateDt.getEnd());
+    assertEquals(new Date(Instant.parse("2005-02-13T15:26:37Z").toEpochMilli()), manufacturedateDt.getStart());
+    assertEquals(new Date(Instant.parse("2008-02-13T15:26:37Z").toEpochMilli()), manufacturedateDt.getEnd());
     assertEquals("+1YEAR", manufacturedateDt.getGap());
     assertEquals("2005-02-13T15:26:37Z", manufacturedateDt.getCounts().get(0).getValue());
     assertEquals(4, manufacturedateDt.getCounts().get(0).getCount());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
----------------------------------------------------------------------
diff --git a/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
index 812663e..a751459 100644
--- a/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
+++ b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
@@ -16,8 +16,31 @@
  */
 package org.apache.solr;
 
-import junit.framework.Assert;
+import javax.servlet.Filter;
+import java.io.File;
+import java.io.IOException;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.invoke.MethodHandles;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Random;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.concurrent.atomic.AtomicInteger;
 
+import junit.framework.Assert;
 import org.apache.commons.io.FileUtils;
 import org.apache.lucene.util.Constants;
 import org.apache.lucene.util.TestUtil;
@@ -26,7 +49,6 @@ import org.apache.solr.client.solrj.SolrResponse;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.embedded.JettyConfig;
 import org.apache.solr.client.solrj.embedded.JettySolrRunner;
-import org.apache.solr.client.solrj.impl.HttpClientUtil;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.UpdateRequest;
 import org.apache.solr.client.solrj.response.QueryResponse;
@@ -37,7 +59,6 @@ import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.NamedList;
-import org.apache.solr.util.DateFormatUtil;
 import org.eclipse.jetty.servlet.ServletHolder;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -48,31 +69,6 @@ import org.junit.runners.model.Statement;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.servlet.Filter;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.invoke.MethodHandles;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Random;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.concurrent.atomic.AtomicInteger;
-
 /**
  * Helper base class for distributed search test cases
  *
@@ -1086,7 +1082,7 @@ public abstract class BaseDistributedSearchTestCase extends SolrTestCaseJ4 {
     public Object val() {
       long v = r.nextLong();
       Date d = new Date(v);
-      return DateFormatUtil.formatExternal(d);
+      return d.toInstant().toString();
     }
   }
   

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
----------------------------------------------------------------------
diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
index 6e511d7..3ce252f 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
@@ -37,7 +37,18 @@ import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.*;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
 import java.util.logging.Level;
 
 import com.carrotsearch.randomizedtesting.RandomizedContext;
@@ -86,7 +97,6 @@ import org.apache.solr.schema.SchemaField;
 import org.apache.solr.search.SolrIndexSearcher;
 import org.apache.solr.servlet.DirectSolrConnection;
 import org.apache.solr.util.AbstractSolrTestCase;
-import org.apache.solr.util.DateFormatUtil;
 import org.apache.solr.util.RefCounted;
 import org.apache.solr.util.RevertDefaultThreadHandlerRule;
 import org.apache.solr.util.SSLTestConfig;
@@ -2036,7 +2046,7 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
    * @see #randomSkewedDate
    */
   public static String randomDate() {
-    return DateFormatUtil.formatExternal(new Date(random().nextLong()));
+    return Instant.ofEpochMilli(random().nextLong()).toString();
   }
 
   /** 


[2/2] lucene-solr:branch_6_0: SOLR-8904: switch from SimpleDateFormat to Instant.parse and format. [value] and ms() and contrib/analytics now call DateMathParser to parse. DateFormatUtil is now removed. (cherry picked from commit 72f5eac)

Posted by ds...@apache.org.
SOLR-8904: switch from SimpleDateFormat to Instant.parse and format.
[value] and ms() and contrib/analytics now call DateMathParser to parse.  DateFormatUtil is now removed.
(cherry picked from commit 72f5eac)


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/a47a0baa
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/a47a0baa
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/a47a0baa

Branch: refs/heads/branch_6_0
Commit: a47a0baa829ee18b30cc391a229b96d85c865ea0
Parents: 0db92bf
Author: David Smiley <ds...@apache.org>
Authored: Wed Mar 30 13:42:42 2016 -0400
Committer: David Smiley <ds...@apache.org>
Committed: Wed Mar 30 14:45:16 2016 -0400

----------------------------------------------------------------------
 solr/CHANGES.txt                                |   8 +
 .../analytics/accumulator/BasicAccumulator.java |   6 +-
 .../accumulator/FacetingAccumulator.java        |   8 +-
 .../analytics/expression/ExpressionFactory.java |   9 +-
 .../StatsCollectorSupplierFactory.java          |  21 +-
 .../solr/analytics/util/AnalyticsParsers.java   |   7 +-
 .../analytics/util/RangeEndpointCalculator.java |   5 +-
 .../util/valuesource/ConstDateSource.java       |   9 +-
 .../util/valuesource/DateFieldSource.java       |   6 +-
 .../util/valuesource/FilterFieldSource.java     |   3 +-
 .../analytics/expression/ExpressionTest.java    |  27 +-
 .../apache/solr/core/SolrDeletionPolicy.java    |  16 +-
 .../solr/handler/CdcrReplicatorState.java       |  21 +-
 .../apache/solr/handler/PingRequestHandler.java |   6 +-
 .../solr/handler/component/PivotFacetValue.java |   3 +-
 .../handler/component/RangeFacetRequest.java    |  50 +---
 .../apache/solr/response/CSVResponseWriter.java |  10 +-
 .../solr/response/TextResponseWriter.java       |   3 +-
 .../transform/ValueAugmenterFactory.java        |   4 +-
 .../org/apache/solr/rest/ManagedResource.java   |  24 +-
 .../org/apache/solr/schema/DateRangeField.java  |  15 +-
 .../org/apache/solr/schema/TrieDateField.java   |   5 +-
 .../java/org/apache/solr/schema/TrieField.java  |  32 ++-
 .../apache/solr/search/ValueSourceParser.java   |  37 ++-
 .../apache/solr/search/facet/FacetRange.java    |   5 +-
 .../DocExpirationUpdateProcessorFactory.java    |  42 ++--
 .../org/apache/solr/util/DateFormatUtil.java    | 245 -------------------
 .../org/apache/solr/util/DateMathParser.java    |  88 ++++++-
 .../org/apache/solr/BasicFunctionalityTest.java |  29 +--
 .../core/src/test/org/apache/solr/TestTrie.java |  13 +-
 .../cloud/SegmentTerminateEarlyTestState.java   |   6 +-
 .../apache/solr/cloud/TestCloudPivotFacet.java  |  23 +-
 .../DistributedFacetPivotLargeTest.java         |   3 +-
 .../apache/solr/request/SimpleFacetsTest.java   |   9 +-
 .../solr/response/TestCSVResponseWriter.java    |  14 +-
 .../org/apache/solr/schema/DateFieldTest.java   | 148 +----------
 .../solr/schema/TestUseDocValuesAsStored.java   |   9 +-
 .../update/processor/AtomicUpdatesTest.java     |  48 ++--
 .../apache/solr/util/DateMathParserTest.java    | 125 +++++++++-
 .../org/apache/solr/client/solrj/SolrQuery.java |  21 +-
 .../client/solrj/impl/XMLResponseParser.java    |  27 +-
 .../solr/client/solrj/util/ClientUtils.java     |  20 +-
 .../apache/solr/client/solrj/SolrQueryTest.java |  18 +-
 .../solrj/response/QueryResponseTest.java       |   7 +-
 .../solr/BaseDistributedSearchTestCase.java     |  54 ++--
 .../java/org/apache/solr/SolrTestCaseJ4.java    |  16 +-
 46 files changed, 516 insertions(+), 789 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 7278e45..5df90d1 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -91,6 +91,10 @@ Upgrading from Solr 5.x
   to prevent future optizations from using the column-stored values over the row-stored values when
   fields have both stored="true" and docValues="true".
 
+* Formatted date-times from Solr have some differences. If the year is more than 4 digits, there is a leading '+'.
+  When there is a non-zero number of milliseconds, it is padded with zeros to 3 digits. Negative year (BC) dates are
+  now possible.  Parsing: It is now an error to supply a portion of the date out of its, range, like 67 seconds.
+
 Detailed Change List
 ----------------------
 
@@ -444,6 +448,10 @@ Other Changes
 * SOLR-8810: Implement Connection.setReadOnly, Statement.set/getFetchSize, 
   ResultSet.getType (Kevin Risden)
 
+* SOLR-8904: All dates are formatted via Instant.toString() (ISO-8601); see Solr upgrade notes for differences. Will
+  now parse (and format) dates with a leading '+' or '-' (BC dates or dates > 4 digit year.
+  [value] and ms() and contrib/analytics now parse with date math. (David Smiley)
+
 ==================  5.5.1 ==================
 
 Bug Fixes

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/BasicAccumulator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/BasicAccumulator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/BasicAccumulator.java
index 53037c1..bd21209 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/BasicAccumulator.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/BasicAccumulator.java
@@ -24,6 +24,7 @@ import java.util.Date;
 import java.util.List;
 import java.util.Set;
 
+import com.google.common.base.Supplier;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.solr.analytics.expression.Expression;
 import org.apache.solr.analytics.expression.ExpressionFactory;
@@ -36,12 +37,9 @@ import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.search.DocSet;
 import org.apache.solr.search.SolrIndexSearcher;
-import org.apache.solr.util.DateFormatUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Supplier;
-
 /**
  * A <code>BasicAccumulator</code> manages the ValueCounters and Expressions without regard to Facets.
  */
@@ -143,7 +141,7 @@ public class BasicAccumulator extends ValueAccumulator {
       if (expressionName.equals(expressionNames[count])) {
         Comparable value = expressions[count].getValue();
         if (value.getClass().equals(Date.class)) {
-          return DateFormatUtil.formatExternal((Date)value);
+          return ((Date)value).toInstant().toString();
         } else {
           return value.toString();
         }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/FacetingAccumulator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/FacetingAccumulator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/FacetingAccumulator.java
index 7cb0c14..03392f0 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/FacetingAccumulator.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/FacetingAccumulator.java
@@ -30,6 +30,7 @@ import java.util.Map.Entry;
 import java.util.Set;
 import java.util.TreeMap;
 
+import com.google.common.collect.Iterables;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.search.BooleanQuery;
@@ -60,9 +61,6 @@ import org.apache.solr.search.Filter;
 import org.apache.solr.search.QParser;
 import org.apache.solr.search.SolrIndexSearcher;
 import org.apache.solr.search.SyntaxError;
-import org.apache.solr.util.DateFormatUtil;
-
-import com.google.common.collect.Iterables;
 
 /**
  * A <code>FacetingAccumulator</code> manages the StatsCollectors and Expressions for facets.
@@ -376,7 +374,7 @@ public class FacetingAccumulator extends BasicAccumulator implements FacetValueA
         if (expressionName.equals(expressionNames[count])) {
           Comparable value = facetExpressions[count].getValue();
           if (value.getClass().equals(Date.class)) {
-            return DateFormatUtil.formatExternal((Date)value);
+            return ((Date)value).toInstant().toString();
           } else {
             return value.toString();
           }
@@ -430,7 +428,7 @@ public class FacetingAccumulator extends BasicAccumulator implements FacetValueA
         if (expressionName.equals(expressionNames[count])) {
           Comparable value = facetExpressions[count].getValue();
           if (value.getClass().equals(Date.class)) {
-            return DateFormatUtil.formatExternal((Date)value);
+            return ((Date)value).toInstant().toString();
           } else {
             return value.toString();
           }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/ExpressionFactory.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/ExpressionFactory.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/ExpressionFactory.java
index 8ad4070..1f2d0e0 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/ExpressionFactory.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/ExpressionFactory.java
@@ -16,7 +16,6 @@
  */
 package org.apache.solr.analytics.expression;
 
-import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -24,7 +23,7 @@ import org.apache.solr.analytics.statistics.StatsCollector;
 import org.apache.solr.analytics.util.AnalyticsParams;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.util.DateFormatUtil;
+import org.apache.solr.util.DateMathParser;
 
 public class ExpressionFactory {
 
@@ -81,11 +80,7 @@ public class ExpressionFactory {
         throw new SolrException(ErrorCode.BAD_REQUEST, "The constant "+operands+" cannot be converted into a number.",e);
       }
     } else if (topOperation.equals(AnalyticsParams.CONSTANT_DATE)) {
-      try {
-        return new ConstantDateExpression(DateFormatUtil.parseDate(operands));
-      } catch (ParseException e) {
-        throw new SolrException(ErrorCode.BAD_REQUEST, "The constant "+operands+" cannot be converted into a date.",e);
-      }
+      return new ConstantDateExpression(DateMathParser.parseMath(null, operands));
     } else if (topOperation.equals(AnalyticsParams.CONSTANT_STRING)) {
       operands = expression.substring(paren+1, expression.lastIndexOf(')'));
       return new ConstantStringExpression(operands);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/StatsCollectorSupplierFactory.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/StatsCollectorSupplierFactory.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/StatsCollectorSupplierFactory.java
index bee7431..bd9f65d 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/StatsCollectorSupplierFactory.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/StatsCollectorSupplierFactory.java
@@ -17,16 +17,14 @@
 package org.apache.solr.analytics.statistics;
 
 import java.lang.invoke.MethodHandles;
-import java.text.ParseException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.HashSet;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
 
+import com.google.common.base.Supplier;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.BytesRefFieldSource;
 import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
@@ -36,7 +34,6 @@ import org.apache.lucene.queries.function.valuesource.LongFieldSource;
 import org.apache.solr.analytics.expression.ExpressionFactory;
 import org.apache.solr.analytics.request.ExpressionRequest;
 import org.apache.solr.analytics.util.AnalyticsParams;
-import org.apache.solr.analytics.util.AnalyticsParsers;
 import org.apache.solr.analytics.util.valuesource.AbsoluteValueDoubleFunction;
 import org.apache.solr.analytics.util.valuesource.AddDoubleFunction;
 import org.apache.solr.analytics.util.valuesource.ConcatStringFunction;
@@ -67,12 +64,10 @@ import org.apache.solr.schema.TrieDoubleField;
 import org.apache.solr.schema.TrieFloatField;
 import org.apache.solr.schema.TrieIntField;
 import org.apache.solr.schema.TrieLongField;
-import org.apache.solr.util.DateFormatUtil;
+import org.apache.solr.util.DateMathParser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Supplier;
-
 public class StatsCollectorSupplierFactory {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
   
@@ -443,11 +438,7 @@ public class StatsCollectorSupplierFactory {
         throw new SolrException(ErrorCode.BAD_REQUEST,"The filter value "+arguments[1]+" cannot be converted into an integer.",e);
       }
     } else if ( src instanceof DateFieldSource || src instanceof MultiDateFunction) {
-      try {
-        defaultObject = DateFormatUtil.parseDate(arguments[1]);
-      } catch (ParseException e) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The filter value "+arguments[1]+" cannot be converted into a date.",e);
-      }
+      defaultObject = DateMathParser.parseMath(null, arguments[1]);
     } else if ( src instanceof LongFieldSource ) {
       try {
         defaultObject = new Long(arguments[1]);
@@ -578,11 +569,7 @@ public class StatsCollectorSupplierFactory {
       if (arguments.length!=1) {
         throw new SolrException(ErrorCode.BAD_REQUEST,"The constant date declaration ["+expressionString+"] does not have exactly 1 argument.");
       }
-      try {
-        return new ConstDateSource(DateFormatUtil.parseDate(operands));
-      } catch (ParseException e) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The constant "+operands+" cannot be converted into a date.",e);
-      }
+      return new ConstDateSource(DateMathParser.parseMath(null, operands));
     } else if (operation.equals(AnalyticsParams.FILTER)) {
       return buildFilterSource(schema, operands, DATE_TYPE);
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsParsers.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsParsers.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsParsers.java
index dad4a5b..7a7e697 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsParsers.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsParsers.java
@@ -17,8 +17,8 @@
 package org.apache.solr.analytics.util;
 
 import java.io.IOException;
+import java.time.Instant;
 import java.util.Arrays;
-import java.util.Date;
 
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.LegacyNumericUtils;
@@ -29,7 +29,6 @@ import org.apache.solr.schema.TrieDoubleField;
 import org.apache.solr.schema.TrieFloatField;
 import org.apache.solr.schema.TrieIntField;
 import org.apache.solr.schema.TrieLongField;
-import org.apache.solr.util.DateFormatUtil;
 
 /** 
  * Class to hold the parsers used for Solr Analytics.
@@ -149,7 +148,7 @@ public class AnalyticsParsers {
     @SuppressWarnings("deprecation")
     public String parse(BytesRef bytes) throws IOException {
       try {
-        return DateFormatUtil.formatExternal(new Date(LegacyNumericUtils.prefixCodedToLong(bytes)));
+        return Instant.ofEpochMilli(LegacyNumericUtils.prefixCodedToLong(bytes)).toString();
       } catch (NumberFormatException e) {
         throw new IOException("The byte array "+Arrays.toString(bytes.bytes)+" cannot be converted to a date.");
       }
@@ -157,7 +156,7 @@ public class AnalyticsParsers {
     @SuppressWarnings("deprecation")
     @Override
     public String parseNum(long l) {
-      return ""+DateFormatUtil.formatExternal(new Date(l));
+      return Instant.ofEpochMilli(l).toString();
     }
   };
   

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/RangeEndpointCalculator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/RangeEndpointCalculator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/RangeEndpointCalculator.java
index 6d899e0..fa9686d 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/RangeEndpointCalculator.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/RangeEndpointCalculator.java
@@ -31,7 +31,6 @@ import org.apache.solr.schema.SchemaField;
 import org.apache.solr.schema.TrieDateField;
 import org.apache.solr.schema.TrieField;
 import org.apache.solr.util.DateMathParser;
-import org.apache.solr.util.DateFormatUtil;
 
 
 public abstract class RangeEndpointCalculator<T extends Comparable<T>> {
@@ -332,12 +331,12 @@ public abstract class RangeEndpointCalculator<T extends Comparable<T>> {
     
     @Override
     public String formatValue(Date val) {
-      return DateFormatUtil.formatExternal(val);
+      return val.toInstant().toString();
     }
     
     @Override
     protected Date parseVal(String rawval) {
-      return DateFormatUtil.parseMath(now, rawval);
+      return DateMathParser.parseMath(now, rawval);
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDateSource.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDateSource.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDateSource.java
index dc2e02c..3ce608f 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDateSource.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDateSource.java
@@ -17,7 +17,7 @@
 package org.apache.solr.analytics.util.valuesource;
 
 import java.io.IOException;
-import java.text.ParseException;
+import java.time.Instant;
 import java.util.Date;
 import java.util.Map;
 
@@ -27,7 +27,6 @@ import org.apache.lucene.queries.function.docvalues.FloatDocValues;
 import org.apache.lucene.util.mutable.MutableValue;
 import org.apache.lucene.util.mutable.MutableValueDate;
 import org.apache.solr.analytics.util.AnalyticsParams;
-import org.apache.solr.util.DateFormatUtil;
 
 /**
  * <code>ConstDateSource</code> returns a constant date for all documents
@@ -35,7 +34,7 @@ import org.apache.solr.util.DateFormatUtil;
 public class ConstDateSource extends ConstDoubleSource {
   public final static String NAME = AnalyticsParams.CONSTANT_DATE;
 
-  public ConstDateSource(Date constant) throws ParseException {
+  public ConstDateSource(Date constant) {
     super(constant.getTime());
   }
 
@@ -46,7 +45,7 @@ public class ConstDateSource extends ConstDoubleSource {
   @SuppressWarnings("deprecation")
   @Override
   public String description() {
-    return name()+"(" + DateFormatUtil.formatExternal(new Date(getLong())) + ")";
+    return name()+"(" + Instant.ofEpochMilli(getLong()) + ")";
   }
 
   protected String name() {
@@ -83,7 +82,7 @@ public class ConstDateSource extends ConstDoubleSource {
       @SuppressWarnings("deprecation")
       @Override
       public String strVal(int doc) {
-        return DateFormatUtil.formatExternal(new Date(longVal(doc)));
+        return Instant.ofEpochMilli(longVal(doc)).toString();
       }
       @Override
       public boolean boolVal(int doc) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateFieldSource.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateFieldSource.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateFieldSource.java
index 631aca0..4d66e00 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateFieldSource.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateFieldSource.java
@@ -17,11 +17,12 @@
 package org.apache.solr.analytics.util.valuesource;
 
 import java.io.IOException;
+import java.time.Instant;
 import java.util.Date;
 import java.util.Map;
 
-import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.NumericDocValues;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.docvalues.LongDocValues;
@@ -31,7 +32,6 @@ import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.LegacyNumericUtils;
 import org.apache.lucene.util.mutable.MutableValue;
 import org.apache.lucene.util.mutable.MutableValueDate;
-import org.apache.solr.util.DateFormatUtil;
 
 /**
  * Extends {@link LongFieldSource} to have a field source that takes in 
@@ -53,7 +53,7 @@ public class DateFieldSource extends LongFieldSource {
 
   @SuppressWarnings("deprecation")
   public String longToString(long val) {
-    return DateFormatUtil.formatExternal((Date)longToObject(val));
+    return Instant.ofEpochMilli(val).toString();
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/FilterFieldSource.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/FilterFieldSource.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/FilterFieldSource.java
index 8eb35d1..22f5a57 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/FilterFieldSource.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/FilterFieldSource.java
@@ -25,7 +25,6 @@ import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.util.mutable.MutableValue;
 import org.apache.solr.analytics.util.AnalyticsParams;
-import org.apache.solr.util.DateFormatUtil;
 
 /**
  * <code>DefaultIsMissingFieldSource</code> wraps a field source to return missing values 
@@ -49,7 +48,7 @@ public class FilterFieldSource extends ValueSource {
   @Override
   public String description() {
     if (missValue.getClass().equals(Date.class)) {
-      return name()+"("+source.description()+","+DateFormatUtil.formatExternal((Date)missValue)+")";
+      return name()+"("+source.description()+","+ ((Date)missValue).toInstant() +")";
     } else {
       return name()+"("+source.description()+","+missValue.toString()+")";
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/ExpressionTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/ExpressionTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/ExpressionTest.java
index 2519358..4a3276b 100644
--- a/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/ExpressionTest.java
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/ExpressionTest.java
@@ -16,22 +16,22 @@
  */
 package org.apache.solr.analytics.expression;
 
-import com.google.common.collect.ObjectArrays;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Scanner;
 
+import com.google.common.collect.ObjectArrays;
 import org.apache.lucene.util.IOUtils;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.analytics.AbstractAnalyticsStatsTest;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.util.DateMathParser;
-import org.apache.solr.util.DateFormatUtil;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Scanner;
-
 public class ExpressionTest extends AbstractAnalyticsStatsTest {
   private static final String fileName = "/analytics/requestFiles/expressions.txt";
 
@@ -156,20 +156,19 @@ public class ExpressionTest extends AbstractAnalyticsStatsTest {
     assertEquals(getRawResponse(), 10, result, 0.0);
   }
 
-  @SuppressWarnings("deprecation")
   @Test
   public void dateMathTest() throws Exception {
     String math = (String) getStatResult("dmr", "cme", VAL_TYPE.STRING);
-    DateMathParser date = new DateMathParser();
-    date.setNow(DateFormatUtil.parseDate((String) getStatResult("dmr", "median", VAL_TYPE.DATE)));
+    DateMathParser dateMathParser = new DateMathParser();
+    dateMathParser.setNow(new Date(Instant.parse((String) getStatResult("dmr", "median", VAL_TYPE.DATE)).toEpochMilli()));
     String dateMath = (String) getStatResult("dmr", "dmme", VAL_TYPE.DATE);
-    assertEquals(getRawResponse(), DateFormatUtil.parseDate(dateMath), date.parseMath(math));
+    assertEquals(getRawResponse(), new Date(Instant.parse(dateMath).toEpochMilli()), dateMathParser.parseMath(math));
 
     math = (String) getStatResult("dmr", "cma", VAL_TYPE.STRING);
-    date = new DateMathParser();
-    date.setNow(DateFormatUtil.parseDate((String) getStatResult("dmr", "max", VAL_TYPE.DATE)));
+    dateMathParser = new DateMathParser();
+    dateMathParser.setNow(new Date(Instant.parse((String) getStatResult("dmr", "max", VAL_TYPE.DATE)).toEpochMilli()));
     dateMath = (String) getStatResult("dmr", "dmma", VAL_TYPE.DATE);
-    assertEquals(getRawResponse(), DateFormatUtil.parseDate(dateMath), date.parseMath(math));
+    assertEquals(getRawResponse(), new Date(Instant.parse(dateMath).toEpochMilli()), dateMathParser.parseMath(math));
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/core/SolrDeletionPolicy.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrDeletionPolicy.java b/solr/core/src/java/org/apache/solr/core/SolrDeletionPolicy.java
index 24b0e61..c7a6689 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrDeletionPolicy.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrDeletionPolicy.java
@@ -15,23 +15,23 @@
  * limitations under the License.
  */
 package org.apache.solr.core;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.List;
+import java.util.Locale;
+
 import org.apache.lucene.index.IndexCommit;
 import org.apache.lucene.index.IndexDeletionPolicy;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.FSDirectory;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.util.DateMathParser;
-import org.apache.solr.util.DateFormatUtil;
 import org.apache.solr.util.plugin.NamedListInitializedPlugin;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
-import java.io.IOException;
-import java.lang.invoke.MethodHandles;
-import java.util.List;
-import java.util.Locale;
-
 
 /**
  * Standard Solr deletion policy that allows reserving index commit points
@@ -174,7 +174,7 @@ public class SolrDeletionPolicy extends IndexDeletionPolicy implements NamedList
         try {
           if (maxCommitAge != null) {
             if (maxCommitAgeTimeStamp==-1) {
-              DateMathParser dmp = new DateMathParser(DateFormatUtil.UTC, Locale.ROOT);
+              DateMathParser dmp = new DateMathParser(DateMathParser.UTC, Locale.ROOT);
               maxCommitAgeTimeStamp = dmp.parseMath(maxCommitAge).getTime();
             }
             if (IndexDeletionPolicyWrapper.getCommitTimestamp(commit) < maxCommitAgeTimeStamp) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/handler/CdcrReplicatorState.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/CdcrReplicatorState.java b/solr/core/src/java/org/apache/solr/handler/CdcrReplicatorState.java
index d0b1c4a..9e01f11 100644
--- a/solr/core/src/java/org/apache/solr/handler/CdcrReplicatorState.java
+++ b/solr/core/src/java/org/apache/solr/handler/CdcrReplicatorState.java
@@ -16,17 +16,24 @@
  */
 package org.apache.solr.handler;
 
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.update.CdcrUpdateLog;
 import org.apache.solr.update.UpdateLog;
-import org.apache.solr.util.DateFormatUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
-import java.lang.invoke.MethodHandles;
-import java.util.*;
-
 /**
  * The state of the replication with a target cluster.
  */
@@ -133,7 +140,7 @@ class CdcrReplicatorState {
       Iterator<ErrorQueueEntry> it = errorsQueue.iterator();
       while (it.hasNext()) {
         ErrorQueueEntry entry = it.next();
-        lastErrors.add(new String[]{DateFormatUtil.formatExternal(entry.timestamp), entry.type.toLower()});
+        lastErrors.add(new String[]{entry.timestamp.toInstant().toString(), entry.type.toLower()});
       }
     }
     return lastErrors;
@@ -145,7 +152,7 @@ class CdcrReplicatorState {
   String getTimestampOfLastProcessedOperation() {
     if (logReader != null && logReader.getLastVersion() != -1) {
       // Shift back to the right by 20 bits the version number - See VersionInfo#getNewClock
-      return DateFormatUtil.formatExternal(new Date(logReader.getLastVersion() >> 20));
+      return Instant.ofEpochMilli(logReader.getLastVersion() >> 20).toString();
     }
     return "";
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java b/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java
index 5df46f5..4b72e0f 100644
--- a/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java
@@ -20,7 +20,7 @@ import java.io.File;
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.nio.file.Files;
-import java.util.Date;
+import java.time.Instant;
 import java.util.Locale;
 
 import org.apache.commons.io.FileUtils;
@@ -34,7 +34,6 @@ import org.apache.solr.core.SolrCore;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrRequestHandler;
 import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.util.DateFormatUtil;
 import org.apache.solr.util.plugin.SolrCoreAware;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -308,8 +307,7 @@ public class PingRequestHandler extends RequestHandlerBase implements SolrCoreAw
     if ( enable ) {
       try {
         // write out when the file was created
-        FileUtils.write(healthcheck, 
-                        DateFormatUtil.formatExternal(new Date()), "UTF-8");
+        FileUtils.write(healthcheck, Instant.now().toString(), "UTF-8");
       } catch (IOException e) {
         throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, 
                                 "Unable to write healthcheck flag file", e);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/handler/component/PivotFacetValue.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/PivotFacetValue.java b/solr/core/src/java/org/apache/solr/handler/component/PivotFacetValue.java
index a1eed07..3280c6c 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/PivotFacetValue.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/PivotFacetValue.java
@@ -26,7 +26,6 @@ import java.util.Map;
 import org.apache.solr.common.params.FacetParams;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.SimpleOrderedMap;
-import org.apache.solr.util.DateFormatUtil;
 import org.apache.solr.util.PivotListEntry;
 
 /**
@@ -92,7 +91,7 @@ public class PivotFacetValue {
     if (null == value) {
       out.add(null);
     } else if (value instanceof Date) {
-      out.add(DateFormatUtil.formatExternal((Date) value));
+      out.add(((Date) value).toInstant().toString());
     } else {
       out.add(value.toString());
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/handler/component/RangeFacetRequest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/RangeFacetRequest.java b/solr/core/src/java/org/apache/solr/handler/component/RangeFacetRequest.java
index 92b118a..8c0c381 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/RangeFacetRequest.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/RangeFacetRequest.java
@@ -17,7 +17,6 @@
 package org.apache.solr.handler.component;
 
 import java.lang.invoke.MethodHandles;
-
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.EnumSet;
@@ -39,8 +38,6 @@ import org.apache.solr.schema.SchemaField;
 import org.apache.solr.schema.TrieDateField;
 import org.apache.solr.schema.TrieField;
 import org.apache.solr.util.DateMathParser;
-import org.apache.solr.util.DateFormatUtil;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -165,7 +162,7 @@ public class RangeFacetRequest extends FacetComponent.FacetBase {
                   "Unable to range facet on tried field of unexpected type:" + this.facetOn);
       }
     } else if (ft instanceof DateRangeField) {
-      calc = new DateRangeFieldEndpointCalculator(this, null);
+      calc = new DateRangeEndpointCalculator(this, null);
     } else {
       throw new SolrException
           (SolrException.ErrorCode.BAD_REQUEST,
@@ -703,56 +700,19 @@ public class RangeFacetRequest extends FacetComponent.FacetBase {
                                        final Date now) {
       super(rangeFacetRequest);
       this.now = now;
-      if (!(field.getType() instanceof TrieDateField)) {
-        throw new IllegalArgumentException
-            (TYPE_ERR_MSG);
-      }
-    }
-
-    @Override
-    public String formatValue(Date val) {
-      return DateFormatUtil.formatExternal(val);
-    }
-
-    @Override
-    protected Date parseVal(String rawval) {
-      return DateFormatUtil.parseMath(now, rawval);
-    }
-
-    @Override
-    protected Object parseGap(final String rawval) {
-      return rawval;
-    }
-
-    @Override
-    public Date parseAndAddGap(Date value, String gap) throws java.text.ParseException {
-      final DateMathParser dmp = new DateMathParser();
-      dmp.setNow(value);
-      return dmp.parseMath(gap);
-    }
-  }
-
-  private static class DateRangeFieldEndpointCalculator
-      extends RangeEndpointCalculator<Date> {
-    private final Date now;
-
-    public DateRangeFieldEndpointCalculator(final RangeFacetRequest rangeFacetRequest,
-                                            final Date now) {
-      super(rangeFacetRequest);
-      this.now = now;
-      if (!(field.getType() instanceof DateRangeField)) {
-        throw new IllegalArgumentException(DateRangeEndpointCalculator.TYPE_ERR_MSG);
+      if (!(field.getType() instanceof TrieDateField) && !(field.getType() instanceof DateRangeField)) {
+        throw new IllegalArgumentException(TYPE_ERR_MSG);
       }
     }
 
     @Override
     public String formatValue(Date val) {
-      return DateFormatUtil.formatExternal(val);
+      return val.toInstant().toString();
     }
 
     @Override
     protected Date parseVal(String rawval) {
-      return ((DateRangeField) field.getType()).parseMath(now, rawval);
+      return DateMathParser.parseMath(now, rawval);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/response/CSVResponseWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/CSVResponseWriter.java b/solr/core/src/java/org/apache/solr/response/CSVResponseWriter.java
index ba77821..326220c 100644
--- a/solr/core/src/java/org/apache/solr/response/CSVResponseWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/CSVResponseWriter.java
@@ -29,12 +29,13 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
 import org.apache.lucene.index.IndexableField;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrDocumentList;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.SolrParams;
-import org.apache.solr.common.util.DateUtil;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.internal.csv.CSVPrinter;
 import org.apache.solr.internal.csv.CSVStrategy;
@@ -46,9 +47,6 @@ import org.apache.solr.search.DocList;
 import org.apache.solr.search.ReturnFields;
 import org.apache.solr.util.FastWriter;
 
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-
 /**
  *
  */
@@ -497,9 +495,7 @@ class CSVWriter extends TextResponseWriter {
 
   @Override
   public void writeDate(String name, Date val) throws IOException {
-    StringBuilder sb = new StringBuilder(25);
-    cal = DateUtil.formatDate(val, cal, sb);
-    writeDate(name, sb.toString());
+    writeDate(name, val.toInstant().toString());
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java b/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
index 3f9e010..bde5759 100644
--- a/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
@@ -40,7 +40,6 @@ import org.apache.solr.schema.IndexSchema;
 import org.apache.solr.schema.SchemaField;
 import org.apache.solr.search.DocList;
 import org.apache.solr.search.ReturnFields;
-import org.apache.solr.util.DateFormatUtil;
 import org.apache.solr.util.FastWriter;
 
 /** Base class for text-oriented response writers.
@@ -335,7 +334,7 @@ public abstract class TextResponseWriter {
 
 
   public void writeDate(String name, Date val) throws IOException {
-    writeDate(name, DateFormatUtil.formatExternal(val));
+    writeDate(name, val.toInstant().toString());
   }
   
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/response/transform/ValueAugmenterFactory.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/response/transform/ValueAugmenterFactory.java b/solr/core/src/java/org/apache/solr/response/transform/ValueAugmenterFactory.java
index 8279780..e4edbdf 100644
--- a/solr/core/src/java/org/apache/solr/response/transform/ValueAugmenterFactory.java
+++ b/solr/core/src/java/org/apache/solr/response/transform/ValueAugmenterFactory.java
@@ -20,9 +20,9 @@ import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.common.params.SolrParams;
-import org.apache.solr.common.util.DateUtil;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.util.DateMathParser;
 
 /**
  *
@@ -48,7 +48,7 @@ public class ValueAugmenterFactory extends TransformerFactory
         if( "int".equals( type ) ) return Integer.valueOf( val );
         if( "double".equals( type ) ) return Double.valueOf( val );
         if( "float".equals( type ) ) return Float.valueOf( val );
-        if( "date".equals( type ) ) return DateUtil.parseDate(val);
+        if( "date".equals( type ) ) return DateMathParser.parseMath(null, val );
       }
       catch( Exception ex ) {
         throw new SolrException( ErrorCode.BAD_REQUEST,

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/rest/ManagedResource.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/rest/ManagedResource.java b/solr/core/src/java/org/apache/solr/rest/ManagedResource.java
index 6b02364..8668c9c 100644
--- a/solr/core/src/java/org/apache/solr/rest/ManagedResource.java
+++ b/solr/core/src/java/org/apache/solr/rest/ManagedResource.java
@@ -27,7 +27,6 @@ import java.util.Set;
 
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.common.util.DateUtil;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.core.SolrResourceLoader;
 import org.apache.solr.rest.ManagedResourceStorage.StorageIO;
@@ -282,16 +281,7 @@ public abstract class ManagedResource {
    * Returns this resource's initialization timestamp.
    */
   public String getInitializedOn() {
-    if (initializedOn == null)
-      return null;
-    
-    StringBuilder dateBuf = new StringBuilder();
-    try {
-      DateUtil.formatDate(initializedOn, null, dateBuf);
-    } catch (IOException e) {
-      // safe to ignore
-    }
-    return dateBuf.toString();
+    return initializedOn == null ? null : initializedOn.toInstant().toString();
   }
 
   /**
@@ -299,17 +289,7 @@ public abstract class ManagedResource {
    * or null if this resource has not been updated since initialization.
    */
   public String getUpdatedSinceInitialization() {
-    String dateStr = null;
-    if (lastUpdateSinceInitialization != null) {
-      StringBuilder dateBuf = new StringBuilder();
-      try {
-        DateUtil.formatDate(lastUpdateSinceInitialization, null, dateBuf);
-        dateStr = dateBuf.toString(); 
-      } catch (IOException e) {
-        // safe to ignore here
-      }
-    }
-    return dateStr;
+    return lastUpdateSinceInitialization == null ? null : lastUpdateSinceInitialization.toInstant().toString();
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/schema/DateRangeField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/DateRangeField.java b/solr/core/src/java/org/apache/solr/schema/DateRangeField.java
index 95b441a..dcda75e 100644
--- a/solr/core/src/java/org/apache/solr/schema/DateRangeField.java
+++ b/solr/core/src/java/org/apache/solr/schema/DateRangeField.java
@@ -22,8 +22,6 @@ import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
-import org.locationtech.spatial4j.shape.Shape;
-
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.spatial.prefix.NumberRangePrefixTreeStrategy;
@@ -37,7 +35,8 @@ import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.request.SolrRequestInfo;
 import org.apache.solr.search.QParser;
 import org.apache.solr.search.SyntaxError;
-import org.apache.solr.util.DateFormatUtil;
+import org.apache.solr.util.DateMathParser;
+import org.locationtech.spatial4j.shape.Shape;
 
 /**
  * A field for indexed dates and date ranges. It's mostly compatible with TrieDateField.
@@ -75,7 +74,7 @@ public class DateRangeField extends AbstractSpatialPrefixTreeFieldType<NumberRan
       if (unitShape.getLevel() == tree.getMaxLevels()) {
         //fully precise date. We can be fully compatible with TrieDateField.
         Date date = tree.toCalendar(unitShape).getTime();
-        return DateFormatUtil.formatExternal(date);
+        return date.toInstant().toString();
       }
     }
     return (shapeStr == null ? shape.toString() : shapeStr);//we don't normalize ranges here; should we?
@@ -100,7 +99,7 @@ public class DateRangeField extends AbstractSpatialPrefixTreeFieldType<NumberRan
     if (str.startsWith("NOW") || str.lastIndexOf('Z') >= 0) {
       //use Solr standard date format parsing rules.
       //TODO parse a Calendar instead of a Date, rounded according to DateMath syntax.
-      Date date = DateFormatUtil.parseMath(null, str);
+      Date date = DateMathParser.parseMath(null, str);
       Calendar cal = tree.newCal();
       cal.setTime(date);
       return cal;
@@ -115,9 +114,9 @@ public class DateRangeField extends AbstractSpatialPrefixTreeFieldType<NumberRan
     }
   }
 
-  /** For easy compatibility with {@link DateFormatUtil#parseMath(Date, String)}. */
+  /** For easy compatibility with {@link DateMathParser#parseMath(Date, String)}. */
   public Date parseMath(Date now, String rawval) {
-    return DateFormatUtil.parseMath(now, rawval);
+    return DateMathParser.parseMath(now, rawval);
   }
 
   @Override
@@ -127,7 +126,7 @@ public class DateRangeField extends AbstractSpatialPrefixTreeFieldType<NumberRan
       if (unitShape.getLevel() == tree.getMaxLevels()) {
         //fully precise date. We can be fully compatible with TrieDateField.
         Date date = tree.toCalendar(unitShape).getTime();
-        return DateFormatUtil.formatExternal(date);
+        return date.toInstant().toString();
       }
     }
     return shape.toString();//range shape

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/schema/TrieDateField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/TrieDateField.java b/solr/core/src/java/org/apache/solr/schema/TrieDateField.java
index ccaf821..209c581 100644
--- a/solr/core/src/java/org/apache/solr/schema/TrieDateField.java
+++ b/solr/core/src/java/org/apache/solr/schema/TrieDateField.java
@@ -19,8 +19,7 @@ package org.apache.solr.schema;
 import java.util.Date;
 
 import org.apache.lucene.index.IndexableField;
-import org.apache.solr.update.processor.TimestampUpdateProcessorFactory; //jdoc
-import org.apache.solr.util.DateFormatUtil;
+import org.apache.solr.update.processor.TimestampUpdateProcessorFactory;
 import org.apache.solr.util.DateMathParser;
 
 /**
@@ -96,7 +95,7 @@ public class TrieDateField extends TrieField implements DateValueFieldType {
   @Override
   public Object toNativeType(Object val) {
     if (val instanceof String) {
-      return DateFormatUtil.parseMath(null, (String)val);
+      return DateMathParser.parseMath(null, (String)val);
     }
     return super.toNativeType(val);
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/schema/TrieField.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/TrieField.java b/solr/core/src/java/org/apache/solr/schema/TrieField.java
index 506d8ad..bed087e 100644
--- a/solr/core/src/java/org/apache/solr/schema/TrieField.java
+++ b/solr/core/src/java/org/apache/solr/schema/TrieField.java
@@ -18,6 +18,7 @@ package org.apache.solr.schema;
 
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
@@ -25,9 +26,9 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
-import org.apache.lucene.document.LegacyDoubleField;
 import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.FieldType.LegacyNumericType;
+import org.apache.lucene.document.LegacyDoubleField;
 import org.apache.lucene.document.LegacyFloatField;
 import org.apache.lucene.document.LegacyIntField;
 import org.apache.lucene.document.LegacyLongField;
@@ -41,14 +42,11 @@ import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
 import org.apache.lucene.queries.function.valuesource.FloatFieldSource;
 import org.apache.lucene.queries.function.valuesource.IntFieldSource;
 import org.apache.lucene.queries.function.valuesource.LongFieldSource;
-import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.BooleanQuery.Builder;
 import org.apache.lucene.search.DocValuesRangeQuery;
 import org.apache.lucene.search.LegacyNumericRangeQuery;
 import org.apache.lucene.search.Query;
-import org.apache.lucene.search.SortedSetSelector;
-import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.search.SortField;
+import org.apache.lucene.search.SortedSetSelector;
 import org.apache.lucene.uninverting.UninvertingReader.Type;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.BytesRefBuilder;
@@ -63,7 +61,7 @@ import org.apache.solr.response.TextResponseWriter;
 import org.apache.solr.search.FunctionRangeQuery;
 import org.apache.solr.search.QParser;
 import org.apache.solr.search.function.ValueSourceRangeFilter;
-import org.apache.solr.util.DateFormatUtil;
+import org.apache.solr.util.DateMathParser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -426,13 +424,13 @@ public class TrieField extends PrimitiveFieldType {
       case DATE:
         if (matchOnly) {
           query = DocValuesRangeQuery.newLongRange(field.getName(),
-                min == null ? null : DateFormatUtil.parseMath(null, min).getTime(),
-                max == null ? null : DateFormatUtil.parseMath(null, max).getTime(),
+                min == null ? null : DateMathParser.parseMath(null, min).getTime(),
+                max == null ? null : DateMathParser.parseMath(null, max).getTime(),
                 minInclusive, maxInclusive);
         } else {
           query = LegacyNumericRangeQuery.newLongRange(field.getName(), ps,
-              min == null ? null : DateFormatUtil.parseMath(null, min).getTime(),
-              max == null ? null : DateFormatUtil.parseMath(null, max).getTime(),
+              min == null ? null : DateMathParser.parseMath(null, min).getTime(),
+              max == null ? null : DateMathParser.parseMath(null, max).getTime(),
               minInclusive, maxInclusive);
         }
         break;
@@ -530,7 +528,7 @@ public class TrieField extends PrimitiveFieldType {
           LegacyNumericUtils.longToPrefixCoded(NumericUtils.doubleToSortableLong(Double.parseDouble(s)), 0, result);
           break;
         case DATE:
-          LegacyNumericUtils.longToPrefixCoded(DateFormatUtil.parseMath(null, s).getTime(), 0, result);
+          LegacyNumericUtils.longToPrefixCoded(DateMathParser.parseMath(null, s).getTime(), 0, result);
           break;
         default:
           throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown type for trie field: " + type);
@@ -554,7 +552,7 @@ public class TrieField extends PrimitiveFieldType {
   @Override
   public String toExternal(IndexableField f) {
     return (type == TrieTypes.DATE)
-      ? DateFormatUtil.formatExternal((Date) toObject(f))
+      ? ((Date) toObject(f)).toInstant().toString()
       : toObject(f).toString();
   }
 
@@ -571,7 +569,7 @@ public class TrieField extends PrimitiveFieldType {
       case DOUBLE:
         return Double.toString( NumericUtils.sortableLongToDouble(LegacyNumericUtils.prefixCodedToLong(indexedForm)) );
       case DATE:
-        return DateFormatUtil.formatExternal(new Date(LegacyNumericUtils.prefixCodedToLong(indexedForm)));
+        return Instant.ofEpochMilli(LegacyNumericUtils.prefixCodedToLong(indexedForm)).toString();
       default:
         throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown type for trie field: " + type);
     }
@@ -594,7 +592,7 @@ public class TrieField extends PrimitiveFieldType {
         value = Double.toString( NumericUtils.sortableLongToDouble(LegacyNumericUtils.prefixCodedToLong(indexedForm)) );
         break;
       case DATE:
-        value = DateFormatUtil.formatExternal(new Date(LegacyNumericUtils.prefixCodedToLong(indexedForm)));
+        value = Instant.ofEpochMilli(LegacyNumericUtils.prefixCodedToLong(indexedForm)).toString();
         break;
       default:
         throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown type for trie field: " + type);
@@ -725,7 +723,7 @@ public class TrieField extends PrimitiveFieldType {
       case DATE:
         Date date = (value instanceof Date)
           ? ((Date)value)
-          : DateFormatUtil.parseMath(null, value.toString());
+          : DateMathParser.parseMath(null, value.toString());
         f = new LegacyLongField(field.getName(), date.getTime(), ft);
         break;
       default:
@@ -830,12 +828,12 @@ class TrieDateFieldSource extends LongFieldSource {
 
   @Override
   public String longToString(long val) {
-    return DateFormatUtil.formatExternal(longToObject(val));
+    return longToObject(val).toInstant().toString();
   }
 
   @Override
   public long externalToLong(String extVal) {
-    return DateFormatUtil.parseMath(null, extVal).getTime();
+    return DateMathParser.parseMath(null, extVal).getTime();
   }
 
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java b/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
index 0830267..aa94a2e 100644
--- a/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
+++ b/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java
@@ -16,7 +16,14 @@
  */
 package org.apache.solr.search;
 
-import org.locationtech.spatial4j.distance.DistanceUtils;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.Term;
@@ -27,8 +34,8 @@ import org.apache.lucene.queries.function.docvalues.BoolDocValues;
 import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
 import org.apache.lucene.queries.function.docvalues.LongDocValues;
 import org.apache.lucene.queries.function.valuesource.*;
-import org.apache.lucene.search.Query;
 import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.search.spell.JaroWinklerDistance;
@@ -39,7 +46,11 @@ import org.apache.lucene.util.BytesRefBuilder;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.request.SolrRequestInfo;
-import org.apache.solr.schema.*;
+import org.apache.solr.schema.CurrencyField;
+import org.apache.solr.schema.FieldType;
+import org.apache.solr.schema.SchemaField;
+import org.apache.solr.schema.StrField;
+import org.apache.solr.schema.TextField;
 import org.apache.solr.search.facet.AggValueSource;
 import org.apache.solr.search.facet.AvgAgg;
 import org.apache.solr.search.facet.CountAgg;
@@ -53,12 +64,16 @@ import org.apache.solr.search.facet.UniqueAgg;
 import org.apache.solr.search.function.CollapseScoreFunction;
 import org.apache.solr.search.function.OrdFieldSource;
 import org.apache.solr.search.function.ReverseOrdFieldSource;
-import org.apache.solr.search.function.distance.*;
-import org.apache.solr.util.DateFormatUtil;
+import org.apache.solr.search.function.distance.GeoDistValueSourceParser;
+import org.apache.solr.search.function.distance.GeohashFunction;
+import org.apache.solr.search.function.distance.GeohashHaversineFunction;
+import org.apache.solr.search.function.distance.HaversineFunction;
+import org.apache.solr.search.function.distance.SquaredEuclideanFunction;
+import org.apache.solr.search.function.distance.StringDistanceFunction;
+import org.apache.solr.search.function.distance.VectorDistanceFunction;
+import org.apache.solr.util.DateMathParser;
 import org.apache.solr.util.plugin.NamedListInitializedPlugin;
-
-import java.io.IOException;
-import java.util.*;
+import org.locationtech.spatial4j.distance.DistanceUtils;
 
 /**
  * A factory that parses user queries to generate ValueSource instances.
@@ -993,8 +1008,10 @@ class DateValueSourceParser extends ValueSourceParser {
 
   public Date getDate(FunctionQParser fp, String arg) {
     if (arg == null) return null;
-    if (arg.startsWith("NOW") || (arg.length() > 0 && Character.isDigit(arg.charAt(0)))) {
-      return DateFormatUtil.parseMathLenient(null, arg, fp.req);
+    // check character index 1 to be a digit.  Index 0 might be a +/-.
+    if (arg.startsWith("NOW") || (arg.length() > 1 && Character.isDigit(arg.charAt(1)))) {
+      Date now = null;//TODO pull from params?
+      return DateMathParser.parseMath(now, arg);
     }
     return null;
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/search/facet/FacetRange.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/search/facet/FacetRange.java b/solr/core/src/java/org/apache/solr/search/facet/FacetRange.java
index b5abf27..8d3d0f5 100644
--- a/solr/core/src/java/org/apache/solr/search/facet/FacetRange.java
+++ b/solr/core/src/java/org/apache/solr/search/facet/FacetRange.java
@@ -34,7 +34,6 @@ import org.apache.solr.schema.SchemaField;
 import org.apache.solr.schema.TrieDateField;
 import org.apache.solr.schema.TrieField;
 import org.apache.solr.search.DocSet;
-import org.apache.solr.util.DateFormatUtil;
 import org.apache.solr.util.DateMathParser;
 
 public class FacetRange extends FacetRequest {
@@ -546,11 +545,11 @@ class FacetRangeProcessor extends FacetProcessor<FacetRange> {
 
     @Override
     public String formatValue(Comparable val) {
-      return DateFormatUtil.formatExternal( (Date)val );
+      return ((Date)val).toInstant().toString();
     }
     @Override
     protected Date parseStr(String rawval) {
-      return DateFormatUtil.parseMath(now, rawval);
+      return DateMathParser.parseMath(now, rawval);
     }
     @Override
     protected Object parseGap(final String rawval) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/update/processor/DocExpirationUpdateProcessorFactory.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/update/processor/DocExpirationUpdateProcessorFactory.java b/solr/core/src/java/org/apache/solr/update/processor/DocExpirationUpdateProcessorFactory.java
index 4608344..b8a4b57 100644
--- a/solr/core/src/java/org/apache/solr/update/processor/DocExpirationUpdateProcessorFactory.java
+++ b/solr/core/src/java/org/apache/solr/update/processor/DocExpirationUpdateProcessorFactory.java
@@ -18,46 +18,42 @@ package org.apache.solr.update.processor;
 
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 
+import org.apache.solr.cloud.CloudDescriptor;
+import org.apache.solr.cloud.ZkController;
 import org.apache.solr.common.SolrException;
-
-import static org.apache.solr.common.SolrException.ErrorCode.*;
-
-import org.apache.solr.common.util.ExecutorUtil;
-import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.cloud.Replica;
 import org.apache.solr.common.cloud.Slice;
+import org.apache.solr.common.util.ExecutorUtil;
+import org.apache.solr.common.util.NamedList;
 import org.apache.solr.core.CloseHook;
 import org.apache.solr.core.SolrCore;
-import org.apache.solr.core.CoreContainer;
-import org.apache.solr.cloud.CloudDescriptor;
-import org.apache.solr.cloud.ZkController;
-import org.apache.solr.request.SolrRequestInfo;
-import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.LocalSolrQueryRequest;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.request.SolrRequestInfo;
 import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.update.AddUpdateCommand;
 import org.apache.solr.update.CommitUpdateCommand;
 import org.apache.solr.update.DeleteUpdateCommand;
 import org.apache.solr.util.DateMathParser;
-import org.apache.solr.util.DateFormatUtil;
 import org.apache.solr.util.DefaultSolrThreadFactory;
 import org.apache.solr.util.plugin.SolrCoreAware;
-
-import java.text.ParseException;
-import java.util.Comparator;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Collections;
-import java.util.concurrent.RejectedExecutionHandler;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.solr.common.SolrException.ErrorCode.BAD_REQUEST;
+import static org.apache.solr.common.SolrException.ErrorCode.SERVER_ERROR;
+
 /**
  * <p>
  * Update Processor Factory for managing automatic "expiration" of documents.
@@ -404,7 +400,7 @@ public final class DocExpirationUpdateProcessorFactory
           try {
             DeleteUpdateCommand del = new DeleteUpdateCommand(req);
             del.setQuery("{!cache=false}" + expireField + ":[* TO " +
-                         DateFormatUtil.formatExternal(SolrRequestInfo.getRequestInfo().getNOW())
+                SolrRequestInfo.getRequestInfo().getNOW().toInstant()
                          + "]");
             proc.processDelete(del);
             

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/util/DateFormatUtil.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/DateFormatUtil.java b/solr/core/src/java/org/apache/solr/util/DateFormatUtil.java
deleted file mode 100644
index b4e33be..0000000
--- a/solr/core/src/java/org/apache/solr/util/DateFormatUtil.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.solr.util;
-
-import java.text.DateFormat;
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.text.FieldPosition;
-import java.text.NumberFormat;
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
-
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.util.DateUtil;
-import org.apache.solr.request.SolrQueryRequest;
-
-public final class DateFormatUtil {
-
-  public static final TimeZone UTC = TimeZone.getTimeZone("UTC");
-  /**
-   * Fixed TimeZone (UTC) needed for parsing/formatting Dates in the
-   * canonical representation.
-   */
-  public static final TimeZone CANONICAL_TZ = UTC;
-  /**
-   * Fixed Locale needed for parsing/formatting Milliseconds in the
-   * canonical representation.
-   */
-  public static final Locale CANONICAL_LOCALE = Locale.ROOT;
-  public static final String NOW = "NOW";
-  public static final char Z = 'Z';
-
-  private static final ISO8601CanonicalDateFormat FORMAT_PROTOTYPE = new ISO8601CanonicalDateFormat();
-
-  /**
-   * Thread safe DateFormat that can <b>format</b> in the canonical
-   * ISO8601 date format, not including the trailing "Z" (since it is
-   * left off in the internal indexed values)
-   */
-  public final static ThreadLocal<DateFormat> FORMAT_THREAD_LOCAL = ThreadLocal.withInitial(FORMAT_PROTOTYPE::clone);
-
-  private DateFormatUtil() {}
-
-  /**
-   * Parses a String which may be a date (in the standard format)
-   * followed by an optional math expression.
-   * @param now an optional fixed date to use as "NOW" in the DateMathParser
-   * @param val the string to parse
-   */
-  public static Date parseMath(Date now, String val) {
-    String math;
-    final DateMathParser p = new DateMathParser();
-  
-    if (null != now) p.setNow(now);
-  
-    if (val.startsWith(NOW)) {
-      math = val.substring(NOW.length());
-    } else {
-      final int zz = val.indexOf(Z);
-      if (0 < zz) {
-        math = val.substring(zz+1);
-        try {
-          // p.setNow(toObject(val.substring(0,zz)));
-          p.setNow(parseDate(val.substring(0,zz+1)));
-        } catch (ParseException e) {
-          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
-                                  "Invalid Date in Date Math String:'" + val + '\'', e);
-        }
-      } else {
-        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
-                                "Invalid Date String:'" +val+'\'');
-      }
-    }
-  
-    if (null == math || math.equals("")) {
-      return p.getNow();
-    }
-  
-    try {
-      return p.parseMath(math);
-    } catch (ParseException e) {
-      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
-                              "Invalid Date Math String:'" +val+'\'',e);
-    }
-  }
-
-  /**
-   * Return the standard human readable form of the date (with trailing 'Z')
-   */
-  public static String formatExternal(Date d) {
-    return FORMAT_THREAD_LOCAL.get().format(d) + Z;
-  }
-
-  /**
-   * Return the standard human readable form of the date
-   */
-  public static String formatDate(Date d) {
-    return FORMAT_THREAD_LOCAL.get().format(d);
-  }
-
-  /**
-   * Thread safe method that can be used to parse a Date
-   * without the trailing 'Z'
-   */
-  public static Date parseDate(String s) throws ParseException {
-    return FORMAT_THREAD_LOCAL.get().parse(s);
-  }
-  
-  /** Parse a date string in the standard format, or any supported by DateUtil.parseDate */
-  public static Date parseDateLenient(String s, SolrQueryRequest req) throws ParseException {
-    // request could define timezone in the future
-    try {
-      return DateFormatUtil.FORMAT_THREAD_LOCAL.get().parse(s);
-    } catch (Exception e) {
-      return DateUtil.parseDate(s);
-    }
-  }
-
-  /**
-   * Parses a String which may be a date
-   * followed by an optional math expression.
-   * @param now an optional fixed date to use as "NOW" in the DateMathParser
-   * @param val the string to parse
-   */
-  public static Date parseMathLenient(Date now, String val, SolrQueryRequest req) {
-    String math;
-    final DateMathParser p = new DateMathParser();
-
-    if (null != now) p.setNow(now);
-
-    if (val.startsWith(DateFormatUtil.NOW)) {
-      math = val.substring(DateFormatUtil.NOW.length());
-    } else {
-      final int zz = val.indexOf(DateFormatUtil.Z);
-      if (0 < zz) {
-        math = val.substring(zz+1);
-        try {
-          // p.setNow(toObject(val.substring(0,zz)));
-          p.setNow(parseDateLenient(val.substring(0,zz+1), req));
-        } catch (ParseException e) {
-          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
-                                  "Invalid Date in Date Math String: '" + val + '\'', e);
-        }
-      } else {
-        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
-                                "Invalid Date String: '" +val+'\'');
-      }
-    }
-
-    if (null == math || math.equals("")) {
-      return p.getNow();
-    }
-
-    try {
-      return p.parseMath(math);
-    } catch (ParseException e) {
-      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
-                              "Invalid Date Math String: '" +val+'\'',e);
-    }
-  }
-
-  @SuppressWarnings("serial")
-  static class ISO8601CanonicalDateFormat extends SimpleDateFormat {
-    
-    protected NumberFormat millisParser
-        = NumberFormat.getIntegerInstance(CANONICAL_LOCALE);
-  
-    protected NumberFormat millisFormat = new DecimalFormat
-        (".###", new DecimalFormatSymbols(CANONICAL_LOCALE));
-  
-    public ISO8601CanonicalDateFormat() {
-      super("yyyy-MM-dd'T'HH:mm:ss", CANONICAL_LOCALE);
-      this.setTimeZone(CANONICAL_TZ);
-    }
-  
-    @Override
-    public Date parse(String i, ParsePosition p) {
-      /* delegate to SimpleDateFormat for easy stuff */
-      Date d = super.parse(i, p);
-      int milliIndex = p.getIndex();
-      /* worry about the milliseconds ourselves */
-      if (null != d &&
-          -1 == p.getErrorIndex() &&
-          milliIndex + 1 < i.length() &&
-          '.' == i.charAt(milliIndex)) {
-        p.setIndex(++milliIndex); // NOTE: ++ to chomp '.'
-        Number millis = millisParser.parse(i, p);
-        if (-1 == p.getErrorIndex()) {
-          int endIndex = p.getIndex();
-          d = new Date(d.getTime()
-              + (long)(millis.doubleValue() * Math.pow(10, (3 - endIndex + milliIndex))));
-        }
-      }
-      return d;
-    }
-  
-    @Override
-    public StringBuffer format(Date d, StringBuffer toAppendTo, FieldPosition pos) {
-      /* delegate to SimpleDateFormat for easy stuff */
-      super.format(d, toAppendTo, pos);
-      /* worry about the milliseconds ourselves */
-      long millis = d.getTime() % 1000l;
-      if (0L == millis) {
-        return toAppendTo;
-      }
-      if (millis < 0L) {
-        // original date was prior to epoch
-        millis += 1000L;
-      }
-      int posBegin = toAppendTo.length();
-      toAppendTo.append(millisFormat.format(millis / 1000d));
-      if (DateFormat.MILLISECOND_FIELD == pos.getField()) {
-        pos.setBeginIndex(posBegin);
-        pos.setEndIndex(toAppendTo.length());
-      }
-      return toAppendTo;
-    }
-  
-    @Override
-    public DateFormat clone() {
-      ISO8601CanonicalDateFormat c = (ISO8601CanonicalDateFormat)super.clone();
-      c.millisParser = NumberFormat.getIntegerInstance(CANONICAL_LOCALE);
-      c.millisFormat = new DecimalFormat(".###", new DecimalFormatSymbols(CANONICAL_LOCALE));
-      return c;
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/java/org/apache/solr/util/DateMathParser.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/DateMathParser.java b/solr/core/src/java/org/apache/solr/util/DateMathParser.java
index 9e750dc..489a5aa 100644
--- a/solr/core/src/java/org/apache/solr/util/DateMathParser.java
+++ b/solr/core/src/java/org/apache/solr/util/DateMathParser.java
@@ -16,18 +16,23 @@
  */
 package org.apache.solr.util;
 
-import org.apache.solr.request.SolrRequestInfo;
-import org.apache.solr.common.params.CommonParams; //jdoc
-
-import java.util.Date;
+import java.text.ParseException;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DateTimeParseException;
 import java.util.Calendar;
-import java.util.TimeZone;
+import java.util.Date;
+import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
-import java.util.HashMap;
-import java.text.ParseException;
+import java.util.TimeZone;
 import java.util.regex.Pattern;
 
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.request.SolrRequestInfo;
+
 /**
  * A Simple Utility class for parsing "math" like strings relating to Dates.
  *
@@ -92,15 +97,23 @@ import java.util.regex.Pattern;
  * @see SolrRequestInfo#getNOW
  */
 public class DateMathParser  {
-  
-  public static TimeZone UTC = TimeZone.getTimeZone("UTC");
+
+  public static final TimeZone UTC = TimeZone.getTimeZone("UTC");
 
   /** Default TimeZone for DateMath rounding (UTC) */
   public static final TimeZone DEFAULT_MATH_TZ = UTC;
+
   /** Default Locale for DateMath rounding (Locale.ROOT) */
   public static final Locale DEFAULT_MATH_LOCALE = Locale.ROOT;
 
   /**
+   * Differs by {@link DateTimeFormatter#ISO_INSTANT} in that it's lenient.
+   * @see #parseNoMath(String)
+   */
+  public static final DateTimeFormatter PARSER = new DateTimeFormatterBuilder()
+      .parseCaseInsensitive().parseLenient().appendInstant().toFormatter(Locale.ROOT);
+
+  /**
    * A mapping from (uppercased) String labels idenyifying time units,
    * to the corresponding Calendar constant used to set/add/roll that unit
    * of measurement.
@@ -115,6 +128,7 @@ public class DateMathParser  {
    */
   public static final Map<String,Integer> CALENDAR_UNITS = makeUnitsMap();
 
+
   /** @see #CALENDAR_UNITS */
   private static Map<String,Integer> makeUnitsMap() {
 
@@ -213,7 +227,60 @@ public class DateMathParser  {
 
   }
 
-  
+  /**
+   * Parses a String which may be a date (in the standard ISO-8601 format)
+   * followed by an optional math expression.
+   * @param now an optional fixed date to use as "NOW"
+   * @param val the string to parse
+   */
+  public static Date parseMath(Date now, String val) {
+    String math;
+    final DateMathParser p = new DateMathParser();
+
+    if (null != now) p.setNow(now);
+
+    if (val.startsWith("NOW")) {
+      math = val.substring("NOW".length());
+    } else {
+      final int zz = val.indexOf('Z');
+      if (zz == -1) {
+        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+            "Invalid Date String:'" + val + '\'');
+      }
+      math = val.substring(zz+1);
+      try {
+        p.setNow(parseNoMath(val.substring(0, zz + 1)));
+      } catch (DateTimeParseException e) {
+        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+            "Invalid Date in Date Math String:'" + val + '\'', e);
+      }
+    }
+
+    if (null == math || math.equals("")) {
+      return p.getNow();
+    }
+
+    try {
+      return p.parseMath(math);
+    } catch (ParseException e) {
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+          "Invalid Date Math String:'" +val+'\'',e);
+    }
+  }
+
+  /**
+   * Parsing Solr dates <b>without DateMath</b>.
+   * This is the standard/pervasive ISO-8601 UTC format but is configured with some leniency.
+   *
+   * Callers should almost always call {@link #parseMath(Date, String)} instead.
+   *
+   * @throws DateTimeParseException if it can't parse
+   */
+  private static Date parseNoMath(String val) {
+    //TODO write the equivalent of a Date::from; avoids Instant -> Date
+    return new Date(PARSER.parse(val, Instant::from).toEpochMilli());
+  }
+
   private TimeZone zone;
   private Locale loc;
   private Date now;
@@ -227,7 +294,6 @@ public class DateMathParser  {
    */
   public DateMathParser() {
     this(null, DEFAULT_MATH_LOCALE);
-    
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java b/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java
index 25ea2c5..9d45a0d 100644
--- a/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java
+++ b/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java
@@ -16,6 +16,8 @@
  */
 package org.apache.solr;
 
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.StringWriter;
@@ -24,8 +26,6 @@ import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
@@ -874,18 +874,19 @@ public class BasicFunctionalityTest extends SolrTestCaseJ4 {
 
   }
 
-  public void testDateRoundtrip() {
-    assertU(adoc("id", "99",  "bday", "99-01-01T12:34:56.789Z"));
-    assertU(commit());
-    assertQ("year should be canonicallized to 4 digits",
-            req("q", "id:99"),
-            "//date[@name='bday'][.='0099-01-01T12:34:56.789Z']");
-    assertU(adoc("id", "99",  "bday", "1999-01-01T12:34:56.900Z"));
-    assertU(commit());
-    assertQ("millis should be canonicallized to no trailing zeros",
-            req("q", "id:99"),
-            "//date[@name='bday'][.='1999-01-01T12:34:56.9Z']");
-  }
+  // commented after SOLR-8904; both are false
+//  public void testDateRoundtrip() {
+//    assertU(adoc("id", "99",  "bday", "99-01-01T12:34:56.789Z"));
+//    assertU(commit());
+//    assertQ("year should be canonicallized to 4 digits",
+//            req("q", "id:99"),
+//            "//date[@name='bday'][.='0099-01-01T12:34:56.789Z']");
+//    assertU(adoc("id", "99",  "bday", "1999-01-01T12:34:56.900Z"));
+//    assertU(commit());
+//    assertQ("millis should be canonicallized to no trailing zeros",
+//            req("q", "id:99"),
+//            "//date[@name='bday'][.='1999-01-01T12:34:56.9Z']");
+//  }
   
   @Test
   public void testPatternReplaceFilter() {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/test/org/apache/solr/TestTrie.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/TestTrie.java b/solr/core/src/test/org/apache/solr/TestTrie.java
index 0c1497f..07935b2 100644
--- a/solr/core/src/test/org/apache/solr/TestTrie.java
+++ b/solr/core/src/test/org/apache/solr/TestTrie.java
@@ -16,19 +16,18 @@
  */
 package org.apache.solr;
 
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+import java.util.TimeZone;
+
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.schema.FieldType;
 import org.apache.solr.schema.TrieField;
 import org.apache.solr.util.DateMathParser;
-import org.apache.solr.util.DateFormatUtil;
 import org.junit.After;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import java.text.SimpleDateFormat;
-import java.util.Locale;
-import java.util.TimeZone;
-
 /**
  * Tests for TrieField functionality
  *
@@ -173,7 +172,7 @@ public class TestTrie extends SolrTestCaseJ4 {
     format.setTimeZone(TimeZone.getTimeZone("UTC"));
 
     assertU(delQ("*:*"));
-    DateMathParser dmp = new DateMathParser(DateFormatUtil.UTC, Locale.ROOT);
+    DateMathParser dmp = new DateMathParser(DateMathParser.UTC, Locale.ROOT);
     String largestDate = "";
     for (int i = 0; i < 10; i++) {
       // index 10 days starting with today
@@ -222,7 +221,7 @@ public class TestTrie extends SolrTestCaseJ4 {
     // For tdate tests
     SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
     format.setTimeZone(TimeZone.getTimeZone("UTC"));
-    DateMathParser dmp = new DateMathParser(DateFormatUtil.UTC, Locale.ROOT);
+    DateMathParser dmp = new DateMathParser(DateMathParser.UTC, Locale.ROOT);
 
     for (int i = 0; i < 10; i++) {
       long l = Integer.MAX_VALUE + i*1L;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/test/org/apache/solr/cloud/SegmentTerminateEarlyTestState.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/SegmentTerminateEarlyTestState.java b/solr/core/src/test/org/apache/solr/cloud/SegmentTerminateEarlyTestState.java
index e7de4d1..199423b 100644
--- a/solr/core/src/test/org/apache/solr/cloud/SegmentTerminateEarlyTestState.java
+++ b/solr/core/src/test/org/apache/solr/cloud/SegmentTerminateEarlyTestState.java
@@ -17,6 +17,8 @@
 
 package org.apache.solr.cloud;
 
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -54,7 +56,7 @@ class SegmentTerminateEarlyTestState {
         final Integer docKey = new Integer(numDocs);
         SolrInputDocument doc = new SolrInputDocument();
         doc.setField(keyField, ""+docKey);
-        final int MM = TestMiniSolrCloudCluster.random().nextInt(60);
+        final int MM = TestMiniSolrCloudCluster.random().nextInt(60); // minutes
         if (minTimestampMM == null || MM <= minTimestampMM.intValue()) {
           if (minTimestampMM != null && MM < minTimestampMM.intValue()) {
             minTimestampDocKeys.clear();
@@ -69,7 +71,7 @@ class SegmentTerminateEarlyTestState {
           maxTimestampMM = new Integer(MM);
           maxTimestampDocKeys.add(docKey);
         }
-        doc.setField(timestampField, "2016-01-01T00:"+MM+":00Z");
+        doc.setField(timestampField, ZonedDateTime.of(2016, 1, 1, 0, MM, 0, 0, ZoneOffset.UTC).toInstant().toString());
         doc.setField(oddField, ""+(numDocs % 2));
         doc.setField(quadField, ""+(numDocs % 4)+1);
         cloudSolrClient.add(doc);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/test/org/apache/solr/cloud/TestCloudPivotFacet.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestCloudPivotFacet.java b/solr/core/src/test/org/apache/solr/cloud/TestCloudPivotFacet.java
index 833cadd..dc7e0b0 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestCloudPivotFacet.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestCloudPivotFacet.java
@@ -16,6 +16,16 @@
  */
 package org.apache.solr.cloud;
 
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 import org.apache.commons.lang.StringUtils;
 import org.apache.lucene.util.TestUtil;
 import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
@@ -29,22 +39,11 @@ import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.params.StatsParams;
 import org.apache.solr.common.util.NamedList;
-import org.apache.solr.util.DateFormatUtil;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
-import java.lang.invoke.MethodHandles;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 import static org.apache.solr.common.params.FacetParams.FACET;
 import static org.apache.solr.common.params.FacetParams.FACET_LIMIT;
 import static org.apache.solr.common.params.FacetParams.FACET_MISSING;
@@ -474,7 +473,7 @@ public class TestCloudPivotFacet extends AbstractFullDistribZkTestBase {
     // otherwise, build up a term filter...
     String prefix = "{!term f=" + constraint.getField() + "}";
     if (value instanceof Date) {
-      return prefix + DateFormatUtil.formatExternal((Date)value);
+      return prefix + ((Date) value).toInstant();
     } else {
       return prefix + value;
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/a47a0baa/solr/core/src/test/org/apache/solr/handler/component/DistributedFacetPivotLargeTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/component/DistributedFacetPivotLargeTest.java b/solr/core/src/test/org/apache/solr/handler/component/DistributedFacetPivotLargeTest.java
index 176b57f..0fa4e8c 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/DistributedFacetPivotLargeTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/DistributedFacetPivotLargeTest.java
@@ -834,6 +834,7 @@ public class DistributedFacetPivotLargeTest extends BaseDistributedSearchTestCas
 
       rfc = pf.getFacetRanges().get(0).getCounts();
       for (RangeFacet.Count c : rfc) {
+
         assertEquals(0, c.getCount()); // no docs in our ranges for this pivot drill down
       }
 
@@ -927,7 +928,7 @@ public class DistributedFacetPivotLargeTest extends BaseDistributedSearchTestCas
     addPivotDoc(oneShard, "id", getDocNum(), "place_s", "cardiff", "company_t", "microsoft polecat","pay_i",5824,"hiredate_dt", "2012-11-01T12:30:00Z");
     addPivotDoc(oneShard, "id", getDocNum(), "place_s", "cardiff", "company_t", "microsoft ","pay_i",6539,"hiredate_dt", "2012-11-01T12:30:00Z"); 
     addPivotDoc(oneShard, "id", getDocNum(), "place_s", "medical staffing network holdings, inc.", "company_t", "microsoft ","pay_i",6539,"hiredate_dt", "2012-11-01T12:30:00Z", "special_s", "xxx");
-    addPivotDoc(oneShard, "id", getDocNum(), "place_s", "cardiff", "company_t", "polecat","pay_i",4352,"hiredate_dt", "2012-1-01T12:30:00Z", "special_s", "xxx"); 
+    addPivotDoc(oneShard, "id", getDocNum(), "place_s", "cardiff", "company_t", "polecat","pay_i",4352,"hiredate_dt", "2012-01-01T12:30:00Z", "special_s", "xxx");
     addPivotDoc(oneShard, "id", getDocNum(), "place_s", "krakaw", "company_t", "polecat","pay_i",4352,"hiredate_dt", "2012-11-01T12:30:00Z", "special_s", SPECIAL); 
     
     addPivotDoc(twoShard, "id", getDocNum(), "place_s", "cardiff", "company_t", "microsoft","pay_i",12,"hiredate_dt", "2012-11-01T12:30:00Z", "special_s", SPECIAL);