Lucene.Net.QueryParser: Fixed several issues with the date range parsing 1) 
Reverted to the behavior of Lucene 3.0.3, which uses strict parsing for Lucene 
3x and higher. 2) Changed to use TryParseExact rather than relying on 
exceptions to be thrown 3) Fixed the default culture on StandardQueryParser. 4) 
Changed the implementations to append the time zone to the date.


Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/7cd1179a
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/7cd1179a
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/7cd1179a

Branch: refs/heads/api-work
Commit: 7cd1179aa95c8a49ce283d462f59e74b31132ffa
Parents: ee04a8c
Author: Shad Storhaug <[email protected]>
Authored: Tue Mar 7 20:03:02 2017 +0700
Committer: Shad Storhaug <[email protected]>
Committed: Tue Mar 7 20:03:02 2017 +0700

----------------------------------------------------------------------
 .../Classic/QueryParserBase.cs                  | 72 ++++++++++----------
 .../Config/StandardQueryConfigHandler.cs        |  2 +-
 .../Processors/TermRangeQueryNodeProcessor.cs   | 19 +++---
 .../Util/QueryParserTestBase.cs                 | 16 ++---
 4 files changed, 52 insertions(+), 57 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7cd1179a/src/Lucene.Net.QueryParser/Classic/QueryParserBase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Classic/QueryParserBase.cs 
b/src/Lucene.Net.QueryParser/Classic/QueryParserBase.cs
index 0ec2a54..0fed97f 100644
--- a/src/Lucene.Net.QueryParser/Classic/QueryParserBase.cs
+++ b/src/Lucene.Net.QueryParser/Classic/QueryParserBase.cs
@@ -52,7 +52,7 @@ namespace Lucene.Net.QueryParsers.Classic
         /// <summary>
         /// Do not catch this exception in your code, it means you are using 
methods that you should no longer use.
         /// </summary>
-        public class MethodRemovedUseAnother : Exception {}
+        public class MethodRemovedUseAnother : Exception { }
 
         protected const int CONJ_NONE = 0;
         protected const int CONJ_AND = 1;
@@ -65,7 +65,7 @@ namespace Lucene.Net.QueryParsers.Classic
 
         // make it possible to call setDefaultOperator() without accessing
         // the nested class:
-        
+
         /// <summary>
         /// Alternative form of <see cref="Operator.AND"/> 
         /// </summary>
@@ -81,15 +81,10 @@ namespace Lucene.Net.QueryParsers.Classic
         //Operator operator_Renamed = OR_OPERATOR;
 
 
-        
-
         //bool lowercaseExpandedTerms = true;
         //MultiTermQuery.RewriteMethod multiTermRewriteMethod = 
MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT;
         //bool allowLeadingWildcard = false;
 
-        // LUCENENET-423 - DateRange differences with Java and .NET
-        private bool _useJavaStyleDateRangeParsing = false;
-
         protected string m_field;
         //int phraseSlop = 0;
         //float fuzzyMinSim = FuzzyQuery.DefaultMinSimilarity;
@@ -98,7 +93,7 @@ namespace Lucene.Net.QueryParsers.Classic
         //TimeZoneInfo timeZone = TimeZoneInfo.Local;
 
         // TODO: Work out what the default date resolution SHOULD be (was null 
in Java, which isn't valid for an enum type)
-        
+
         /// <summary>
         /// the default date resolution
         /// </summary>
@@ -450,51 +445,54 @@ namespace Lucene.Net.QueryParsers.Classic
                 part2 = part2 == null ? null : Locale.TextInfo.ToLower(part2);
             }
 
