mirror of https://github.com/apache/lucene.git
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.
This commit is contained in:
parent
34180ad5c3
commit
94c04237cc
|
@ -176,6 +176,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
|
||||
----------------------
|
||||
|
||||
|
@ -514,6 +518,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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()+")";
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -14,11 +14,13 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.solr.common.util;
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormat;
|
||||
package org.apache.solr.handler.extraction;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
|
@ -32,7 +34,7 @@ import java.util.TimeZone;
|
|||
/**
|
||||
* This class has some code from HttpClient DateUtil.
|
||||
*/
|
||||
public class DateUtil {
|
||||
public class ExtractionDateUtil {
|
||||
//start HttpClient
|
||||
/**
|
||||
* Date format pattern used to parse HTTP date headers in RFC 1123 format.
|
||||
|
@ -67,6 +69,12 @@ public class DateUtil {
|
|||
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Differs by {@link DateTimeFormatter#ISO_INSTANT} in that it's lenient.
|
||||
*/
|
||||
public static final DateTimeFormatter ISO_8601_PARSER = new DateTimeFormatterBuilder()
|
||||
.parseCaseInsensitive().parseLenient().appendInstant().toFormatter(Locale.ROOT);
|
||||
|
||||
/**
|
||||
* A suite of default date formats that can be parsed, and thus transformed to the Solr specific format
|
||||
*/
|
||||
|
@ -95,9 +103,12 @@ public class DateUtil {
|
|||
}
|
||||
|
||||
public static Date parseDate(String d, Collection<String> fmts) throws ParseException {
|
||||
// 2007-04-26T08:05:04Z
|
||||
if (d.endsWith("Z") && d.length() > 20) {
|
||||
return getThreadLocalDateFormat().parse(d);
|
||||
if (d.length() > 0 && d.charAt(d.length() - 1) == 'Z') {
|
||||
try {
|
||||
return new Date(ISO_8601_PARSER.parse(d, Instant::from).toEpochMilli());
|
||||
} catch (Exception e) {
|
||||
//ignore; perhaps we can parse with one of the formats below...
|
||||
}
|
||||
}
|
||||
return parseDate(d, fmts, null);
|
||||
}
|
||||
|
@ -140,6 +151,7 @@ public class DateUtil {
|
|||
dateValue = dateValue.substring(1, dateValue.length() - 1);
|
||||
}
|
||||
|
||||
//TODO upgrade to Java 8 DateTimeFormatter. But how to deal with the GMT as a default?
|
||||
SimpleDateFormat dateParser = null;
|
||||
Iterator formatIter = dateFormats.iterator();
|
||||
|
||||
|
@ -163,97 +175,4 @@ public class DateUtil {
|
|||
throw new ParseException("Unable to parse the date " + dateValue, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a formatter that can be use by the current thread if needed to
|
||||
* convert Date objects to the Internal representation.
|
||||
*
|
||||
* @return The {@link java.text.DateFormat} for the current thread
|
||||
*/
|
||||
public static DateFormat getThreadLocalDateFormat() {
|
||||
return fmtThreadLocal.get();
|
||||
}
|
||||
|
||||
public static TimeZone UTC = TimeZone.getTimeZone("UTC");
|
||||
private static ThreadLocalDateFormat fmtThreadLocal = new ThreadLocalDateFormat();
|
||||
|
||||
private static class ThreadLocalDateFormat extends ThreadLocal<DateFormat> {
|
||||
DateFormat proto;
|
||||
|
||||
public ThreadLocalDateFormat() {
|
||||
super();
|
||||
//2007-04-26T08:05:04Z
|
||||
SimpleDateFormat tmp = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT);
|
||||
tmp.setTimeZone(UTC);
|
||||
proto = tmp;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DateFormat initialValue() {
|
||||
return (DateFormat) proto.clone();
|
||||
}
|
||||
}
|
||||
|
||||
/** Formats the date and returns the calendar instance that was used (which may be reused) */
|
||||
public static Calendar formatDate(Date date, Calendar cal, Appendable out) throws IOException {
|
||||
// using a stringBuilder for numbers can be nice since
|
||||
// a temporary string isn't used (it's added directly to the
|
||||
// builder's buffer.
|
||||
|
||||
StringBuilder sb = out instanceof StringBuilder ? (StringBuilder)out : new StringBuilder();
|
||||
if (cal==null) cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"), Locale.ROOT);
|
||||
cal.setTime(date);
|
||||
|
||||
int i = cal.get(Calendar.YEAR);
|
||||
sb.append(i);
|
||||
sb.append('-');
|
||||
i = cal.get(Calendar.MONTH) + 1; // 0 based, so add 1
|
||||
if (i<10) sb.append('0');
|
||||
sb.append(i);
|
||||
sb.append('-');
|
||||
i=cal.get(Calendar.DAY_OF_MONTH);
|
||||
if (i<10) sb.append('0');
|
||||
sb.append(i);
|
||||
sb.append('T');
|
||||
i=cal.get(Calendar.HOUR_OF_DAY); // 24 hour time format
|
||||
if (i<10) sb.append('0');
|
||||
sb.append(i);
|
||||
sb.append(':');
|
||||
i=cal.get(Calendar.MINUTE);
|
||||
if (i<10) sb.append('0');
|
||||
sb.append(i);
|
||||
sb.append(':');
|
||||
i=cal.get(Calendar.SECOND);
|
||||
if (i<10) sb.append('0');
|
||||
sb.append(i);
|
||||
i=cal.get(Calendar.MILLISECOND);
|
||||
if (i != 0) {
|
||||
sb.append('.');
|
||||
if (i<100) sb.append('0');
|
||||
if (i<10) sb.append('0');
|
||||
sb.append(i);
|
||||
|
||||
// handle canonical format specifying fractional
|
||||
// seconds shall not end in '0'. Given the slowness of
|
||||
// integer div/mod, simply checking the last character
|
||||
// is probably the fastest way to check.
|
||||
int lastIdx = sb.length()-1;
|
||||
if (sb.charAt(lastIdx)=='0') {
|
||||
lastIdx--;
|
||||
if (sb.charAt(lastIdx)=='0') {
|
||||
lastIdx--;
|
||||
}
|
||||
sb.setLength(lastIdx+1);
|
||||
}
|
||||
|
||||
}
|
||||
sb.append('Z');
|
||||
|
||||
if (out != sb)
|
||||
out.append(sb);
|
||||
|
||||
return cal;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -15,16 +15,6 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.solr.core;
|
||||
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;
|
||||
|
@ -32,6 +22,16 @@ 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.plugin.NamedListInitializedPlugin;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
|
|
|
@ -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 "";
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatValue(Date val) {
|
||||
return DateFormatUtil.formatExternal(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Date parseVal(String rawval) {
|
||||
return ((DateRangeField) field.getType()).parseMath(now, rawval);
|
||||
return DateMathParser.parseMath(now, rawval);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -18,46 +18,42 @@ package org.apache.solr.update.processor;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
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.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.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.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 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.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.DefaultSolrThreadFactory;
|
||||
import org.apache.solr.util.plugin.SolrCoreAware;
|
||||
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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,14 +97,22 @@ 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
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 + "'");
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -16,40 +16,7 @@
|
|||
*/
|
||||
package org.apache.solr;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.lucene.util.Constants;
|
||||
import org.apache.lucene.util.TestUtil;
|
||||
import org.apache.solr.client.solrj.SolrClient;
|
||||
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;
|
||||
import org.apache.solr.client.solrj.response.UpdateResponse;
|
||||
import org.apache.solr.common.SolrDocument;
|
||||
import org.apache.solr.common.SolrDocumentList;
|
||||
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;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
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;
|
||||
|
@ -73,6 +40,35 @@ 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;
|
||||
import org.apache.solr.client.solrj.SolrClient;
|
||||
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.HttpSolrClient;
|
||||
import org.apache.solr.client.solrj.request.UpdateRequest;
|
||||
import org.apache.solr.client.solrj.response.QueryResponse;
|
||||
import org.apache.solr.client.solrj.response.UpdateResponse;
|
||||
import org.apache.solr.common.SolrDocument;
|
||||
import org.apache.solr.common.SolrDocumentList;
|
||||
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.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue