fix parsing of dates in range queries that use local date format: include the last day if query is inclusive

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@373355 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Daniel Naber 2006-01-29 20:51:43 +00:00
parent 9db7eaa951
commit 0f19da3c90
4 changed files with 83 additions and 5 deletions

View File

@ -333,6 +333,10 @@ Bug fixes
22. IndexWriter.setMaxBufferedDocs(1) didn't have the expected effect, 22. IndexWriter.setMaxBufferedDocs(1) didn't have the expected effect,
this has now been fixed. (Daniel Naber) this has now been fixed. (Daniel Naber)
23. Fixed QueryParser when called with a date in local form like
"[1/16/2000 TO 1/18/2000]". This query did not include the documents
of 1/18/2000, i.e. the last day was not included. (Daniel Naber)
Optimizations Optimizations
1. Disk usage (peak requirements during indexing and optimization) 1. Disk usage (peak requirements during indexing and optimization)

View File

@ -517,6 +517,18 @@ public class QueryParser implements QueryParserConstants {
df.setLenient(true); df.setLenient(true);
Date d1 = df.parse(part1); Date d1 = df.parse(part1);
Date d2 = df.parse(part2); Date d2 = df.parse(part2);
if (inclusive) {
// The user can only specify the date, not the time, so make sure
// the time is set to the latest possible time of that date to really
// include all documents:
Calendar cal = Calendar.getInstance(locale);
cal.setTime(d2);
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.MILLISECOND, 999);
d2 = cal.getTime();
}
part1 = DateField.dateToString(d1); part1 = DateField.dateToString(d1);
part2 = DateField.dateToString(d2); part2 = DateField.dateToString(d2);
} }

View File

@ -540,6 +540,18 @@ public class QueryParser {
df.setLenient(true); df.setLenient(true);
Date d1 = df.parse(part1); Date d1 = df.parse(part1);
Date d2 = df.parse(part2); Date d2 = df.parse(part2);
if (inclusive) {
// The user can only specify the date, not the time, so make sure
// the time is set to the latest possible time of that date to really
// include all documents:
Calendar cal = Calendar.getInstance(locale);
cal.setTime(d2);
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.MILLISECOND, 999);
d2 = cal.getTime();
}
part1 = DateField.dateToString(d1); part1 = DateField.dateToString(d1);
part2 = DateField.dateToString(d2); part2 = DateField.dateToString(d2);
} }

View File

@ -26,18 +26,26 @@ import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.WhitespaceAnalyzer; import org.apache.lucene.analysis.WhitespaceAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.DateField; import org.apache.lucene.document.DateField;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.FuzzyQuery; import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.PhraseQuery; import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.PrefixQuery; import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.apache.lucene.search.RangeQuery; import org.apache.lucene.search.RangeQuery;
import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.WildcardQuery; import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.store.RAMDirectory;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.text.DateFormat; import java.text.DateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.Locale;
/** /**
* Tests QueryParser. * Tests QueryParser.
@ -342,23 +350,32 @@ public class TestQueryParser extends TestCase {
assertQueryEquals("gack ( bar blar { a TO z}) ", null, "gack (bar blar {a TO z})"); assertQueryEquals("gack ( bar blar { a TO z}) ", null, "gack (bar blar {a TO z})");
} }
public String getDate(String s) throws Exception { private String getDate(String s) throws Exception {
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT); DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
return DateField.dateToString(df.parse(s)); return DateField.dateToString(df.parse(s));
} }
public String getLocalizedDate(int year, int month, int day) { private String getLocalizedDate(int year, int month, int day, boolean extendLastDate) {
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT); DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
calendar.set(year, month, day); calendar.set(year, month, day);
if (extendLastDate) {
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
calendar.set(Calendar.MILLISECOND, 999);
}
return df.format(calendar.getTime()); return df.format(calendar.getTime());
} }
public void testDateRange() throws Exception { public void testDateRange() throws Exception {
String startDate = getLocalizedDate(2002, 1, 1); String startDate = getLocalizedDate(2002, 1, 1, false);
String endDate = getLocalizedDate(2002, 1, 4); String endDate = getLocalizedDate(2002, 1, 4, false);
Calendar endDateExpected = Calendar.getInstance();
endDateExpected.set(2002, 1, 4, 23, 59, 59);
endDateExpected.set(Calendar.MILLISECOND, 999);
assertQueryEquals("[ " + startDate + " TO " + endDate + "]", null, assertQueryEquals("[ " + startDate + " TO " + endDate + "]", null,
"[" + getDate(startDate) + " TO " + getDate(endDate) + "]"); "[" + getDate(startDate) + " TO " + DateField.dateToString(endDateExpected.getTime()) + "]");
assertQueryEquals("{ " + startDate + " " + endDate + " }", null, assertQueryEquals("{ " + startDate + " " + endDate + " }", null,
"{" + getDate(startDate) + " TO " + getDate(endDate) + "}"); "{" + getDate(startDate) + " TO " + getDate(endDate) + "}");
} }
@ -537,6 +554,39 @@ public class TestQueryParser extends TestCase {
assertEquals(query1, query2); assertEquals(query1, query2);
} }
public void testLocalDateFormat() throws IOException, ParseException {
RAMDirectory ramDir = new RAMDirectory();
IndexWriter iw = new IndexWriter(ramDir, new WhitespaceAnalyzer(), true);
addDateDoc("a", 2005, 12, 2, 10, 15, 33, iw);
addDateDoc("b", 2005, 12, 4, 22, 15, 00, iw);
iw.close();
IndexSearcher is = new IndexSearcher(ramDir);
assertHits(1, "[12/1/2005 TO 12/3/2005]", is);
assertHits(2, "[12/1/2005 TO 12/4/2005]", is);
assertHits(1, "[12/3/2005 TO 12/4/2005]", is);
assertHits(1, "{12/1/2005 TO 12/3/2005}", is);
assertHits(1, "{12/1/2005 TO 12/4/2005}", is);
assertHits(0, "{12/3/2005 TO 12/4/2005}", is);
is.close();
}
private void assertHits(int expected, String query, IndexSearcher is) throws ParseException, IOException {
QueryParser qp = new QueryParser("date", new WhitespaceAnalyzer());
qp.setLocale(Locale.ENGLISH);
Query q = qp.parse(query);
Hits hits = is.search(q);
assertEquals(expected, hits.length());
}
private static void addDateDoc(String content, int year, int month,
int day, int hour, int minute, int second, IndexWriter iw) throws IOException {
Document d = new Document();
d.add(new Field("f", content, Field.Store.YES, Field.Index.TOKENIZED));
Calendar cal = Calendar.getInstance();
cal.set(year, month-1, day, hour, minute, second);
d.add(new Field("date", DateField.dateToString(cal.getTime()), Field.Store.YES, Field.Index.UN_TOKENIZED));
iw.addDocument(d);
}
public void tearDown() { public void tearDown() {
BooleanQuery.setMaxClauseCount(originalMaxClauses); BooleanQuery.setMaxClauseCount(originalMaxClauses);