-            try
+            string shortDateFormat = Locale.DateTimeFormat.ShortDatePattern;
+            DateTime d1;
+            DateTime d2 = DateTime.MaxValue; // We really don't care what we 
set this to, but we need something or the compiler will complain below
+            DateTools.Resolution resolution = GetDateResolution(field);
+
+            // LUCENENET specific: This doesn't emulate java perfectly.
+            // See LUCENENET-423 - DateRange differences with Java and .NET
+
+            // Java allows parsing of the string up to the end of the pattern
+            // and then ignores everything else.  .NET will throw an 
exception, 
+            // so this will fail in those cases, though the code below is clear
+            // that users can only specify the date, not the time. 
Unfortunately,
+            // the date format is much more strict in .NET.
+
+            // To emulate Java more precisely, it is possible to make a custom 
format
+            // by calling 
Locale.DateTimeFormat.SetAllDateTimePatterns(string[], char)
+            // that contains all of the formats that you need to support and 
setting
+            // the Locale.DateTimeFormat.ShortDatePattern to be the same as 
the second
+            // parameter of SetAllDateTimePatterns.
+
+            // LUCENENET TODO: Try to make setting custom formats easier by 
adding
+            // another configuration setting (IList<string> of date formats).
+            // Also consider making a IsStrictDateFormat setting which allows 
toggling
+            // to DateTime.TryParse(part1, Locale, DateTimeStyles.None, out 
d1);
+            // rather than TryParseExact
+
+            if (DateTime.TryParseExact(part1, shortDateFormat, Locale, 
DateTimeStyles.None, out d1))
             {
-                DateTime d1, d2;
-                if (_useJavaStyleDateRangeParsing)
-                {
-                    // LUCENENET TODO: This doesn't emulate java perfectly.
-                    // Java allows parsing of the string up to the end of the 
pattern
-                    // and then ignores everything else.  .NET will throw an 
exception, 
-                    // so this will fail in those cases, though the code below 
is clear
-                    // that users can only specify the date, not the time.
-                    var shortFormat = Locale.DateTimeFormat.ShortDatePattern;
-                    d1 = DateTime.ParseExact(part1, shortFormat, Locale);
-                    d2 = DateTime.ParseExact(part2, shortFormat, Locale);
-                }
-                else
-                {
-                    d1 = DateTime.Parse(part1, Locale);
-                    d2 = DateTime.Parse(part2, Locale);
-                }
+                part1 = DateTools.DateToString(d1, resolution);
+            }
 
+            if (DateTime.TryParseExact(part2, shortDateFormat, Locale, 
DateTimeStyles.None, out d2))
+            {
                 if (endInclusive)
                 {
                     // 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:
 
-                    // LUCENENET TODO: Try to work out if the Time Zone is 
pertinent here or
-                    // whether it should just be removed from the API entirely.
-                    // In Java:
-                    // Calendar cal = Calendar.getInstance(timeZone, locale);
-                    
+                    d2 = TimeZoneInfo.ConvertTime(d2, TimeZone);
                     var cal = Locale.Calendar;
                     d2 = cal.AddHours(d2, 23);
                     d2 = cal.AddMinutes(d2, 59);
                     d2 = cal.AddSeconds(d2, 59);
                     d2 = cal.AddMilliseconds(d2, 999);
                 }
-                DateTools.Resolution resolution = GetDateResolution(field);
 
-                part1 = DateTools.DateToString(d1, resolution);
                 part2 = DateTools.DateToString(d2, resolution);
-
-            }
-            catch (Exception)
-            {
             }
 
             return NewRangeQuery(field, part1, part2, startInclusive, 
endInclusive);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7cd1179a/src/Lucene.Net.QueryParser/Flexible/Standard/Config/StandardQueryConfigHandler.cs
----------------------------------------------------------------------
diff --git 
a/src/Lucene.Net.QueryParser/Flexible/Standard/Config/StandardQueryConfigHandler.cs
 
b/src/Lucene.Net.QueryParser/Flexible/Standard/Config/StandardQueryConfigHandler.cs
index db5b39f..e934063 100644
--- 
a/src/Lucene.Net.QueryParser/Flexible/Standard/Config/StandardQueryConfigHandler.cs
+++ 
b/src/Lucene.Net.QueryParser/Flexible/Standard/Config/StandardQueryConfigHandler.cs
@@ -52,7 +52,7 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Config
             Set(ConfigurationKeys.ENABLE_POSITION_INCREMENTS, false); 
//default value 2.4
             Set(ConfigurationKeys.FIELD_BOOST_MAP, new LinkedHashMap<string, 
float?>());
             Set(ConfigurationKeys.FUZZY_CONFIG, new FuzzyConfig());
-            Set(ConfigurationKeys.LOCALE, CultureInfo.InvariantCulture);
+            Set(ConfigurationKeys.LOCALE, CultureInfo.CurrentCulture);
             Set(ConfigurationKeys.MULTI_TERM_REWRITE_METHOD, 
MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT);
             Set(ConfigurationKeys.FIELD_DATE_RESOLUTION_MAP, new 
HashMap<string, DateTools.Resolution?>());
         }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7cd1179a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/TermRangeQueryNodeProcessor.cs
----------------------------------------------------------------------
diff --git 
a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/TermRangeQueryNodeProcessor.cs
 
b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/TermRangeQueryNodeProcessor.cs
index d5eef1a..a44f2e1 100644
--- 
a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/TermRangeQueryNodeProcessor.cs
+++ 
b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/TermRangeQueryNodeProcessor.cs
@@ -61,8 +61,8 @@ namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
                 FieldQueryNode upper = 
(FieldQueryNode)termRangeNode.UpperBound;
                 FieldQueryNode lower = 
(FieldQueryNode)termRangeNode.LowerBound;
 
-                // LUCENENET TODO: Add a NOT_SET value so we have a logical 
default?
-                DateTools.Resolution dateRes = DateTools.Resolution.MINUTE/* = 
null*/;
+                // LUCENENET specific - set to 0 (instead of null), since it 
doesn't correspond to any valid setting
+                DateTools.Resolution dateRes = 0/* = null*/;
                 bool inclusive = false;
                 CultureInfo locale = 
GetQueryConfigHandler().Get(ConfigurationKeys.LOCALE);
 
@@ -104,21 +104,18 @@ namespace 
Lucene.Net.QueryParsers.Flexible.Standard.Processors
 
                 try
                 {
-                    //DateFormat df = 
DateFormat.GetDateInstance(DateFormat.SHORT, locale);
-                    //df.setLenient(true);
+                    string shortDateFormat = 
locale.DateTimeFormat.ShortDatePattern;
+                    DateTime d1;
+                    DateTime d2 = DateTime.MaxValue; // We really don't care 
what we set this to, but we need something or the compiler will complain below
 
-                    if (part1.Length > 0)
+                    if (DateTime.TryParseExact(part1, shortDateFormat, locale, 
DateTimeStyles.None, out d1))
                     {
-                        //DateTime d1 = df.parse(part1);
-                        DateTime d1 = DateTime.Parse(part1, locale);
                         part1 = DateTools.DateToString(d1, dateRes);
                         lower.Text = new StringCharSequenceWrapper(part1);
                     }
 
-                    if (part2.Length > 0)
+                    if (DateTime.TryParseExact(part2, shortDateFormat, locale, 
DateTimeStyles.None, out d2))
                     {
-                        //DateTime d2 = df.parse(part2);
-                        DateTime d2 = DateTime.Parse(part2, locale);
                         if (inclusive)
                         {
                             // The user can only specify the date, not the 
time, so make sure
@@ -133,6 +130,7 @@ namespace 
Lucene.Net.QueryParsers.Flexible.Standard.Processors
                             //cal.set(Calendar.MILLISECOND, 999);
                             //d2 = cal.getTime();
 
+                            d2 = TimeZoneInfo.ConvertTime(d2, timeZone);
                             var cal = locale.Calendar;
                             d2 = cal.AddHours(d2, 23);
                             d2 = cal.AddMinutes(d2, 59);
@@ -143,6 +141,7 @@ namespace 
Lucene.Net.QueryParsers.Flexible.Standard.Processors
                         part2 = DateTools.DateToString(d2, dateRes);
                         upper.Text = new StringCharSequenceWrapper(part2);
                     }
+
                 }
 #pragma warning disable 168
                 catch (Exception e)

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/7cd1179a/src/Lucene.Net.Tests.QueryParser/Util/QueryParserTestBase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Util/QueryParserTestBase.cs 
b/src/Lucene.Net.Tests.QueryParser/Util/QueryParserTestBase.cs
index ffffc76..a548554 100644
--- a/src/Lucene.Net.Tests.QueryParser/Util/QueryParserTestBase.cs
+++ b/src/Lucene.Net.Tests.QueryParser/Util/QueryParserTestBase.cs
@@ -647,13 +647,9 @@ namespace Lucene.Net.QueryParsers.Util
         /// <summary>for testing DateTools support</summary>
         private string GetDate(string s, DateTools.Resolution resolution)
         {
-            // TODO: Is this the correct way to parse the string?
-            DateTime d = DateTime.Parse(s, 
System.Globalization.CultureInfo.InvariantCulture);
-            return GetDate(d, resolution);
-
-            //// we use the default Locale since LuceneTestCase randomizes it
-            //DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, 
Locale.getDefault());
-            //return GetDate(df.Parse(s), resolution);      
+            // we use the default Locale since LuceneTestCase randomizes it
+            DateTime d = DateTime.ParseExact(s, 
CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern, 
CultureInfo.CurrentCulture);
+            return GetDate(d, resolution);   
         }
 
         /// <summary>for testing DateTools support</summary>
@@ -664,8 +660,10 @@ namespace Lucene.Net.QueryParsers.Util
 
         private string GetLocalizedDate(int year, int month, int day)
         {
-            DateTime d = new DateTime(year, month, day, 23, 59, 59, 999);
-            return d.ToString("d");
+            // we use the default Locale/TZ since LuceneTestCase randomizes it
+            DateTime date = new GregorianCalendar().ToDateTime(year, month, 
day, 23, 59, 59, 999);
+            date = TimeZoneInfo.ConvertTime(date, TimeZoneInfo.Local);
+            return date.ToString("d");
 
             //// we use the default Locale/TZ since LuceneTestCase randomizes 
it
             //DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, 
Locale.getDefault());

Reply via email to